AI Architecture·

การสร้าง MCP Server สำหรับธุรกิจของคุณ: คู่มือปฏิบัติสู่ Model Context Protocol

เรียนรู้วิธีสร้าง MCP Server พร้อมใช้งานในระดับโปรดักชั่นที่เชื่อมต่อระบบธุรกิจของคุณกับ AI Model — พร้อมรูปแบบการตรวจสอบสิทธิ, กลยุทธ์การลงทะเบียน Tools และรูปแบบการใช้งานจริงที่ช่วยให้แอปพลิเคชัน AI ที่มีความเข้าใจบริบบบทมีประสิทธิภาพ

การสร้าง MCP Server สำหรับธุรกิจของคุณ: คู่มือปฏิบัติสู่ Model Context Protocol

Model Context Protocol (MCP) ได้กลายเป็นมาตรฐานที่ยอมรับกันอย่างแพร่หลายสำหรับการเชื่อมต่อ AI Model เข้ากับระบบธุรกิจ เริ่มต้นพัฒนาโดย Anthropic MCP ได้รับการนำมาใช้กันอย่างกว้างขวางทั่วทั้งระบบนิเวศ AI ช่วยให้การบูรณาการระหว่าง Large Language Models กับข้อมูล เครื่องมือ และเวิร์กโฟลว์ของธุรกิจของคุณเป็นไปอย่างราบรื่น

ในคู่มือที่ครอบคลุมนี้ เราจะพาคุณผ่านกระบวนการสร้าง MCP Server พร้อมใช้งานในระดับโปรดักชั่นที่ช่วยปลดล็อกศักยภาพสูงสุดของ AI ในการดำเนินงานธุรกิจของคุณ

MCP คืออะไร และทำไมถึงสำคัญ?

Model Context Protocol กำหนดวิธีการมาตรฐานสำหรับระบบ AI ในการค้นหาและโต้ตอบกับความสามารถภายนอก นึกถึงมันเหมือนกับตัวเชื่อมอเนกประสงค์ที่ช่วยให้ AI Model เชื่อมต่อกับฐานข้อมูล API ระบบไฟล์ และตรรกะธุรกิจของคุณได้โดยไม่ต้องเขียนโค้ดการบูรณาการแบบกำหนดเองสำหรับแต่ละการเชื่อมต่อ

ประโยชน์หลักของ MCP:

  • การบูรณาการมาตรฐาน — โปรโตคอลเดียว เชื่อมต่อได้ไม่จำกัด
  • การโต้ตอบที่มีความปลอดภัยด้านชนิดข้อมูล — JSON-RPC 2.0 พร้อมการตรวจสอบ JSON Schema
  • การออกแบบเน้นความปลอดภัย — การตรวจสอบสิทธิและกำหนดขอบเขตสิทธิในตัว
  • การสื่อสารแบบทวิทิศทาง — AI สามารถอ่านข้อมูลและดำเนินการได้
  • ไม่ผูกขาดผู้ขาย — ใช้ได้กับ Claude GPT Gemini และ LLM อื่นๆ

เข้าใจสถาปัตยกรรม MCP

ในหัวใจสำคัญ MCP ใช้รูปแบบ Client-Server:

เลเยอร์ Transport

  • stdio: อินพุต/เอาต์พุตมาตรฐานสำหรับการสื่อสารโปรเซสในเครื่อง
  • HTTP กับ SSE: Server-Sent Events สำหรับการเชื่อมต่อระยะไกลที่มีสถานะ
  • WebSocket: การสื่อสารแบบ Full-Duplex สำหรับแอปพลิเคชัน Real-Time

เลเยอร์โปรโตคอล

  • รูปแบบข้อความ JSON-RPC 2.0
  • รูปแบบ Request/Notification สำหรับการสื่อสาร
  • การบันทึกบันทึกและจัดการข้อผิดพลาดแบบมีโครงสร้าง

