AI for Dev EP.1: ทำให้ AI คุมแอปของเราได้ด้วย MCP
มีให้อ่านในภาษา:

AI for Dev EP.1: ทำให้ AI คุมแอปของเราได้ด้วย MCP

3 June 2026

/

41 mins read

AI

MCP

AIAgent

Developer

SoftwareDevelopment

แชร์:

สวัสดีครับทุกท่าน เป็นอย่างไรกันบ้างครับ? ส่วนผมนั้นก็เรื่อย ๆ เซ็งบ้าง สุขบ้าง แต่ก็ยังคงเดินเอาหน้าไถดินต่อไปเรื่อย ๆ ครับ

วันนี้เราจะมาเริ่มต้นซีรีส์ใหม่ที่ชื่อว่า “AI for Dev” กันนะครับ ในตอนแรกนี้ เราจะมาทำความรู้จักกับเครื่องมือและมาตรฐานที่น่าสนใจมาก ๆ ที่เรียกว่า MCP หรือ Model Context Protocol กันครับ

จริง ๆ หัวข้อนี้เป็นส่วนนึงของหัวข้อที่ผมได้มีโอกาสไปพูดในงาน Agent Camp Bangkok 2026 ที่ผ่านมา หัวข้อ “No Hero Needed: Give AI Agents Hands with Microsoft Foundry, MongoDB, and MCP”

ดูย้อนหลังได้ที่ https://youtu.be/YlzXTZyHrkg

Description

ในวันนั้นผมได้พูดถึงเรื่องการพัฒนา AI Agent ด้วยการไม่ต้องเขียนโค้ดเองทุกอย่าง ใน layer ของ AI Agent แต่ใช้ความสามารถของ Microsoft Foundry Agent Service ช่วยทำให้ส่วนนี้ง่ายขึ้น และใช้ MCP เป็นตัวกลางในการเชื่อมต่อ AI Agent กับแอปของเรา และใช้ MongoDB ในการเก็บข้อมูลทั้งในรูปแบบ document และ vector database เพื่อให้ AI Agent สามารถเข้าถึงข้อมูลแบบ semantic search ได้อย่างมีประสิทธิภาพ


ก่อนจะไปเรื่อง MCP เรามาทำความเข้าใจกันก่อนว่า ถ้าอยากให้ AI ขยับจากแค่ “ตอบคำถาม” ไปสู่ “ลงมือทำ” เราต้องทำยังไงบ้าง?


AI จาก “ตอบคำถาม” ไปสู่ “ลงมือทำ”

ในช่วงแรกของการพัฒนา AI นั้น เรามักจะใช้ AI ในการตอบคำถาม หรือให้ข้อมูลต่าง ๆ เท่านั้น เช่น ถามว่า “ท้องทำไมถึงเป็นสีฟ้า?” หรือ “ใครเป็นนายกคนที่ 21 ของประเทศไทย?” ซึ่ง AI ก็จะตอบกลับมาเป็นข้อความที่มีข้อมูลที่เราต้องการ จากความรู้ที่มีอยู่ในตัวเอง หรือที่เรียกว่า knowledge cutoff

แต่เมื่อเวลาผ่านไป เราก็เริ่มต้องการให้ AI ทำอะไรได้มากกว่านั้น เช่น การสั่งงานต่าง ๆ ในแอปของเรา เช่น “จองตั๋วหนังให้หน่อย” หรือ “ส่งอีเมลหาลูกค้าให้หน่อย” ในกรณีนี้ AI จะต้องทำได้มากกว่าแค่ตอบคำถาม แต่ต้องเชื่อมต่อกับระบบต่าง ๆ ของเรา และทำงานได้จริง ๆ นั่นคือจุดที่เราต้องการให้ AI “ลงมือทำ” ได้

เพื่อให้ AI สามารถทำงานต่าง ๆ ได้ เราจึงมีแนวคิดที่เรียกว่า Function Calling หรือ Tools แนวคิดนี้ช่วยให้ AI เรียกใช้ฟังก์ชัน หรือเครื่องมือต่าง ๆ ที่เรามีอยู่ในแอปของเราได้อย่างง่ายดาย โดยที่เราไม่ต้องเขียนโค้ดเองทุกครั้ง

ถ้าหากเราเปรียบเทียบ Model ที่เราเอามาใช้กับ AI Agent เป็นเหมือนกับสมองของ AI แล้ว Function Calling หรือ Tools ก็จะเป็นเหมือนกับเครื่องมือ หรือค้อน ที่ให้ AI หยิบไปใช้ในการทำงานต่าง ๆ นั่นเอง

Description

ที่เทียบ Model เป็นสมอง ก็เพราะ Model เก่งเรื่องประมวลผลข้อมูลและให้คำตอบ แต่ถ้าอยากให้มันลงมือทำงานได้จริง ก็ต้องมีเครื่องมือหรือฟังก์ชันให้หยิบไปใช้ นั่นก็คือ Function Calling หรือ Tools นั่นเอง

