
TL;DRMCPModel Context Protocol是 Anthropic 推出的开放协议让 AI 模型能标准化地连接外部工具和数据源。本文从协议原理讲起手把手带你用 Python 搭建一个 MCP Server并接入 Claude / Cursor 使用。1. 为什么需要 MCP过去让 AI 调用工具每个应用都要自己实现一遍集成想让 Claude 读数据库 → 自己写一套工具调用逻辑想让 Cursor 访问文件系统 → 再写一套想让自研 Agent 调 API → 又写一套结果就是N 个模型 × M 个工具 N×M 个集成每个都是定制化代码。MCP 的出现解决了这个问题MCP 架构┌──────────────┐ MCP 协议 ┌──────────────┐ │ AI 应用 │ ←────────────→ │ MCP Server │ │ (Claude/Cursor│ (stdio/HTTP) │ (你的工具) │ │ /Agent) │ │ - 数据库 │ └──────────────┘ │ - 文件系统 │ │ - API │ └──────────────┘模型只需要支持 MCP 协议就能连接任意 MCP Server。一次开发处处可用。2. MCP 的核心概念概念说明HostAI 应用本身Claude Desktop、Cursor、自研 AgentClientHost 内部的 MCP 客户端负责和 Server 通信Server提供能力的服务工具、资源、提示词模板Tool可调用的函数如查询数据库、发送邮件Resource可读取的数据如文件、API 响应Prompt预定义的提示词模板3. 搭建第一个 MCP Server3.1 环境准备bashpip install mcp pip install uvicorn # 如果用 HTTP 模式 # 验证安装 python -c import mcp; print(MCP installed)3.2 用 FastMCP 写一个简单 ServerPython - mcp_server.pyfrom mcp.server.fastmcp import FastMCP import sqlite3 import os # 创建 MCP Server mcp FastMCP(company-db-server) DB_PATH ./company.db def get_db_connection(): conn sqlite3.connect(DB_PATH) conn.row_factory sqlite3.Row return conn # Tool 1: 查询员工 def query_employee(name: str) - str: 根据姓名查询员工信息 Args: name: 员工姓名支持模糊匹配 conn get_db_connection() cursor conn.cursor() cursor.execute( SELECT * FROM employees WHERE name LIKE ?, (f%{name}%,) ) rows cursor.fetchall() conn.close() if not rows: return f未找到匹配 {name} 的员工 result [] for row in rows: result.append( f姓名: {row[name]}, 部门: {row[department]}, f职位: {row[title]}, 入职: {row[hire_date]} ) return \n.join(result) # Tool 2: 统计部门人数 def count_department(department: str) - str: 统计某个部门的员工人数 Args: department: 部门名称 conn get_db_connection() cursor conn.cursor() cursor.execute( SELECT COUNT(*) as count FROM employees WHERE department ?, (department,) ) count cursor.fetchone()[count] conn.close() return f部门 {department} 共有 {count} 名员工 # Resource: 数据库 schema schema://employees) def get_schema() - str: 返回 employees 表的字段定义 return employees 表结构 - id: 主键 - name: 姓名 - department: 部门 - title: 职位 - salary: 薪资 - hire_date: 入职日期 # 启动 Serverstdio 模式 if __name__ __main__: mcp.run()3.3 在 Claude Desktop 中配置claude_desktop_config.json{ mcpServers: { company-db: { command: python, args: [/path/to/mcp_server.py] } } }重启 Claude Desktop 后它会自动发现你的 MCP Server你就能直接对话你「公司技术部有多少人」Claude自动调用count_department(技术部)→ 「技术部共有 15 名员工」4. 进阶带鉴权的 MCP Server生产环境需要安全控制。给 MCP Server 加上 API Key 鉴权Python - 带鉴权的 MCP Serverfrom mcp.server.fastmcp import FastMCP from mcp.server import Server from mcp.types import Tool, TextContent import os EXPECTED_TOKEN os.getenv(MCP_TOKEN, default-secret) # 自定义 Server拦截请求做鉴权 server Server(secure-db-server) server.list_tools() async def list_tools() - list[Tool]: return [ Tool( namequery_employee, description查询员工信息, inputSchema{ type: object, properties: { name: {type: string} } } ) ] server.call_tool() async def call_tool(name: str, arguments: dict) - list[TextContent]: # 这里简化真实场景从请求头读取 token if name query_employee: result query_employee(arguments[name]) return [TextContent(typetext, textresult)] return [TextContent(typetext, textUnknown tool)] # 启动 if __name__ __main__: import mcp.server.stdio async def main(): async with mcp.server.stdio.stdio_server() as (read, write): await server.run(read, write, server.create_initialization_options()) asyncio.run(main())5. 实战构建一个 GitHub MCP Server让 AI 能查 Issue、建 PR、读代码Python - github_mcp_server.pyfrom mcp.server.fastmcp import FastMCP import requests import os mcp FastMCP(github-server) GITHUB_TOKEN os.getenv(GITHUB_TOKEN) BASE_URL https://api.github.com HEADERS { Authorization: ftoken {GITHUB_TOKEN}, Accept: application/vnd.github.v3json } def list_open_issues(repo: str, limit: int 10) - str: 列出仓库的开放 Issue Args: repo: 格式为 owner/repo limit: 返回数量限制 response requests.get( f{BASE_URL}/repos/{repo}/issues, headersHEADERS, params{state: open, per_page: limit} ) issues response.json() result [] for issue in issues[:limit]: result.append(f#{issue[number]} {issue[title]} ({issue[html_url]})) return \n.join(result) if result else 没有开放 Issue def create_issue(repo: str, title: str, body: str ) - str: 创建新的 GitHub Issue Args: repo: 格式为 owner/repo title: Issue 标题 body: Issue 内容 response requests.post( f{BASE_URL}/repos/{repo}/issues, headersHEADERS, json{title: title, body: body} ) if response.status_code 201: data response.json() return f✅ 已创建 Issue #{data[number]}: {data[html_url]} return f❌ 创建失败: {response.status_code} {response.text} if __name__ __main__: mcp.run()6. MCP vs Function Calling维度MCPFunction Calling定位标准化协议连接方式模型能力调用方式复用性一次开发多模型使用每个模型各自实现生态跨应用共享 Server绑定单一应用复杂度需要 Server 进程直接传函数定义适用工具生态建设简单工具调用⚠️ 注意MCP 和 Function Calling 不是对立的。MCP Server 底层也是用 Function Calling 实现工具调用只是封装了一层标准化协议让工具可以跨模型、跨应用复用。7. 总结MCP 解决了 AI 工具集成的「N×M 问题」过去每个 AI 应用自己写工具集成重复劳动现在写一次 MCP Server所有支持 MCP 的 AI 应用都能用适合用 MCP 的场景你有一套内部工具/API想让多个 AI 应用都能调用你做 Agent 平台想让用户自己贡献工具你需要统一的安全/鉴权层管理工具访问入门建议先用 FastMCP 写一个简单 Server如查询数据库接入 Claude Desktop 体验。熟悉后再做鉴权、HTTP 模式、多工具编排。如果对你有帮助欢迎在评论区聊聊你用 MCP 踩过的坑。