เลเยอร์ความสามารถ

  • Tools: ฟังก์ชันที่ AI สามารถเรียกใช้เพื่อดำเนินการ
  • Resources: แหล่งข้อมูลแบบอ่านอย่างเดียวที่ AI สามารถเข้าถึงได้
  • Prompts: อินเตอร์แอ็กชันแบบเทมเพลตสำหรับงานทั่วไป

สร้าง MCP Server ตัวแรกของคุณ

มาสร้าง MCP Server ที่ปฏิบัติได้ซึ่งเชื่อมต่อกับ CRM ของธุรกิจของคุณและให้ข้อมูลเชิงลึกด้านการขายสำหรับผู้ช่วย AI

ตั้งค่าโปรเจกต์

# สร้างโปรเจกต์ MCP Server ใหม่
mkdir mcp-crm-server
cd mcp-crm-server
npm init -y
npm install @modelcontextprotocol/sdk zod

# ติดตั้ง Dependency เพิ่มเติมสำหรับกรณีใช้งานของคุณ
npm install axios dotenv

โครงสร้างเซิร์ฟเวอร์

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListResourcesRequestSchema,
  ListToolsRequestSchema,
  ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";

// กำหนด Schema ของ Tools
const GetSalesDataSchema = z.object({
  startDate: z.string().datetime(),
  endDate: z.string().datetime(),
  region: z.string().optional(),
});

class CRMMCPServer {
  private server: Server;
  private crmAPI: CRMClient;

  constructor() {
    this.server = new Server(
      {
        name: "crm-mcp-server",
        version: "1.0.0",
      },
      {
        capabilities: {
          tools: {},
          resources: {},
        },
      }
    );

    this.crmAPI = new CRMClient({
      apiKey: process.env.CRM_API_KEY,
      baseURL: process.env.CRM_BASE_URL,
    });

    this.setupHandlers();
  }

  private setupHandlers() {
    // แสดงรายการ Tools ที่มีให้ใช้
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: "get_sales_data",
          description: "ดึงข้อมูลประสิทธิภาพการขายสำหรับช่วงวันที่ที่กำหนด",
          inputSchema: {
            type: "object",
            properties: {
              startDate: {
                type: "string",
                format: "date-time",
                description: "วันที่เริ่มต้นในรูปแบบ ISO 8601",
              },
              endDate: {
                type: "string",
                format: "date-time",
                description: "วันที่สิ้นสุดในรูปแบบ ISO 8601",
              },
              region: {
                type: "string",
                description: "ตัวกรองภูมิภาคแบบเลือกได้ (เช่น 'EMEA', 'APAC')",
              },
            },
            required: ["startDate", "endDate"],
          },
        },
        {
          name: "update_contact_status",
          description: "อัปเดตสถานะของ Contact ใน CRM",
          inputSchema: {
            type: "object",
            properties: {
              contactId: {
                type: "string",
                description: "ตัวระบุ Contact ที่ไม่ซ้ำกัน",
              },
              status: {
                type: "string",
                enum: ["lead", "qualified", "customer", "churned"],
                description: "สถานะใหม่สำหรับ Contact",
              },
              notes: {
                type: "string",
                description: "บันทึกเพิ่มเติมเกี่ยวกับการเปลี่ยนสถานะ",
              },
            },
            required: ["contactId", "status"],
          },
        },
      ],
    }));

    // ประมวลผลการเรียกใช้ Tools
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;

      try {
        switch (name) {
          case "get_sales_data": {
            const validated = GetSalesDataSchema.parse(args);
            const data = await this.crmAPI.getSalesData(validated);
            return {
              content: [
                {
                  type: "text",
                  text: JSON.stringify(data, null, 2),
                },
              ],
            };
          }

          case "update_contact_status": {
            const { contactId, status, notes } = args as {
              contactId: string;
              status: string;
              notes?: string;
            };
            await this.crmAPI.updateContact(contactId, { status, notes });
            return {
              content: [
                {
                  type: "text",
                  text: `อัปเดต Contact ${contactId} เป็นสถานะ: ${status} สำเร็จแล้ว`,
                },
              ],
            };
          }

          default:
            throw new Error(`Tool ที่ไม่รู้จัก: ${name}`);
        }
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `ข้อผิดพลาด: ${error instanceof Error ? error.message : String(error)}`,
            },
          ],
          isError: true,
        };
      }
    });

    // แสดงรายการ Resources ที่มีให้ใช้
    this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
      resources: [
        {
          uri: "crm://contacts",
          name: "Contact ใน CRM ทั้งหมด",
          description: "รายการ Contact ทั้งหมดใน CRM",
          mimeType: "application/json",
        },
        {
          uri: "crm://deals/pipeline",
          name: "Sales Pipeline ที่กำลังดำเนินการ",
          description: "Sales Pipeline ปัจจุบันพร้อมขั้นตอน Deal",
          mimeType: "application/json",
        },
      ],
    }));

    // จัดการการอ่าน Resources
    this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
      const { uri } = request.params;

      try {
        switch (uri) {
          case "crm://contacts": {
            const contacts = await this.crmAPI.getAllContacts();
            return {
              contents: [
                {
                  uri,
                  mimeType: "application/json",
                  text: JSON.stringify(contacts, null, 2),
                },
              ],
            };
          }

          case "crm://deals/pipeline": {
            const pipeline = await this.crmAPI.getPipeline();
            return {
              contents: [
                {
                  uri,
                  mimeType: "application/json",
                  text: JSON.stringify(pipeline, null, 2),
                },
              ],
            };
          }

          default:
            throw new Error(`Resource ที่ไม่รู้จัก: ${uri}`);
        }
      } catch (error) {
        throw new Error(`ไม่สามารถอ่าน Resource ได้: ${error}`);
      }
    });
  }

  async run() {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);
    console.error("CRM MCP Server กำลังทำงานบน stdio");
  }
}