Function Calling / Tools คืออะไร

ก่อนที่เราจะไปถึง MCP เราต้องเข้าใจก่อนว่า AI สามารถ “เรียกใช้เครื่องมือภายนอก” ได้อย่างไร

Function Calling หรือ Tools คือแนวคิดที่ทำให้ AI สามารถเรียกใช้ function หรือ tool ต่าง ๆ ภายนอก model ได้ เช่น การเรียก API, query ฐานข้อมูล, สั่งรันฟังก์ชัน หรือเรียกใช้เครื่องมือต่าง ๆ ที่อยู่ในแอปพลิเคชันของเรา

แต่จุดสำคัญคือ model ไม่ได้เป็นคน execute สิ่งเหล่านั้นเองโดยตรง หน้าที่ของ model คือเลือกว่าควรเรียก tool ใด และควรส่ง input อะไรเข้าไป จากนั้น application หรือ agent runtime ของเราจะเป็นตัวนำคำสั่งนั้นไป execute กับระบบจริง แล้วส่งผลลัพธ์กลับมาให้ model ใช้ตอบผู้ใช้อีกครั้ง

ในปัจจุบัน LLM หลายรายรองรับแนวคิดนี้แล้ว เช่น OpenAI Function Calling / Tools, Anthropic Claude Tool Use และ Google Gemini Function Calling

ตัวอย่าง: AI เรียก API หรือ function ในแอป

สมมติว่าเรามีแอปจองตั๋วหนังที่มี API สำหรับจองตั๋ว, ดึงข้อมูลตารางการฉาย อยู่ เราก็สามารถสร้าง tools ที่เป็น interface สำหรับเรียก API

  • สำหรับจองตั๋วหนัง (book_movie_tool) รับ parameters 4 อย่าง เช่น ID หนัง, เวลา, จำนวนตั๋ว และชื่อผู้จอง
  • สำหรับดึงข้อมูลตารางการฉาย (get_showtimes_tool) รับ parameters 2 อย่าง เช่น ID หนัง และ วันที่

หลังจากนั้น user ก็สามารถบอก AI ว่า “จองตั๋วหนังเรื่อง Toy Story 5 ตอน 2 ทุ่ม ให้หน่อย” แล้ว AI ก็จะรู้ว่ามันควรจะเรียกใช้ tool ที่ชื่อว่า book_movie_tool พร้อมกับ parameters ที่ถูกต้อง เช่น

  • ID หนัง = movie_001
  • เวลา = “2026-06-03T20:00:00+07:00”
  • จำนวนตั๋ว = 2
  • ชื่อผู้จอง = “จิรชัย”
sequenceDiagram
    autonumber

    actor User as User
    participant App as Application / Agent Runtime
    participant LLM as AI Model / LLM
    participant Tool as book_movie_tool
    participant API as Movie Booking API

    User->>App: "จองตั๋วหนังเรื่อง Toy Story 5 ตอน 20:00 ให้หน่อย"
    App->>LLM: ส่ง prompt + รายละเอียด tools ที่ใช้ได้<br/>(book_movie_tool รับ movie, time, tickets, name)

    LLM-->>App: เลือก book_movie_tool<br/>movie="Toy Story 5", time="20:00"<br/>tickets=2, name="จิรชัย"

    App->>App: ตรวจสอบ permission<br/>และ validate input

    App->>Tool: Execute book_movie_tool(movie, time, tickets, name)
    Tool->>API: POST /bookings<br/>{ movie, time, tickets, name }
    API-->>Tool: { booking_id: "BK-001", status: "confirmed" }

    Tool-->>App: Tool result: จองสำเร็จ (BK-001)
    App->>LLM: ส่งผลลัพธ์ของ tool กลับให้ model

    LLM-->>App: สร้างคำตอบสุดท้าย
    App-->>User: "จองตั๋วหนัง Toy Story 5 เวลา 20:00 เรียบร้อยแล้วครับ 🎬"

จะเห็นว่าการสร้างและเรียกใช้ tools นั้นตรงไปตรงมา

graph LR
    User([User]) --> Agent[Agent]
    Agent --> LLM[LLM เลือก tools]
    LLM --> AgentExec[Agent execute tools ตัวนั้น]
    AgentExec --> API[เรียก API]
    API --> APIResponse[API ตอบกลับ]
    APIResponse --> AgentResp[Agent ตอบ User]

ทีนี้ลองมาดูโค้ด TypeScript กันว่าจริง ๆ แล้วแต่ละขั้นตอนทำยังไงบ้าง

1. เขียน function ที่จะให้ AI เรียกใช้

