การสร้างเซิร์ฟเวอร์ MCP แรกของคุณ
ใช้ Python MCP SDK สร้างเซิร์ฟเวอร์ที่เปิดให้เข้าถึงทรัพยากร เครื่องมือ และพรอมต์ จากนั้นเชื่อมต่อกับ Claude Desktop เพื่อดูการทำงานตั้งแต่ต้นจนจบ
การสร้างเซิร์ฟเวอร์ MCP แรกของคุณ เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
การตั้งค่าโครงการสำหรับเซิร์ฟเวอร์ MCP
การสร้างเซิร์ฟเวอร์ MCP ด้วย Python ต้องใช้ SDK mcp และสภาพแวดล้อม Python คุณจะสร้างเซิร์ฟเวอร์ที่ Claude Desktop หรือไคลเอ็นต์ MCP ใด ๆ เชื่อมต่อผ่าน stdio ได้ เริ่มด้วยการติดตั้งแพ็กเกจและสร้างไฟล์เซิร์ฟเวอร์
# Create a project directory
# mkdir my_mcp_server && cd my_mcp_server
# Create a virtual environment
# python -m venv venv && source venv/bin/activate
# Install the MCP SDK
# pip install mcp httpx
# Project structure:
# my_mcp_server/
# server.py <- Your MCP server
# requirements.txt
# README.mdการสร้างออบเจ็กต์เซิร์ฟเวอร์
นำเข้าจากแพ็กเกจ mcp และสร้างอินสแตนซ์ Server โดยระบุชื่อเซิร์ฟเวอร์ ชื่อนี้จะแสดงให้ไคลเอ็นต์เห็นในรายการเซิร์ฟเวอร์ MCP ให้เลือกชื่อที่สื่อความหมาย ออบเจ็กต์เซิร์ฟเวอร์เป็นจุดเริ่มต้นสำหรับลงทะเบียนเครื่องมือ ทรัพยากร และคำสั่งทั้งหมดของคุณ
# server.py
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
import asyncio
import httpx
# Create the server — name is shown in Claude Desktop
app = Server('weather-server')
# --- Tool registrations go here ---
# Entry point
if __name__ == '__main__':
asyncio.run(stdio_server(app))การลงทะเบียนเครื่องมือด้วย @app.list_tools()
ตัวตกแต่ง @app.list_tools() จะลงทะเบียนตัวจัดการที่ส่งคืนรายการเครื่องมือที่พร้อมใช้งานเมื่อไคลเอ็นต์ร้องขอ เครื่องมือแต่ละรายการกำหนดด้วยชื่อ คำอธิบาย และ inputSchema ซึ่งเป็น JSON Schema ที่อธิบายพารามิเตอร์ของเครื่องมือ ไคลเอ็นต์จะส่งรายการนี้ให้ LLM เพื่อให้โมเดลทราบว่าเรียกใช้เครื่องมือใดได้บ้าง
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name='get_weather',
description='Get current weather for a city. Use when the user asks about weather in a specific location.',
inputSchema={
'type': 'object',
'properties': {
'city': {
'type': 'string',
'description': 'City name, e.g. London or New York'
},
'units': {
'type': 'string',
'enum': ['metric', 'imperial'],
'description': 'Temperature units. Default is metric.'
}
},
'required': ['city']
}
),
types.Tool(
name='list_cities',
description='Return a list of major cities the user can query weather for.',
inputSchema={'type': 'object', 'properties': {}, 'required': []}
)
]การนำการเรียกใช้เครื่องมือไปใช้งาน
ตัวตกแต่ง @app.call_tool() จัดการการเรียกใช้เครื่องมือ เมื่อไคลเอ็นต์เรียกใช้เครื่องมือ ตัวจัดการนี้จะได้รับชื่อเครื่องมือและอาร์กิวเมนต์ ให้ดำเนินการตามตรรกะที่เหมาะสม แล้วส่งคืนรายการออบเจ็กต์ TextContent ที่มีสตริงผลลัพธ์
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == 'list_cities':
cities = ['London', 'New York', 'Tokyo', 'Paris', 'Sydney']
return [types.TextContent(type='text', text=', '.join(cities))]
if name == 'get_weather':
city = arguments['city']
units = arguments.get('units', 'metric')
unit_symbol = 'C' if units == 'metric' else 'F'
# Call real weather API (stub here)
async with httpx.AsyncClient() as client:
# Replace with actual API call
result = f'{city}: 18{chr(176)}{unit_symbol}, partly cloudy, humidity 65%'
return [types.TextContent(type='text', text=result)]
raise ValueError(f'Unknown tool: {name}')การเปิดเผย Resource
Resource คือข้อมูลแบบคงที่หรือแบบไดนามิกที่โมเดลสามารถอ่านได้ ลองนึกภาพว่าเป็นไฟล์ กำหนด URI ของ Resource และนำตัวอ่าน Resource ไปใช้งาน Resource จะแสดงในไคลเอ็นต์เป็นรายการที่ AI ใช้อ้างอิงได้ จึงเหมาะสำหรับการกำหนดค่า เอกสาร หรือภาพรวมข้อมูลที่มีการเรียกใช้บ่อย
@app.list_resources()
async def list_resources() -> list[types.Resource]:
return [
types.Resource(
uri='weather://supported-cities',
name='Supported Cities List',
description='Complete list of cities available in this weather server.',
mimeType='text/plain'
)
]
@app.read_resource()
async def read_resource(uri: str) -> str:
if uri == 'weather://supported-cities':
cities = ['London', 'New York', 'Tokyo', 'Paris', 'Sydney', 'Dubai', 'Singapore']
return '\n'.join(cities)
raise ValueError(f'Unknown resource URI: {uri}')การลงทะเบียนเทมเพลต Prompt
Prompt คือเทมเพลตข้อความที่นำกลับมาใช้ซ้ำได้ โดยไคลเอ็นต์จะแสดงให้ผู้ใช้เห็นเป็นคำสั่งแบบสแลชหรือการดำเนินการด่วน Prompt รับพารามิเตอร์และส่งคืนรายการข้อความ ซึ่งจะกลายเป็นบริบทเริ่มต้นของการสนทนา Prompt เหมาะอย่างยิ่งสำหรับเก็บคำสั่งที่ซับซ้อนซึ่งผู้ใช้เรียกใช้ได้ด้วยคำสั่งเดียว
@app.list_prompts()
async def list_prompts() -> list[types.Prompt]:
return [
types.Prompt(
name='weather-report',
description='Generate a formatted weather report for a city.',
arguments=[
types.PromptArgument(name='city', description='City name', required=True)
]
)
]
@app.get_prompt()
async def get_prompt(name: str, arguments: dict) -> types.GetPromptResult:
if name == 'weather-report':
city = arguments.get('city', 'London')
return types.GetPromptResult(
description=f'Weather report for {city}',
messages=[
types.PromptMessage(
role='user',
content=types.TextContent(
type='text',
text=f'Use the get_weather tool to look up {city} and give me a detailed weather report including what clothing I should wear.'
)
)
]
)
raise ValueError(f'Unknown prompt: {name}')การเชื่อมต่อกับ Claude Desktop
หากต้องการใช้เซิร์ฟเวอร์ MCP กับ Claude Desktop ให้เพิ่มเซิร์ฟเวอร์ลงในไฟล์การกำหนดค่าของ Claude Desktop บน macOS ไฟล์นี้อยู่ที่ ~/Library/Application Support/Claude/claude_desktop_config.json ให้ระบุคำสั่งสำหรับเริ่มเซิร์ฟเวอร์และตัวแปรสภาพแวดล้อมที่เซิร์ฟเวอร์ต้องใช้
# ~/Library/Application Support/Claude/claude_desktop_config.json
# Add this JSON configuration:
# {
# "mcpServers": {
# "weather-server": {
# "command": "/path/to/venv/bin/python",
# "args": ["/path/to/my_mcp_server/server.py"],
# "env": {
# "WEATHER_API_KEY": "your_api_key_here"
# }
# }
# }
# }
# After saving, restart Claude Desktop.
# Your server's tools will appear in Claude's tool list.การทดสอบเซิร์ฟเวอร์ด้วย MCP CLI
ก่อนเชื่อมต่อกับ Claude Desktop ให้ทดสอบเซิร์ฟเวอร์โดยใช้ตัวตรวจสอบ MCP หรือเครื่องมือ CLI คำสั่ง mcp dev จะเริ่มเซิร์ฟเวอร์และเปิดตัวตรวจสอบในเบราว์เซอร์ ซึ่งคุณสามารถเรียกใช้เครื่องมือด้วยตนเองและดูข้อความโพรโทคอลดิบได้ จึงช่วยแก้ไขปัญหาได้ง่าย
# Install the MCP development tools
# pip install 'mcp[cli]'
# Start the inspector with your server
# mcp dev server.py
# The inspector opens at http://localhost:5173
# You can:
# - See all registered tools and their schemas
# - Call tools with custom arguments
# - Browse available resources
# - Test prompt templates
# - View the full JSON-RPC message exchangeการจัดการข้อผิดพลาดในเซิร์ฟเวอร์ MCP
เซิร์ฟเวอร์ MCP ไม่ควรหยุดทำงานเมื่อได้รับข้อมูลนำเข้าที่ไม่ถูกต้อง ให้ครอบการเรียกใช้เครื่องมือทั้งหมดด้วย try/except และส่งคืนข้อความข้อผิดพลาดเป็น TextContent แทนการโยนข้อยกเว้น สำหรับข้อผิดพลาดร้ายแรง เช่น ปัญหาการกำหนดค่าหรือคีย์ API ที่ขาดหายไป ให้บันทึกข้อผิดพลาดเมื่อเริ่มต้นระบบ และโยนข้อผิดพลาดก่อนที่เซิร์ฟเวอร์จะเข้าสู่ลูปหลัก
@app.call_tool()
async def call_tool_safe(name: str, arguments: dict) -> list[types.TextContent]:
try:
if name == 'get_weather':
city = arguments.get('city')
if not city:
return [types.TextContent(type='text', text='Error: city argument is required.')]
result = await fetch_weather(city, arguments.get('units', 'metric'))
return [types.TextContent(type='text', text=result)]
raise ValueError(f'Unknown tool: {name}')
except httpx.TimeoutException:
return [types.TextContent(type='text', text='Error: Weather API timed out. Try again.')]
except Exception as e:
return [types.TextContent(type='text', text=f'Error: {str(e)}')]การบันทึกข้อมูลสำหรับเซิร์ฟเวอร์ MCP
เนื่องจากเซิร์ฟเวอร์ MCP สื่อสารกับไคลเอ็นต์ผ่าน stdio คำสั่งพิมพ์ข้อความจะทำให้โพรโทคอลเสียหาย ให้ใช้ stderr สำหรับการบันทึกข้อมูลเสมอ เพราะข้อมูลจะถูกส่งไปยังสตรีมแยกต่างหากและไม่รบกวนการแลกเปลี่ยนข้อความ MCP ให้กำหนดค่าโมดูล logging ของ Python ให้เขียนข้อมูลไปยัง stderr
import logging
import sys
# Configure logging to stderr (NOT stdout — that's the MCP channel)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s [%(levelname)s] %(message)s',
stream=sys.stderr
)
logger = logging.getLogger('weather-server')
# In your tool handler:
# logger.info(f'Getting weather for {city}')
# logger.error(f'API call failed: {e}')
# Claude Desktop captures stderr to a log file:
# ~/Library/Logs/Claude/mcp-server-weather-server.logการจัดแพ็กเกจเซิร์ฟเวอร์ MCP
แบ่งปันเซิร์ฟเวอร์ MCP ของคุณโดยจัดแพ็กเกจด้วย pyproject.toml แล้วเผยแพร่ไปยัง PyPI หรือแจกจ่ายเป็นคอนเทนเนอร์ Docker สำหรับทีม ใช้ตัวแปรสภาพแวดล้อมสำหรับข้อมูลลับทั้งหมด เช่น คีย์ API และ URL ฐานข้อมูล เพื่อแยกการกำหนดค่าเซิร์ฟเวอร์ออกจากโค้ด จัดทำเอกสารตัวแปรสภาพแวดล้อมที่จำเป็นและตัวอย่างการกำหนดค่าไว้ใน README ที่อ่านเข้าใจง่าย
ตรวจสอบความเข้าใจ
ทดสอบความเข้าใจเกี่ยวกับการสร้างเซิร์ฟเวอร์ MCP ใน Python
สรุปบทเรียน
ในบทเรียนนี้ คุณได้เรียนรู้ว่า เซิร์ฟเวอร์ MCP เปิดเผยเครื่องมือผ่านตัวตกแต่ง @app.list_tools() และ @app.call_tool() Resource และ Prompt ช่วยเพิ่มข้อมูลที่อ่านได้และเทมเพลตที่นำกลับมาใช้ซ้ำให้แก่เซิร์ฟเวอร์ และ การบันทึกข้อมูลต้องใช้ stderr เพื่อป้องกันไม่ให้ช่องทางโพรโทคอล MCP แบบ stdio เสียหาย ต่อไป เราจะเชื่อมต่อเซิร์ฟเวอร์ MCP กับฐานข้อมูลและเปิดเผย Resource แบบไดนามิกพร้อมการแบ่งหน้า
คำถามที่พบบ่อย
บทเรียน “การสร้างเซิร์ฟเวอร์ MCP แรกของคุณ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การสร้างเซิร์ฟเวอร์ MCP แรกของคุณ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การสร้างเซิร์ฟเวอร์ MCP แรกของคุณ”
ใช้ Python MCP SDK สร้างเซิร์ฟเวอร์ที่เปิดให้เข้าถึงทรัพยากร เครื่องมือ และพรอมต์ จากนั้นเชื่อมต่อกับ Claude Desktop เพื่อดูการทำงานตั้งแต่ต้นจนจบ คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน
บทเรียน “การสร้างเซิร์ฟเวอร์ MCP แรกของคุณ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม
ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- MCP คืออะไรและสำคัญอย่างไร
- การสร้างเซิร์ฟเวอร์ MCP แรกของคุณ
- การเปิดให้เข้าถึงทรัพยากรฐานข้อมูลผ่าน MCP
- ความปลอดภัยและการยืนยันตัวตนของ MCP