// เริ่มต้นเซิร์ฟเวอร์
const server = new CRMMCPServer();
server.run().catch(console.error);

รูปแบบการตรวจสอบสิทธิและความปลอดภัย

Credentials แบบตั้งค่าจาก Environment

// config/security.ts
import { z } from "zod";

const SecurityConfigSchema = z.object({
  apiKey: z.string().min(32),
  allowedOrigins: z.array(z.string().url()),
  rateLimit: z.object({
    requestsPerMinute: z.number().default(60),
  }),
  jwtSecret: z.string().optional(),
});

export const securityConfig = SecurityConfigSchema.parse({
  apiKey: process.env.MCP_API_KEY,
  allowedOrigins: process.env.MCP_ALLOWED_ORIGINS?.split(",") || [],
  rateLimit: {
    requestsPerMinute: parseInt(process.env.MCP_RATE_LIMIT || "60"),
  },
  jwtSecret: process.env.MCP_JWT_SECRET,
});

Middleware สำหรับการตรวจสอบคำขอ

// middleware/validation.ts
import { z, ZodTypeAny } from "zod";

export function validateToolInput<T extends ZodTypeAny>(
  schema: T,
  input: unknown
): z.infer<T> {
  try {
    return schema.parse(input);
  } catch (error) {
    if (error instanceof z.ZodError) {
      const messages = error.errors
        .map((e) => `${e.path.join(".")}: ${e.message}`)
        .join("; ");
      throw new Error(`การตรวจสอบล้มเหลว: ${messages}`);
    }
    throw error;
  }
}

// ทำความสะอาดเอาต์พุตเพื่อป้องกัน Prompt Injection
export function sanitizeOutput(text: string): string {
  return text
    .replace(/<script[^>]*>.*?<\/script>/gi, "")
    .replace(/javascript:/gi, "")
    .replace(/on\w+\s*=/gi, "");
}

กลยุทธ์การ Deploy สำหรับ Production

Containerization ด้วย Docker

# Dockerfile
FROM node:20-alpine

WORKDIR /app

# คัดลอกไฟล์แพ็กเกจ
COPY package*.json ./
RUN npm ci --only=production