เริ่มจากเขียน function TypeScript ธรรมดา ๆ ตัวนึง รับ parameters เข้ามาแล้วก็ยิงไปเรียก API จริง ตรงนี้ยังไม่เกี่ยวกับ AI นะครับ เป็นแค่ logic ของแอปเราเองล้วน ๆ

async function bookMovie(params: {
  movieId: string
  time: string
  tickets: number
  name: string
}): Promise<{ bookingId: string; status: string }> {
  const response = await fetch('https://api.example.com/bookings', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(params),
  })
  return response.json()
}

2. ทำ tool schema ให้ AI รู้ว่ามีอะไรให้ใช้บ้าง

ทีนี้ก็ถึงเวลาที่จะบอก AI ว่าเรามี tool ตัวนี้อยู่นะ ชื่ออะไร เอาไว้ทำอะไร แล้วก็ต้องการ input แบบไหนบ้าง ส่วนนี้เปรียบเหมือน “เมนู” ที่เรายื่นให้ AI อ่านก่อนตัดสินใจว่าจะหยิบ tool ไหนไปใช้

import type { ChatCompletionTool } from 'openai/resources'

const tools: ChatCompletionTool[] = [
  {
    type: 'function',
    function: {
      name: 'book_movie',
      description: 'จองตั๋วหนัง ใช้เมื่อผู้ใช้ต้องการจองตั๋วหนัง',
      parameters: {
        type: 'object',
        properties: {
          movieId: {
            type: 'string',
            description: 'ID ของหนัง เช่น movie_001',
          },
          time: {
            type: 'string',
            description: 'เวลาที่ต้องการชม ในรูปแบบ ISO 8601 เช่น 2026-06-03T20:00:00+07:00',
          },
          tickets: {
            type: 'number',
            description: 'จำนวนตั๋วที่ต้องการ',
          },
          name: {
            type: 'string',
            description: 'ชื่อผู้จอง',
          },
        },
        required: ['movieId', 'time', 'tickets', 'name'],
      },
    },
  },
]

3. เชื่อมต่อกับ AI แล้วจัดการ tool call

ขั้นสุดท้ายคือส่ง tools แนบไปกับ message แล้วก็คอย handle ตอนที่ AI ตัดสินใจเรียก tool — พอมันเรียกมา เราก็ execute function จริง แล้วส่งผลลัพธ์กลับไปให้ AI เอาไปเรียบเรียงเป็นคำตอบสุดท้ายให้ user อีกที

import OpenAI from 'openai'

const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })

async function chat(userMessage: string): Promise<string> {
  // ส่ง tools ให้ AI รู้ว่ามีเครื่องมืออะไรให้เลือกใช้
  const response = await client.chat.completions.create({
    model: 'gpt-4o',
    messages: [{ role: 'user', content: userMessage }],
    tools,
  })

  const message = response.choices[0].message

  // AI ตอบโดยไม่เรียก tool — return คำตอบตรง ๆ
  if (!message.tool_calls?.length) {
    return message.content ?? ''
  }

  // AI เลือกเรียก tool — execute function จริงแล้วรวบรวม result
  const toolResults = await Promise.all(
    message.tool_calls.map(async (toolCall) => {
      if (toolCall.function.name === 'book_movie') {
        const args = JSON.parse(toolCall.function.arguments)
        const result = await bookMovie(args)
        return {
          tool_call_id: toolCall.id,
          role: 'tool' as const,
          content: JSON.stringify(result),
        }
      }
    }),
  )

  // ส่ง tool result กลับให้ AI เพื่อสร้างคำตอบสุดท้าย
  const final = await client.chat.completions.create({
    model: 'gpt-4o',
    messages: [
      { role: 'user', content: userMessage },
      message,
      ...(toolResults.filter(Boolean) as OpenAI.Chat.ChatCompletionToolMessageParam[]),
    ],
    tools,
  })

  return final.choices[0].message.content ?? ''
}

เมื่อ tools เริ่มเยอะ ปัญหาก็เริ่มแยะ

ในช่วงแรก เราอาจมี tools เพียงไม่กี่ตัว เช่น tool สำหรับจองตั๋วหนัง หรือ tool สำหรับค้นหาข้อมูลบางอย่าง แต่เมื่อระบบเริ่มโตขึ้น จำนวน tools ก็มักจะเพิ่มขึ้นตามไปด้วย ไม่ว่าจะเป็น tool สำหรับจองร้านอาหาร, สั่งของออนไลน์, จัดการปฏิทิน, ค้นหาข้อมูลลูกค้า, เรียกดูสถานะคำสั่งซื้อ หรือเชื่อมต่อกับระบบภายในองค์กรต่าง ๆ

ยิ่งมี tools มากขึ้น การดูแลรักษาก็ยิ่งซับซ้อนขึ้นตามไปด้วย เพราะนอกจากการทำให้แต่ละ tool ใช้งานได้แล้ว เรายังต้องคิดถึงเรื่องมาตรฐานกลาง เช่น input/output format, error handling, authentication, authorization, logging, monitoring และอีกหลายส่วนที่เกี่ยวข้อง

