บทความนี้จะพาคุณเรียนรู้การสร้าง MCP (Model Context Protocol) Server ด้วย TypeScript ตั้งแต่ขั้นตอนแรกจนถึงการนำไปใช้งานจริง โดยเนื้อหาทั้งหมดมาจากประสบการณ์ตรงในการพัฒนา production-grade MCP Server ที่รองรับ AI providers หลายตัว พร้อมแนะนำการประหยัดค่าใช้จ่ายด้วย สมัครที่นี่
ทำไมต้องพัฒนา MCP Server ของตัวเอง?
MCP Server คือ middleware ที่ทำหน้าที่เป็นตัวกลางระหว่าง AI models กับ data sources ต่างๆ ข้อดีหลักคือ:
- สามารถเชื่อมต่อ database, APIs, และ file systems เข้าด้วยกัน
- Reusable ข้ามหลาย AI applications
- Type-safe ด้วย TypeScript ทำให้ debug ง่าย
- รองรับ streaming และ streaming responses
เปรียบเทียบต้นทุน AI API 2026
ก่อนเริ่มพัฒนา มาดูต้นทุนต่อเดือนสำหรับ 10M tokens/เดือน:
| Model | ราคา (output/MTok) | ต้นทุน 10M tokens/เดือน |
|---|---|---|
| Claude Sonnet 4.5 | $15.00 | $150.00 |
| GPT-4.1 | $8.00 | $80.00 |
| Gemini 2.5 Flash | $2.50 | $25.00 |
| DeepSeek V3.2 | $0.42 | $4.20 |
หมายเหตุ: DeepSeek V3.2 ประหยัดกว่า Claude Sonnet 4.5 ถึง 97%! หากใช้ HolySheep AI ที่มีอัตรา ¥1=$1 พร้อมรองรับ WeChat/Alipay และ latency <50ms คุณจะได้รับเครดิตฟรีเมื่อลงทะเบียน ช่วยลดต้นทุนได้มากกว่า 85%
การติดตั้ง Project และ Dependencies
mkdir mcp-server-tutorial
cd mcp-server-tutorial
npm init -y
npm install typescript ts-node @types/node zod
npm install -D @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint
Initialize TypeScript config
npx tsc --init
Install MCP SDK (latest version)
npm install @modelcontextprotocol/sdk
ไฟล์ tsconfig.json สำหรับ MCP Server:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
โครงสร้าง MCP Server พื้นฐาน
สร้างไฟล์ src/index.ts หลัก:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
// Define tool schemas
const searchSchema = z.object({
query: z.string().describe("Search query string"),
limit: z.number().optional().default(10),
});
const analyzeSchema = z.object({
text: z.string().describe("Text to analyze"),
model: z.enum(["gpt-4.1", "claude-sonnet-4.5", "deepseek-v3.2"]).default("deepseek-v3.2"),
});
// Create server instance
const server = new Server(
{
name: "mcp-tutorial-server",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "search",
description: "Search for information using AI",
inputSchema: {
type: "object",
properties: {
query: { type: "string", description: "Search query string" },
limit: { type: "number", description: "Max results", default: 10 },
},
required: ["query"],
},
},
{
name: "analyze",
description: "Analyze text using specified AI model",
inputSchema: {
type: "object",
properties: {
text: { type: "string", description: "Text to analyze" },
model: {
type: "string",
enum: ["gpt-4.1", "claude-sonnet-4.5", "deepseek-v3.2"],
default: "deepseek-v3.2"
},
},
required: ["text"],
},
},
],
};
});
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
if (name === "search") {
const { query, limit } = searchSchema.parse(args);
// Implementation here
return {
content: [
{
type: "text",
text: JSON.stringify({ query, limit, results: [] }),
},
],
};
}
if (name === "analyze") {
const { text, model } = analyzeSchema.parse(args);
// Call HolySheep AI API
const response = await callHolySheepAPI(text, model);
return {
content: [{ type: "text", text: response }],
};
}
throw new Error(Unknown tool: ${name});
} catch (error) {
return {
content: [{ type: "text", text: Error: ${error} }],
isError: true,
};
}
});
// Helper function to call HolySheep AI
async function callHolySheepAPI(text: string, model: string): Promise {
const response = await fetch("https://api.holysheep.ai/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": Bearer ${process.env.HOLYSHEEP_API_KEY},
},
body: JSON.stringify({
model: model,
messages: [{ role: "user", content: text }],
max_tokens: 1000,
}),
});
const data = await response.json();
return data.choices[0].message.content;
}
// Start server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("MCP Server running on stdio");
}
main().catch(console.error);
การเพิ่ม Resource Management
เพิ่มความสามารถในการจัดการ resources:
import {
ListResourcesRequestSchema,
ReadResourceRequestSchema,
ListPromptsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
// Register resource handler
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: "config://ai-models",
name: "AI Models Configuration",
mimeType: "application/json",
description: "Available AI models and pricing",
},
{
uri: "stats://usage",
name: "Usage Statistics",
mimeType: "application/json",
description: "Current API usage data",
},
],
};
});
// Register resource reader
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;
if (uri === "config://ai-models") {
return {
contents: [
{
uri,
mimeType: "application/json",
text: JSON.stringify({
models: [
{ name: "gpt-4.1", provider: "OpenAI", pricePerMToken: 8 },
{ name: "claude-sonnet-4.5", provider: "Anthropic", pricePerMToken: 15 },
{ name: "deepseek-v3.2", provider: "DeepSeek", pricePerMToken: 0.42 },
{ name: "gemini-2.5-flash", provider: "Google", pricePerMToken: 2.50 },
],
}),
},
],
};
}
throw new Error(Unknown resource: ${uri});
});
การ Debug MCP Server
สร้างไฟล์ test-server.ts สำหรับทดสอบ:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function testServer() {
const transport = new StdioClientTransport({
command: "npx",
args: ["ts-node", "src/index.ts"],
env: {
HOLYSHEEP_API_KEY: process.env.HOLYSHEEP_API_KEY || "YOUR_HOLYSHEEP_API_KEY",
},
});
const client = new Client(
{ name: "mcp-test-client", version: "1.0.0" },
{ capabilities: { tools: true, resources: true } }
);
try {
await client.connect(transport);
console.log("✅ Connected to MCP Server");
// Test list tools
const tools = await client.request({ method: "tools/list" }, ListToolsRequestSchema);
console.log("✅ Available tools:", tools.tools.map(t => t.name));
// Test call tool
const result = await client.request(
{
method: "tools/call",
params: {
name: "analyze",
arguments: { text: "Hello world", model: "deepseek-v3.2" },
},
},
CallToolRequestSchema
);
console.log("✅ Tool result:", result);
} catch (error) {
console.error("❌ Error:", error);
} finally {
await client.close();
}
}
testServer();
ข้อผิดพลาดที่พบบ่อยและวิธีแก้ไข
1. Error: Module not found: @modelcontextprotocol/sdk
# ปัญหา: ไม่พบ package หรือ version ไม่ตรงกัน
วิธีแก้: ตรวจสอบ package.json และติดตั้งใหม่
ลบ node_modules และ package-lock.json
rm -rf node_modules package-lock.json
ติดตั้ง dependencies ใหม่
npm install @modelcontextprotocol/sdk@latest typescript@latest
หรือใช้ npm ci สำหรับ production
npm ci
2. Error: Invalid base_url or API key
# ปัญหา: ใช้ base_url ผิดหรือ API key ไม่ถูกต้อง
วิธีแก้: ตรวจสอบ environment variables
สร้างไฟล์ .env
echo 'HOLYSHEEP_API_KEY=YOUR_HOLYSHEEP_API_KEY' > .env
ใช้ dotenv ในโค้ด
npm install dotenv
เพิ่มที่ด้านบนของ index.ts
import 'dotenv/config';
// ตรวจสอบว่า base_url ถูกต้อง
ต้องเป็น: https://api.holysheep.ai/v1
ห้ามใช้: api.openai.com หรือ api.anthropic.com
3. Error: Streaming response timeout
# ปัญหา: Response ใช้เวลานานเกิน timeout
วิธีแก้: เพิ่ม timeout และ retry logic
async function callWithRetry(
url: string,
options: RequestInit,
maxRetries = 3
): Promise<any> {
for (let i = 0; i < maxRetries; i++) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000);
const response = await fetch(url, {
...options,
signal: controller.signal,
});
clearTimeout(timeoutId);
return response;
} catch (error: any) {
if (i === maxRetries - 1) throw error;
console.log(Retry ${i + 1}/${maxRetries}...);
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
}
}
}
4. Error: Zod validation failed
# ปัญหา: Input schema ไม่ตรงกับ request
วิธีแก้: เพิ่ม error handling และ validation
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
// ใช้ safeParse แทน parse เพื่อ catch error
if (name === "search") {
const result = searchSchema.safeParse(args);
if (!result.success) {
return {
content: [{
type: "text",
text: Validation error: ${result.error.message}
}],
isError: true,
};
}
const { query, limit } = result.data;
// Process...
}
} catch (error) {
return {
content: [{ type: "text", text: Server error: ${error} }],
isError: true,
};
}
});
สรุป
การพัฒนา MCP Server ด้วย TypeScript ต้องใส่ใจในเรื่อง type safety, error handling, และการจัดการ resources อย่างเหมาะสม จากการเปรียบเทียบต้นทุน 10M tokens/เดือน พบว่า DeepSeek V3.2 ที่ $0.42/MTok ประหยัดที่สุดเมื่อเทียบกับ Claude Sonnet 4.5 ที่ $15/MTok
HolySheep AI เป็นตัวเลือกที่ดีสำหรับ production เพราะมีอัตรา ¥1=$1 รองรับ WeChat/Alipay latency <50ms และให้เครดิตฟรีเมื่อลงทะเบียน ช่วยประหยัดได้มากกว่า