// คัดลอกโค้ดต้นฉบับ
COPY dist/ ./dist/

// ความปลอดภัย: รันในฐานะ Non-Root User
USER node

EXPOSE 3000

HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
  CMD node dist/healthcheck.js

CMD ["node", "dist/index.js"]

HTTP Transport กับ SSE

สำหรับการ Deploy ระยะไกล ให้ใช้ HTTP พร้อม Server-Sent Events:

import express from "express";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";

const app = express();
const transport = new SSEServerTransport("/mcp", app);

// จัดการการเชื่อมต่อ MCP
app.use("/mcp", async (req, res) => {
  const sessionId = req.headers["x-session-id"] as string;
  await server.connect(transport, { sessionId });
});

// Middleware ตรวจสอบสิทธิ
app.use((req, res, next) => {
  const authHeader = req.headers.authorization;
  if (!authHeader || !verifyToken(authHeader)) {
    return res.status(401).json({ error: "ไม่ได้รับอนุญาต" });
  }
  next();
});

app.listen(3000, () => {
  console.log("MCP Server กำลังฟังที่ Port 3000");
});

การทดสอบ MCP Server ของคุณ

ตัวอย่าง Unit Test

// tests/crm-server.test.ts
import { describe, it, expect, beforeEach } from "vitest";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { InMemoryTransport } from "@modelcontextprotocol/sdk/inMemory.js";

describe("CRM MCP Server", () => {
  let client: Client;

  beforeEach(async () => {
    const { client: c, server: s } = InMemoryTransport.createLinkedPair();
    client = new Client({ name: "test-client", version: "1.0.0" });
    await client.connect(c);
  });

  it("ควรแสดงรายการ Tools ที่มีให้ใช้", async () => {
    const tools = await client.listTools();
    expect(tools.tools).toContainEqual(
      expect.objectContaining({ name: "get_sales_data" })
    );
  });

  it("ควรตรวจสอบอินพุตของ Tool", async () => {
    await expect(
      client.callTool({
        name: "get_sales_data",
        arguments: { startDate: "วันที่ไม่ถูกต้อง" },
      })
    ).rejects.toThrow();
  });
});

การทดสอบแบบ Integration

// tests/integration.test.ts
import { spawn } from "child_process";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

describe("การทดสอบ Integration", () => {
  it("ควรเชื่อมต่อกับเซิร์ฟเวอร์ที่กำลังทำงาน", async () => {
    const transport = new StdioClientTransport({
      command: "node",
      args: ["dist/index.js"],
      env: { CRM_API_KEY: "test-key" },
    });

    const client = new Client({
      name: "integration-test",
      version: "1.0.0",
    });

    await client.connect(transport);

    const resources = await client.listResources();
    expect(resources.resources.length).toBeGreaterThan(0);

    await client.close();
  });
});

รูปแบบทั่วไปและ Best Practices

1. การเปิดเผยความสามารถแบบ Progressive

อย่าเปิดเผยความสามารถทั้งหมดในครั้งเดียว ใช้การควบคุมการเข้าถึง:

getCapabilities() {
  const capabilities: Capabilities = {};
  
  if (this.hasPermission("tools:read")) {
    capabilities.tools = this.getToolsForUser();
  }
  
  if (this.hasPermission("resources:read")) {
    capabilities.resources = this.getResourcesForUser();
  }
  
  if (this.hasPermission("prompts:read")) {
    capabilities.prompts = this.getPromptsForUser();
  }
  
  return capabilities;
}

2. Pagination สำหรับชุดข้อมูลขนาดใหญ่

{
  name: "search_contacts",
  inputSchema: {
    type: "object",
    properties: {
      query: { type: "string" },
      limit: { type: "number", maximum: 100, default: 20 },
      cursor: { type: "string", description: "Cursor สำหรับ Pagination" },
    },
  },
}

3. การจัดการข้อผิดพลาดด้วยบริบท

class MCPToolError extends Error {
  constructor(
    message: string,
    public code: string,
    public details?: Record<string, unknown>
  ) {
    super(message);
  }
}