ถ้าไม่มีการจัดการที่ดีตั้งแต่ต้น ปัญหาเหล่านี้อาจค่อย ๆ สะสมจนกลายเป็น ดินพอกหางหมู ในระยะยาว

ลองนึกภาพว่า ถ้าเรามี tools อยู่ 20-30 ตัว ปัญหาที่อาจเจอมีหลายอย่าง เช่น

1. ไม่มีมาตรฐานกลาง

แต่ละ tool อาจถูกพัฒนาโดยคนละทีม ใช้ naming convention ไม่เหมือนกัน มี error format ต่างกัน ใช้วิธี authentication ต่างกัน หรือแม้แต่มีรูปแบบ input/output ที่ไม่สอดคล้องกัน

ผลที่ตามมาคือ การดูแลรักษาและ debug จะยากขึ้นมาก เพราะนักพัฒนาต้องเรียนรู้พฤติกรรมเฉพาะของแต่ละ tool แทนที่จะใช้มาตรฐานเดียวกันทั้งระบบ

2. ใช้ context window มากเกินไป

เวลาที่เราส่ง tools ให้ LLM เลือกใช้ เรามักต้องส่ง schema หรือ definition ของ tools เหล่านั้นไปพร้อมกันด้วย

ถ้ามี tools จำนวนมาก token ส่วนหนึ่งจะถูกใช้ไปกับ tool definitions แทนที่จะเหลือไว้ให้ LLM ใช้ทำงานจริง เช่น ทำความเข้าใจคำถาม วิเคราะห์บริบท หรือสร้างคำตอบที่มีคุณภาพ

นอกจากนี้ เมื่อมี tools ให้เลือกมากเกินไป LLM ก็อาจสับสน เลือก tool ผิด หรือเรียกใช้ tool ที่ไม่เหมาะสมกับงานได้ง่ายขึ้น

3. ผูกติดกับ AI platform ที่ใช้อยู่

แต่ละ AI platform เช่น OpenAI, Anthropic หรือ Google อาจมีรูปแบบการนิยาม tools ที่แตกต่างกัน

ถ้าวันหนึ่งเราต้องการเปลี่ยน LLM หรือรองรับหลาย provider พร้อมกัน เราอาจต้องแปลงหรือเขียน tool definitions ใหม่ให้เข้ากับแต่ละ platform ซึ่งทำให้เกิดงานซ้ำซ้อนและเพิ่มภาระในการดูแลระบบ

4. แต่ละ AI application ต้องสร้าง tools ซ้ำกัน

ในองค์กรหนึ่งอาจมี AI applications หลายตัว เช่น chatbot สำหรับลูกค้า, internal assistant สำหรับพนักงาน, agent สำหรับทีม support หรือ workflow automation สำหรับทีม operation

แต่ละ application อาจต้องเชื่อมต่อกับ service เดิม ๆ เช่น database, CRM, ticketing system หรือ internal API เดียวกัน แต่กลับต้องสร้าง integration หรือ tool definition แยกกันใหม่ในแต่ละระบบ

สุดท้ายแล้ว เราจะเริ่มเจอปัญหาเดิมซ้ำ ๆ คือ service เดิม แต่ integration กระจัดกระจาย ไม่มีมาตรฐานเดียวกัน และยากต่อการ reuse

นี่จึงเป็นจุดที่ทำให้เกิดแนวคิดของ MCP (Model Context Protocol) ขึ้นมา

MCP ถูกออกแบบมาเพื่อเป็น มาตรฐานกลาง สำหรับเชื่อมต่อ AI applications เข้ากับ tools, data sources และ external systems โดยไม่ต้องสร้าง integration แบบเฉพาะทางใหม่ทุกครั้ง ช่วยให้ tools สามารถถูก reuse ได้ง่ายขึ้น มีโครงสร้างที่เป็นมาตรฐานมากขึ้น และลดความซับซ้อนในการดูแลระบบเมื่อจำนวน tools เพิ่มขึ้นในระยะยาว

MCP คืออะไร

MCP ย่อมาจาก Model Context Protocol เป็นมาตรฐานกลางที่ถูกออกแบบมาเพื่อช่วยให้ AI applications สามารถเชื่อมต่อกับ tools, data sources และ external systems ได้อย่างเป็นระบบมากขึ้น

ถ้าเราเปรียบเทียบ LLM เป็นสมองของ AI แล้ว MCP ก็เป็นเหมือนแขนหรือมือ ที่ช่วยให้สมองนั้นสามารถหยิบจับเครื่องมือต่าง ๆ (Function Calling/Tools) มาใช้ในการทำงาน

Description

แต่ถ้าจะเปรียบเทียบให้ตรงมากขึ้น MCP ก็เหมือน USB-C สำหรับ AI และ Tools แทนที่แต่ละ AI application จะต้องสร้าง integration เฉพาะทางเพื่อเชื่อมต่อกับแต่ละ service เองทั้งหมด เราสามารถให้ service เหล่านั้นเปิดความสามารถผ่าน MCP server แล้วให้ AI application ที่รองรับ MCP เชื่อมต่อเข้ามาใช้งานผ่านมาตรฐานเดียวกัน

graph LR
    subgraph Clients["🤖 MCP Clients (AI Apps)"]
        C1[Claude Desktop]
        C2[VS Code / Cursor]
        C3[Custom AI App]
    end

    subgraph Protocol["⚡ MCP Protocol\n(มาตรฐานกลาง)"]
        MCP[MCP Server]
    end

    subgraph Tools["🛠️ Tools / Services"]
        T1[📁 File System]
        T2[🗄️ Database]
        T3[🌐 REST API]
        T4[📅 Calendar]
        T5[📦 Any Service...]
    end

    C1 -->|MCP| MCP
    C2 -->|MCP| MCP
    C3 -->|MCP| MCP

    MCP --> T1
    MCP --> T2
    MCP --> T3
    MCP --> T4
    MCP --> T5

อ่านเพิ่มเติมเกี่ยวกับ MCP ได้จาก official documentation

MCP ทำให้ AI “คุมแอป” ได้อย่างไร

คำว่า “คุมแอป” ในที่นี้ไม่ได้หมายความว่า AI เข้าไปควบคุมระบบของเราแบบไร้ขอบเขต แต่หมายถึง AI เรียกใช้ความสามารถบางอย่างของแอปหรือระบบภายนอกได้ ผ่านinterface ที่เรากำหนดไว้ชัดเจน

ตัวอย่างเช่น ถ้าเรามีระบบโรงหนัง เราอาจเปิดความสามารถบางอย่างผ่าน MCP server เช่น

  • ค้นหารอบฉายของหนังแต่ละเรื่อง
  • ตรวจสอบที่นั่งว่างในแต่ละรอบ
  • จองตั๋วและตรวจสอบสถานะการจอง
  • เปิดเคสแจ้งปัญหาให้ทีม support เวลาลูกค้าจองแล้วติดปัญหา
  • สรุปข้อมูลสมาชิกและแต้มสะสมจากระบบ CRM
  • ดึงข้อมูลจาก database มาช่วยตอบคำถาม

เมื่อ AI application เชื่อมต่อกับ MCP server ได้แล้ว AI ก็จะเห็นว่า system นี้มี tools อะไรให้ใช้งานบ้าง แต่ละ tool ต้องการ input แบบไหน และจะคืน output กลับมาในรูปแบบใด

ภาพรวม flow จะประมาณนี้

graph LR
    User([User]) --> AIApp[AI Application]
    AIApp --> LLM[LLM]
    LLM --> AIApp
    AIApp --> MCPClient[MCP Client]
    MCPClient --> MCPServer[MCP Server]
    MCPServer --> Tool1[Showtime Service]
    MCPServer --> Tool2[Booking Service]
    MCPServer --> Tool3[Member Database]
    Tool1 --> MCPServer
    Tool2 --> MCPServer
    Tool3 --> MCPServer
    MCPServer --> MCPClient
    MCPClient --> AIApp
    AIApp --> User

ในมุมของ developer เราไม่ได้ปล่อยให้ AI ไปเรียก API ตรง ๆ แบบไม่มีการควบคุม แต่เราเป็นคนออกแบบ MCP server ขึ้นมาเพื่อกำหนดว่า AI สามารถทำอะไรได้บ้าง ต้องส่งข้อมูลอะไรเข้ามา และจะได้รับผลลัพธ์แบบไหนกลับไป

พูดอีกแบบคือ MCP server ทำหน้าที่เป็น controlled gateway ระหว่าง AI application กับระบบจริงของเรา

Before/After Architecture

ถ้าระบบโรงหนังของเราไม่มี MCP สถาปัตยกรรมก็มักจะออกมาเป็นแบบนี้ — AI application แต่ละตัวต้องสร้าง tool เอง ต่อ service เอง แล้วก็ดูแล integration เองทั้งหมด

graph LR
    App1[Customer Chatbot] --> ToolA1[Showtime Tool]
    App1 --> ToolB1[Booking Tool]
    App1 --> ToolC1[Member Tool]

    App2[Internal Assistant] --> ToolA2[Showtime Tool]
    App2 --> ToolB2[Booking Tool]
    App2 --> ToolC2[Member Tool]

    ToolA1 --> Showtime[Showtime API]
    ToolA2 --> Showtime
    ToolB1 --> Booking[Booking API]
    ToolB2 --> Booking
    ToolC1 --> Member[Member / Database]
    ToolC2 --> Member