// ใน Tool Handler
try {
  await riskyOperation();
} catch (error) {
  throw new MCPToolError(
    "การอัปเดต Contact ล้มเหลว",
    "CONTACT_UPDATE_FAILED",
    { contactId: args.contactId, reason: error.message }
  );
}

การติดตามและการสังเกตการณ์

Structured Logging

import { pino } from "pino";

const logger = pino({
  level: process.env.LOG_LEVEL || "info",
  formatters: {
    bindings: () => ({ service: "mcp-server" }),
  },
});

// ใน Handlers ของคุณ
logger.info({ tool: name, duration_ms: elapsed }, "Tool ดำเนินการสำเร็จแล้ว");
logger.error({ error, tool: name }, "Tool ดำเนินการล้มเหลว");

Health Checks

// healthcheck.ts
import { checkDatabaseConnection } from "./db";
import { checkExternalAPIs } from "./apis";

export async function healthCheck(): Promise<HealthStatus> {
  const [db, apis] = await Promise.all([
    checkDatabaseConnection(),
    checkExternalAPIs(),
  ]);

  const healthy = db.healthy && apis.every((a) => a.healthy);

  return {
    status: healthy ? "healthy" : "unhealthy",
    timestamp: new Date().toISOString(),
    checks: {
      database: db,
      external_apis: apis,
    },
  };
}

กรณีใช้งานจริง

การบูรณาการหลายระบบ

// เชื่อมต่อ CRM, ERP และระบบสนับสนุน
class EnterpriseMCPServer {
  private integrations = {
    crm: new CRMIntegration(),
    erp: new ERPIntegration(),
    support: new SupportIntegration(),
  };

  async getCustomer360View(customerId: string) {
    const [crmData, erpData, supportHistory] = await Promise.all([
      this.integrations.crm.getCustomer(customerId),
      this.integrations.erp.getOrders(customerId),
      this.integrations.support.getTickets(customerId),
    ]);

    return {
      profile: crmData,
      purchaseHistory: erpData,
      supportInteractions: supportHistory,
      healthScore: this.calculateHealthScore(crmData, erpData, supportHistory),
    };
  }
}

Pipeline การประมวลผลเอกสาร

{
  name: "process_document",
  description: "อัปโหลดและประมวลผลเอกสาร",
  inputSchema: {
    type: "object",
    properties: {
      file_path: { type: "string" },
      operations: {
        type: "array",
        items: {
          enum: ["ocr", "summarize", "extract_entities", "translate"],
        },
      },
    },
  },
}

สรุป

การสร้าง MCP Server จะช่วยปลดล็อกศักยภาพสูงสุดของ AI ในธุรกิจของคุณโดยให้สิทธิ์การเข้าถึงแบบมาตรฐานและปลอดภัยสู่ระบบของคุณ เริ่มต้นด้วยการบูรณาการเดียว ปฏิบัติตาม Best Practices ด้านความปลอดภัย และขยายความสามารถของคุณทีละขั้น การลงทุนในสถาปัตยกรรมที่เหมาะสมจะจ่ายผลตอบแทนผ่านการพัฒนาฟีเจอร์ AI ที่เร็วขึ้นและการบูรณาการที่ง่ายต่อการบำรุงรักษา

จำไว้ว่า: MCP เกี่ยวกับการทำให้ AI ทำงาน ร่วมกับ ธุรกิจของคุณ ไม่ใช่การแทนที่ระบบที่มีอยู่ มุ่งเน้นที่ Use Case ที่ชัดเจน การจัดการข้อผิดพลาดที่แข็งแกร่ง และการติดตามที่ครอบคลุมเพื่อความสำเร็จในระดับ Production


พร้อมที่จะนำ MCP มาใช้ในธุรกิจของคุณแล้วหรือยัง? ติดต่อ Tropical Media ที่ tropical-media.work เพื่อรับคำแนะนำจากผู้เชี่ยวชาญด้านสถาปัตยกรรม AI และการบูรณาการ