จากภาพ ถึงปลายทางจะเป็นระบบโรงหนังตัวเดียวกัน แต่ AI application แต่ละตัวก็ต้องสร้าง tool กับ integration ของตัวเองซ้ำกันอยู่ดี พอวันไหน API, authentication, error format หรือ business logic เปลี่ยน ก็ต้องไล่ตามไปแก้หลายจุด

แต่พอใช้ MCP เราก็ย้าย logic การต่อ service พวกนี้มารวมไว้ที่ MCP server แล้วให้ AI application หลายตัวต่อเข้ามาใช้ผ่านมาตรฐานเดียวกัน

graph LR
    App1[Customer Chatbot] --> MCP[MCP Server]
    App2[Internal Assistant] --> MCP
    App3[Support Agent] --> MCP

    MCP --> Showtime[Showtime API]
    MCP --> Booking[Booking API]
    MCP --> Member[Member / Database]

ผลลัพธ์ก็คือ integration รวมศูนย์ขึ้น reuse ง่ายขึ้น แล้วก็ลดภาระในการดูแล tool ที่ซ้ำกันในหลาย ๆ app ลงไปเยอะ

โค้ดตัวอย่าง: แบบไม่มี vs มี MCP

ลองมาดูในโค้ดจริง ๆ เลยครับว่าต่างกันยังไงบ้าง

แบบไม่มี MCP — tool อยู่ใน app โดยตรง

ก็คือแบบที่เราทำมาตั้งแต่ต้นนั่นแหละครับ — tool definition, logic, และ handler ทุกอย่างอยู่ใน app เดียวกันหมดเลย พอมีอีก app อยากใช้ tool เดิม ก็ต้องก๊อปโค้ดไปทำใหม่อีกรอบ

graph TD
    User1([👤 User]) --> App1
    User2([👤 User]) --> App2

    subgraph App1["📱 App 1 — Customer Chatbot"]
        LLM1[🧠 LLM]
        Tools1["📋 book_movie schema\n⚙️ bookMovie()"]
        LLM1 -->|เลือก tool| Tools1
    end

    subgraph App2["📱 App 2 — Internal Assistant\n⚠️ ต้องก๊อปมาใหม่ทั้งหมด"]
        LLM2[🧠 LLM]
        Tools2["📋 book_movie schema\n⚙️ bookMovie()"]
        LLM2 -->|เลือก tool| Tools2
    end

    Tools1 -->|execute| API[🎬 Booking API]
    Tools2 -->|execute| API
// tool definition อยู่ใน app — ทุก app ต้องทำซ้ำกัน
const tools: ChatCompletionTool[] = [
  {
    type: 'function',
    function: {
      name: 'book_movie',
      description: 'จองตั๋วหนัง',
      parameters: {
        type: 'object',
        properties: {
          movieId: { type: 'string' },
          time: { type: 'string' },
          tickets: { type: 'number' },
          name: { type: 'string' },
        },
        required: ['movieId', 'time', 'tickets', 'name'],
      },
    },
  },
]

// function จริงก็อยู่ที่นี่ด้วย
async function bookMovie(params: { movieId: string; time: string; tickets: number; name: string }) {
  const res = await fetch('https://api.example.com/bookings', {
    method: 'POST',
    body: JSON.stringify(params),
  })
  return res.json()
}

// handle tool call ใน app เดียวกัน
if (toolCall.function.name === 'book_movie') {
  const args = JSON.parse(toolCall.function.arguments)
  const result = await bookMovie(args)
  // ...
}

แบบมี MCP — แยก tool ออกมาเป็น MCP Server

ด้วย MCP เราก็แยก tool logic ออกมาตั้งเป็น server ต่างหาก AI app ตัวไหนอยากใช้ก็แค่ต่อมาที่ server ตัวนี้ ไม่ต้องก๊อปโค้ดไปใส่ทุก app เลย

graph TD
    User1([👤 User]) --> App1
    User2([👤 User]) --> App2

    subgraph App1["📱 App 1 — Customer Chatbot"]
        LLM1[🧠 LLM]
        Client1[MCP Client]
        LLM1 -->|เลือก tool| Client1
    end

    subgraph App2["📱 App 2 — Internal Assistant"]
        LLM2[🧠 LLM]
        Client2[MCP Client]
        LLM2 -->|เลือก tool| Client2
    end

    Client1 -->|MCP Protocol| MCPServer
    Client2 -->|MCP Protocol| MCPServer

    subgraph MCPServer["🛠️ MCP Server (ที่เดียว — ทุก app ใช้ร่วมกัน)"]
        ToolDef["📋 book_movie schema\n⚙️ bookMovie()"]
    end

    MCPServer -->|execute| API[🎬 Booking API]

ฝั่ง MCP Server — ที่ที่ tool อยู่จริง:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { z } from 'zod'

const server = new McpServer({ name: 'movie-booking', version: '1.0.0' })

// ลงทะเบียน tool ด้วย Zod schema — ไม่ต้องเขียน JSON Schema มือเองแล้ว
server.tool(
  'book_movie',
  'จองตั๋วหนัง ใช้เมื่อผู้ใช้ต้องการจองตั๋ว',
  {
    movieId: z.string().describe('ID ของหนัง เช่น movie_001'),
    time: z.string().describe('เวลาที่ต้องการชม ISO 8601'),
    tickets: z.number().describe('จำนวนตั๋วที่ต้องการ'),
    name: z.string().describe('ชื่อผู้จอง'),
  },
  async (params) => {
    const res = await fetch('https://api.example.com/bookings', {
      method: 'POST',
      body: JSON.stringify(params),
    })
    const result = await res.json()
    return { content: [{ type: 'text', text: JSON.stringify(result) }] }
  }
)

// เปิด server รอรับการเชื่อมต่อ
const transport = new StdioServerTransport()
await server.connect(transport)

ฝั่ง AI App — เชื่อมต่อ MCP Server แล้วดึง tools มาใช้ได้เลย:

import { Client } from '@modelcontextprotocol/sdk/client/index.js'
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
import OpenAI from 'openai'

// ต่อเข้า MCP Server
const transport = new StdioClientTransport({
  command: 'node',
  args: ['./booking-server.js'],
})
const mcpClient = new Client({ name: 'my-ai-app', version: '1.0.0' })
await mcpClient.connect(transport)

// ดึง tool list จาก MCP Server มาแปลงเป็น format ของ OpenAI
const { tools: mcpTools } = await mcpClient.listTools()
const openaiTools = mcpTools.map((t) => ({
  type: 'function' as const,
  function: { name: t.name, description: t.description, parameters: t.inputSchema },
}))

// ส่งให้ AI เหมือนเดิมเลย ไม่ต้องรู้ว่า tool อยู่ที่ไหน
const openai = new OpenAI()
const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: [{ role: 'user', content: 'จองตั๋วหนัง Toy Story 5 ตอน 2 ทุ่ม' }],
  tools: openaiTools,
})

// พอ AI เลือก tool ก็เรียกผ่าน MCP Client ได้เลย
const toolCall = response.choices[0].message.tool_calls?.[0]
if (toolCall) {
  const result = await mcpClient.callTool({
    name: toolCall.function.name,
    arguments: JSON.parse(toolCall.function.arguments),
  })
  console.log(result.content)
}

app ฝั่งเราก็ไม่ต้องรู้เลยว่า tool ข้างในทำงานยังไง รู้แค่ว่า MCP Server มีอะไรให้เรียกบ้างก็พอ — พอ AI ตัดสินใจเรียก เราก็โยนให้ MCP Client จัดการต่อเลย ถ้าวันนึงอยากเพิ่ม tool ใหม่หรือแก้ logic เก่า ก็แก้แค่ที่ server ที่เดียว ทุก app ที่ต่ออยู่ก็เห็น tool ใหม่ทันทีเลยครับ

Use cases สำหรับ Developer

สำหรับ developer แล้ว MCP ไม่ได้มีประโยชน์แค่ในแง่ของการต่อ AI เข้ากับระบบภายนอกเท่านั้น แต่ยังช่วยให้เราสร้าง developer experience ที่ดีขึ้นได้ด้วย เช่น

1. ให้ AI ช่วย query database

เราสามารถสร้าง MCP server ที่ expose ความสามารถบางอย่างของ database ให้ AI ใช้ได้ เช่น query ข้อมูลสมาชิก, ตรวจสอบการจอง, สรุปยอดขายตั๋วในแต่ละรอบ หรือทำ semantic search จาก vector database

จุดสำคัญคือเราไม่ควรเปิดให้ AI query ทุกอย่างได้อย่างอิสระ แต่ควรกำหนด tools ที่ชัดเจน เช่น get_member_by_id, search_bookings, get_showtimes_by_branch หรือ semantic_search_movies เพื่อควบคุม scope และลดความเสี่ยง

2. ให้ AI ช่วยทำงานกับ internal API

โรงหนังเองก็มักมี internal API อยู่แล้ว เช่น ระบบจัดรอบฉาย, ระบบสมาชิก, ระบบ CRM, ระบบจัดการที่นั่ง หรือระบบอนุมัติโปรโมชันต่าง ๆ

แทนที่จะให้แต่ละ AI application เขียน integration เองทั้งหมด เราสามารถสร้าง MCP server เป็นชั้นกลางที่ expose เฉพาะ action ที่ปลอดภัยและจำเป็น เช่น เปิดเคสแจ้งปัญหาการจอง, ตรวจสอบสถานะการจอง, ดึงข้อมูลสมาชิก หรือสร้าง draft โปรโมชัน

3. ให้ AI ช่วยใน workflow ของทีม support

สำหรับทีม support หรือ operation MCP สามารถช่วยให้ AI agent ดึงข้อมูลจากหลายระบบมาประกอบกันได้ เช่น ดึงข้อมูลสมาชิกจาก CRM, ตรวจสอบการจองจาก booking service, ตรวจสอบที่นั่งว่างจาก showtime service แล้วสรุปเป็นคำตอบให้เจ้าหน้าที่

ตรงนี้ทำให้ AI ไม่ได้เป็นแค่ chatbot ที่ตอบจาก knowledge base เท่านั้น แต่สามารถช่วยทำงานบนข้อมูลจริงที่อยู่ในระบบขององค์กรได้

4. ให้ AI ช่วย developer ใน IDE

MCP ยังเหมาะกับ use case ในฝั่ง developer tooling เช่น ให้ AI ใน IDE อ่าน project structure, ค้นหาไฟล์, เข้าใจ schema, เรียกดู logs หรือเชื่อมต่อกับระบบ deployment ได้

เมื่อ AI มี context จากระบบจริงมากขึ้น คำตอบที่ได้ก็จะไม่ใช่แค่คำแนะนำทั่วไป แต่สามารถช่วยวิเคราะห์ปัญหาใน project ของเราได้แม่นยำขึ้น

ข้อควรระวัง

แม้ MCP จะช่วยให้การเชื่อมต่อ AI กับ tools เป็นระบบมากขึ้น แต่ก็ไม่ได้แปลว่าเราควรเปิดทุกอย่างให้ AI ใช้งานได้ทันที การออกแบบ MCP server ยังต้องคิดเรื่อง security และ governance อย่างจริงจัง

สิ่งที่ควรระวัง เช่น

  • Authentication และ Authorization: ต้องชัดเจนว่าใครสามารถเรียก tool ไหนได้บ้าง และเรียกได้ใน scope ใด
  • Input validation: ไม่ควรเชื่อ input ที่มาจาก AI โดยตรง ต้อง validate ก่อนส่งต่อไปยังระบบจริงเสมอ
  • Least privilege: ให้ AI เข้าถึงเฉพาะความสามารถที่จำเป็น ไม่ควรให้สิทธิ์กว้างเกินไป
  • Audit log: ควรบันทึกว่า AI เรียก tool อะไร เมื่อไร ด้วย input อะไร และได้ผลลัพธ์อะไรกลับมา
  • Human approval: งานที่มีผลกระทบสูง เช่น ยกเลิกการจอง คืนเงินค่าตั๋ว ปรับโปรโมชัน หรือส่งข้อความหาลูกค้าจริง ควรมีขั้นตอนให้มนุษย์ตรวจสอบก่อน
  • Error handling: ต้องออกแบบ error format ให้ชัดเจน เพื่อให้ AI เข้าใจได้ว่าเกิดปัญหาอะไร และควรตอบผู้ใช้อย่างไร

MCP ช่วยให้ tools เป็นมาตรฐานมากขึ้น แต่ความปลอดภัยยังคงเป็นหน้าที่ของเราที่ต้องออกแบบและควบคุมให้ดี

สรุป

ในโลกของ AI application การทำให้ AI “ตอบคำถามได้” เป็นเพียงจุดเริ่มต้น แต่ถ้าเราอยากให้ AI “ลงมือทำได้” เราต้องให้มันสามารถเชื่อมต่อกับ tools และระบบภายนอกได้อย่างปลอดภัย

Function Calling หรือ Tools ช่วยให้ AI เรียกใช้ความสามารถภายนอกได้ แต่เมื่อจำนวน tools เพิ่มขึ้น ปัญหาเรื่องมาตรฐาน การดูแลรักษา context window และการผูกติดกับ platform ก็จะเริ่มชัดเจนขึ้นเรื่อย ๆ

MCP จึงเข้ามาช่วยในฐานะมาตรฐานกลางที่ทำให้ AI applications สามารถเชื่อมต่อกับ tools, data sources และ external systems ได้ง่ายขึ้น เป็นระบบมากขึ้น และ reuse ได้ดีขึ้น

สำหรับ developer สิ่งที่น่าสนใจคือ MCP ไม่ได้เป็นแค่แนวคิดเชิง architecture เท่านั้น แต่เป็นแนวทางที่ช่วยให้เราสร้าง AI application ที่เชื่อมต่อกับระบบจริงได้อย่างเป็นระเบียบมากขึ้น

ในตอนต่อไป เราจะลองลงมือสร้าง MCP server แบบง่าย ๆ และเชื่อมต่อให้ AI เรียกใช้งานจริง เพื่อดูว่าแนวคิดนี้สามารถนำมาใช้กับ application ของเราได้อย่างไร ไว้เจอกันใหม่ตอนหน้าครับ :D

โดย Jirachai C.