[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-goujian-diyige-mcp-fuwuqi-kaifazhe-shijian-zhinan":3},{"article":4,"author":50},{"id":5,"category_id":6,"title":7,"slug":8,"excerpt":9,"content_md":10,"content_html":11,"locale":12,"author_id":13,"published":14,"published_at":15,"meta_title":7,"meta_description":16,"focus_keyword":17,"og_image":18,"canonical_url":18,"robots_meta":19,"created_at":15,"updated_at":15,"tags":20,"category_name":30,"related_articles":31},"d0000000-0000-0000-0000-000000000504","a0000000-0000-0000-0000-000000000036","构建您的第一个 MCP 服务器：开发者实践指南","goujian-diyige-mcp-fuwuqi-kaifazhe-shijian-zhinan","一步一步教您用 TypeScript 和 Python 构建 Model Context Protocol (MCP) 服务器、连接 Claude Desktop 或 Cursor、并部署到生产环境的实践教程。","## 什么是 Model Context Protocol (MCP)？\n\n**Model Context Protocol (MCP)** 是 Anthropic 创建的一项开放标准，定义了 AI 应用程序如何与外部数据源和工具进行通信。将 MCP 视为 **AI 集成的 USB-C**：就像 USB-C 提供了一个用于充电、数据传输和显示输出的通用连接器一样，MCP 提供了一个将 AI 模型连接到数据库、API、文件系统和任何其他服务的通用协议。MCP 消除了每个 AI 应用程序与每个工具之间自定义集成的需求。\n\n2026 年，MCP 已成为 AI 工具通信的主导标准。Gartner 预测，到 **2026 年底，40% 的企业应用程序将包含 AI 代理**，而 MCP 是使这在规模上变得可行的协议。在 MCP 出现之前，将 AI 模型连接到 N 个工具需要 N 个自定义集成。对于 M 个 AI 应用程序和 N 个工具，您需要 M x N 个集成适配器。MCP 将其减少为 M + N：每个 AI 应用程序实现一个 MCP client，每个工具实现一个 MCP server。\n\n## MCP 架构：Host、Client、Server 和 Transport\n\n在编写任何代码之前，理解 MCP 架构至关重要。该协议定义了四个关键角色：\n\n| 组件 | 角色 | 示例 |\n|------|------|------|\n| **Host** | 终端用户交互的 AI 应用程序 | Claude Desktop、Cursor、VS Code Copilot |\n| **Client** | Host 内的 MCP 协议处理器 | 内置于 Host 应用程序中 |\n| **Server** | 通过 MCP 公开 tools、resources 和 prompts | 您的自定义服务器（我们将构建的） |\n| **Transport** | Client 和 Server 之间的通信层 | stdio、HTTP+SSE、Streamable HTTP |\n\n通信流程如下：\n\n1. **Host** 启动并为每个配置的服务器初始化 MCP **Client**。\n2. **Client** 通过 **Transport** 连接到 **Server**（本地使用 stdio，远程使用 HTTP）。\n3. **Client** 发送 `initialize` 请求，协商协议版本和能力。\n4. **Server** 响应其可用的 **tools**、**resources** 和 **prompts**。\n5. 当 AI 模型需要外部数据或操作时，**Client** 调用相应的服务器方法。\n6. **Server** 执行操作并通过 JSON-RPC 2.0 消息返回结果。\n\n### Tools vs Resources vs Prompts\n\nMCP server 可以公开三种类型的能力：\n\n- **Tools** 是 AI 模型可以调用的函数。它们接受结构化输入并返回结构化输出。示例：`query_database(sql: string)` 或 `send_email(to: string, subject: string, body: string)`。\n- **Resources** 是 AI 模型可以读取的数据。它们由 URI 标识并返回内容。示例：`file:\u002F\u002F\u002Fpath\u002Fto\u002Fdocument.md` 或 `postgres:\u002F\u002Flocalhost\u002Fmydb\u002Fusers`。\n- **Prompts** 是服务器提供的可重用提示模板。它们帮助标准化 AI 与服务器领域的交互方式。示例：用于 Jira MCP server 的 `summarize_ticket` 提示模板。\n\n## 逐步指南：在 TypeScript 中构建 MCP Server\n\n让我们构建一个实用的 MCP server，提供用于查询 SQLite 数据库的工具。这是一个常见用例：给 AI 模型提供对应用程序数据的安全只读访问。\n\n### 步骤 1：初始化项目\n\n```bash\nmkdir mcp-sqlite-server && cd mcp-sqlite-server\nnpm init -y\nnpm install @modelcontextprotocol\u002Fsdk better-sqlite3\nnpm install -D typescript @types\u002Fnode @types\u002Fbetter-sqlite3\nnpx tsc --init\n```\n\n配置 `tsconfig.json`：\n\n```json\n{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"Node16\",\n    \"outDir\": \".\u002Fdist\",\n    \"rootDir\": \".\u002Fsrc\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"declaration\": true\n  },\n  \"include\": [\"src\u002F**\u002F*\"]\n}\n```\n\n### 步骤 2：实现服务器\n\n创建 `src\u002Findex.ts`：\n\n```typescript\nimport { McpServer } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fmcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fstdio.js\";\nimport Database from \"better-sqlite3\";\nimport { z } from \"zod\";\n\nconst db = new Database(process.env.DB_PATH || \".\u002Fdata.db\", {\n  readonly: true,\n});\n\nconst server = new McpServer({\n  name: \"sqlite-query\",\n  version: \"1.0.0\",\n});\n\nserver.tool(\n  \"query\",\n  \"对 SQLite 数据库执行只读 SQL 查询\",\n  {\n    sql: z.string().describe(\"要执行的 SQL SELECT 查询\"),\n  },\n  async ({ sql }) => {\n    const normalized = sql.trim().toUpperCase();\n    if (!normalized.startsWith(\"SELECT\")) {\n      return {\n        content: [{ type: \"text\", text: \"错误：仅允许 SELECT 查询。\" }],\n        isError: true,\n      };\n    }\n    try {\n      const rows = db.prepare(sql).all();\n      return {\n        content: [{ type: \"text\", text: JSON.stringify(rows, null, 2) }],\n      };\n    } catch (error) {\n      return {\n        content: [{ type: \"text\", text: `查询错误：${(error as Error).message}` }],\n        isError: true,\n      };\n    }\n  }\n);\n\nserver.tool(\n  \"list_tables\",\n  \"列出数据库中所有表及其架构\",\n  {},\n  async () => {\n    const tables = db\n      .prepare(\n        `SELECT name, sql FROM sqlite_master\n         WHERE type='table' AND name NOT LIKE 'sqlite_%'\n         ORDER BY name`\n      )\n      .all();\n    return {\n      content: [{ type: \"text\", text: JSON.stringify(tables, null, 2) }],\n    };\n  }\n);\n```\n\n### 步骤 3：构建并本地测试\n\n```bash\nnpx tsc\necho '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-03-26\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0\"}}}' | node dist\u002Findex.js\n```\n\n您将看到包含服务器能力的 JSON-RPC 响应。\n\n### 步骤 4：用 Python 构建相同的服务器\n\n对于 Python 开发者，以下是使用官方 MCP Python SDK 的等效实现：\n\n```python\nimport sqlite3\nimport json\nfrom mcp.server.fastmcp import FastMCP\n\nmcp = FastMCP(\"sqlite-query\")\nDB_PATH = \"data.db\"\n\n@mcp.tool()\ndef query(sql: str) -> str:\n    \"\"\"对 SQLite 数据库执行只读 SQL 查询。\"\"\"\n    normalized = sql.strip().upper()\n    if not normalized.startswith(\"SELECT\"):\n        raise ValueError(\"仅允许 SELECT 查询。\")\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row\n    try:\n        cursor = conn.execute(sql)\n        rows = [dict(row) for row in cursor.fetchall()]\n        return json.dumps(rows, indent=2, default=str)\n    finally:\n        conn.close()\n\n@mcp.tool()\ndef list_tables() -> str:\n    \"\"\"列出数据库中所有表及其架构。\"\"\"\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row\n    try:\n        cursor = conn.execute(\n            \"SELECT name, sql FROM sqlite_master \"\n            \"WHERE type='table' AND name NOT LIKE 'sqlite_%'\"\n        )\n        tables = [dict(row) for row in cursor.fetchall()]\n        return json.dumps(tables, indent=2)\n    finally:\n        conn.close()\n\nif __name__ == \"__main__\":\n    mcp.run(transport=\"stdio\")\n```\n\n## 连接到 Claude Desktop\n\nClaude Desktop 原生支持 MCP server。要连接您的服务器，请编辑 Claude Desktop 配置文件：\n\n**macOS：** `~\u002FLibrary\u002FApplication Support\u002FClaude\u002Fclaude_desktop_config.json`\n**Windows：** `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-query\": {\n      \"command\": \"node\",\n      \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"DB_PATH\": \"\u002Fabsolute\u002Fpath\u002Fto\u002Fyour\u002Fdata.db\"\n      }\n    }\n  }\n}\n```\n\n重启 Claude Desktop。您将在聊天界面中看到一个锤子图标，表示可用的 MCP 工具。现在您可以向 Claude 提问，例如\"数据库中有哪些表？\"或\"按注册日期显示前 10 个用户\"，Claude 将使用您的 MCP server 直接查询数据库。\n\n## 连接到 Cursor\n\nCursor 也支持 MCP server。在项目根目录的 `.cursor\u002Fmcp.json` 中添加配置：\n\n```json\n{\n  \"mcpServers\": {\n    \"sqlite-query\": {\n      \"command\": \"node\",\n      \"args\": [\".\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"DB_PATH\": \".\u002Fdata.db\"\n      }\n    }\n  }\n}\n```\n\n保存后重启 Cursor。MCP 工具将出现在 AI 助手面板中，可在代码生成和调试会话期间调用。\n\n## 测试和调试您的 MCP Server\n\n### 使用 MCP Inspector\n\nMCP Inspector 是官方调试工具。它提供了与服务器交互的 Web UI：\n\n```bash\nnpx @modelcontextprotocol\u002Finspector node dist\u002Findex.js\n```\n\n这将在 `http:\u002F\u002Flocalhost:5173` 打开浏览器界面，您可以在其中：\n\n- 查看所有已注册的 tools、resources 和 prompts\n- 使用自定义输入调用工具并检查响应\n- 实时监控 JSON-RPC 消息流\n- 通过发送格式错误的请求测试错误处理\n\n### 常见调试问题\n\n| 问题 | 原因 | 解决方案 |\n|------|------|----------|\n| Server 未出现在 Claude Desktop 中 | 配置路径或 JSON 语法错误 | 验证 JSON，检查绝对路径 |\n| \"Tool not found\" 错误 | Server 在连接前未注册 tools | 在调用 `server.connect()` 之前注册 tools |\n| 工具调用超时 | 长时间运行的操作无进度 | 通过 `server.sendProgress()` 添加进度通知 |\n| stderr 输出破坏协议 | Console.log 写入 stdout（stdio transport） | 使用 stdio 时用 `console.error()` 进行日志记录 |\n| 空闲后连接断开 | Transport 超时 | 实现心跳或使用 HTTP transport |\n\n## 生产环境最佳实践\n\n1. **输入验证**：始终验证和清理工具输入。使用 Zod schema（TypeScript）或 Pydantic 模型（Python）进行严格的类型检查。\n\n2. **默认只读**：从只读访问开始。仅在明确需要时添加写入功能，并始终要求确认破坏性操作。\n\n3. **错误处理**：返回带有 `isError: true` 的结构化错误消息。永远不要暴露内部堆栈跟踪或数据库连接字符串。\n\n4. **日志记录**：记录所有工具调用的时间戳、输入和执行持续时间。使用 stdio transport 时使用 stderr 进行日志记录（而非 stdout）。\n\n5. **速率限制**：实现按工具的速率限制，防止失控的 AI 循环使后端服务不堪重负。\n\n6. **超时设置**：为所有工具处理程序设置执行超时。AI 模型可能会调用触发昂贵查询的工具——保护您的基础设施。\n\n7. **环境隔离**：使用环境变量进行所有配置。永远不要硬编码数据库 URL、API 密钥或文件路径。\n\n8. **版本管理**：遵循 MCP server 的语义版本控制。`initialize` 握手包含版本协商——破坏性更改需要主版本号升级。\n\n## 常见问题\n\n**问：MCP 和 function calling 有什么区别？**\n答：Function calling（OpenAI、Anthropic 等使用）在每个 API 请求中内联定义工具。MCP 将工具定义外部化到独立服务器中，任何 MCP 兼容的 host 都可以发现和使用。Function calling 是按请求的；MCP 是具有有状态会话的持久协议。\n\n**问：我可以在 Claude 以外的模型中使用 MCP 吗？**\n答：可以。MCP 是开放协议。截至 2026 年初，OpenAI、Google DeepMind 和 Microsoft 已在其平台中采用 MCP 支持。任何实现 MCP client 的 AI 应用程序都可以连接到任何 MCP server。\n\n**问：MCP 仅用于本地工具吗？**\n答：不是。虽然 stdio transport 设计用于本地服务器，但 HTTP+SSE 和 Streamable HTTP transport 支持远程 MCP server。您可以将 MCP server 部署为可通过网络访问的云服务。\n\n**问：MCP 如何处理身份验证？**\n答：该协议支持远程服务器的 OAuth 2.0。本地 stdio 服务器继承 host 进程的安全上下文。对于企业部署，MCP gateway 可以集中身份验证和授权。\n\n**问：我可以用什么语言构建 MCP server？**\n答：官方 SDK 支持 TypeScript、Python、Java、Kotlin、C# 和 Swift。社区 SDK 涵盖 Rust、Go、Ruby 和 PHP。该协议与语言无关——任何可以通过 stdio 或 HTTP 读写 JSON-RPC 的语言都可以实现 MCP server。\n\n**问：如何在不重启 host 的情况下更新 MCP server？**\n答：MCP 支持能力变更通知。当服务器的工具发生变化时，它可以发送 `notifications\u002Ftools\u002Flist_changed` 消息，提示 client 重新获取工具列表。对于 stdio 服务器，host 通常需要重启。HTTP 服务器可以在不重启 host 的情况下更新。","\u003Ch2 id=\"model-context-protocol-mcp\">什么是 Model Context Protocol (MCP)？\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>Model Context Protocol (MCP)\u003C\u002Fstrong> 是 Anthropic 创建的一项开放标准，定义了 AI 应用程序如何与外部数据源和工具进行通信。将 MCP 视为 \u003Cstrong>AI 集成的 USB-C\u003C\u002Fstrong>：就像 USB-C 提供了一个用于充电、数据传输和显示输出的通用连接器一样，MCP 提供了一个将 AI 模型连接到数据库、API、文件系统和任何其他服务的通用协议。MCP 消除了每个 AI 应用程序与每个工具之间自定义集成的需求。\u003C\u002Fp>\n\u003Cp>2026 年，MCP 已成为 AI 工具通信的主导标准。Gartner 预测，到 \u003Cstrong>2026 年底，40% 的企业应用程序将包含 AI 代理\u003C\u002Fstrong>，而 MCP 是使这在规模上变得可行的协议。在 MCP 出现之前，将 AI 模型连接到 N 个工具需要 N 个自定义集成。对于 M 个 AI 应用程序和 N 个工具，您需要 M x N 个集成适配器。MCP 将其减少为 M + N：每个 AI 应用程序实现一个 MCP client，每个工具实现一个 MCP server。\u003C\u002Fp>\n\u003Ch2 id=\"mcp-host-client-server-transport\">MCP 架构：Host、Client、Server 和 Transport\u003C\u002Fh2>\n\u003Cp>在编写任何代码之前，理解 MCP 架构至关重要。该协议定义了四个关键角色：\u003C\u002Fp>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>组件\u003C\u002Fth>\u003Cth>角色\u003C\u002Fth>\u003Cth>示例\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>\u003Cstrong>Host\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>终端用户交互的 AI 应用程序\u003C\u002Ftd>\u003Ctd>Claude Desktop、Cursor、VS Code Copilot\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Cstrong>Client\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>Host 内的 MCP 协议处理器\u003C\u002Ftd>\u003Ctd>内置于 Host 应用程序中\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Cstrong>Server\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>通过 MCP 公开 tools、resources 和 prompts\u003C\u002Ftd>\u003Ctd>您的自定义服务器（我们将构建的）\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>\u003Cstrong>Transport\u003C\u002Fstrong>\u003C\u002Ftd>\u003Ctd>Client 和 Server 之间的通信层\u003C\u002Ftd>\u003Ctd>stdio、HTTP+SSE、Streamable HTTP\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Cp>通信流程如下：\u003C\u002Fp>\n\u003Col>\n\u003Cli>\u003Cstrong>Host\u003C\u002Fstrong> 启动并为每个配置的服务器初始化 MCP \u003Cstrong>Client\u003C\u002Fstrong>。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Client\u003C\u002Fstrong> 通过 \u003Cstrong>Transport\u003C\u002Fstrong> 连接到 \u003Cstrong>Server\u003C\u002Fstrong>（本地使用 stdio，远程使用 HTTP）。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Client\u003C\u002Fstrong> 发送 \u003Ccode>initialize\u003C\u002Fcode> 请求，协商协议版本和能力。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Server\u003C\u002Fstrong> 响应其可用的 \u003Cstrong>tools\u003C\u002Fstrong>、\u003Cstrong>resources\u003C\u002Fstrong> 和 \u003Cstrong>prompts\u003C\u002Fstrong>。\u003C\u002Fli>\n\u003Cli>当 AI 模型需要外部数据或操作时，\u003Cstrong>Client\u003C\u002Fstrong> 调用相应的服务器方法。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Server\u003C\u002Fstrong> 执行操作并通过 JSON-RPC 2.0 消息返回结果。\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch3>Tools vs Resources vs Prompts\u003C\u002Fh3>\n\u003Cp>MCP server 可以公开三种类型的能力：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Tools\u003C\u002Fstrong> 是 AI 模型可以调用的函数。它们接受结构化输入并返回结构化输出。示例：\u003Ccode>query_database(sql: string)\u003C\u002Fcode> 或 \u003Ccode>send_email(to: string, subject: string, body: string)\u003C\u002Fcode>。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Resources\u003C\u002Fstrong> 是 AI 模型可以读取的数据。它们由 URI 标识并返回内容。示例：\u003Ccode>file:\u002F\u002F\u002Fpath\u002Fto\u002Fdocument.md\u003C\u002Fcode> 或 \u003Ccode>postgres:\u002F\u002Flocalhost\u002Fmydb\u002Fusers\u003C\u002Fcode>。\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Prompts\u003C\u002Fstrong> 是服务器提供的可重用提示模板。它们帮助标准化 AI 与服务器领域的交互方式。示例：用于 Jira MCP server 的 \u003Ccode>summarize_ticket\u003C\u002Fcode> 提示模板。\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"typescript-mcp-server\">逐步指南：在 TypeScript 中构建 MCP Server\u003C\u002Fh2>\n\u003Cp>让我们构建一个实用的 MCP server，提供用于查询 SQLite 数据库的工具。这是一个常见用例：给 AI 模型提供对应用程序数据的安全只读访问。\u003C\u002Fp>\n\u003Ch3>步骤 1：初始化项目\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-bash\">mkdir mcp-sqlite-server &amp;&amp; cd mcp-sqlite-server\nnpm init -y\nnpm install @modelcontextprotocol\u002Fsdk better-sqlite3\nnpm install -D typescript @types\u002Fnode @types\u002Fbetter-sqlite3\nnpx tsc --init\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>配置 \u003Ccode>tsconfig.json\u003C\u002Fcode>：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",\n    \"module\": \"Node16\",\n    \"moduleResolution\": \"Node16\",\n    \"outDir\": \".\u002Fdist\",\n    \"rootDir\": \".\u002Fsrc\",\n    \"strict\": true,\n    \"esModuleInterop\": true,\n    \"declaration\": true\n  },\n  \"include\": [\"src\u002F**\u002F*\"]\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>步骤 2：实现服务器\u003C\u002Fh3>\n\u003Cp>创建 \u003Ccode>src\u002Findex.ts\u003C\u002Fcode>：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-typescript\">import { McpServer } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fmcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol\u002Fsdk\u002Fserver\u002Fstdio.js\";\nimport Database from \"better-sqlite3\";\nimport { z } from \"zod\";\n\nconst db = new Database(process.env.DB_PATH || \".\u002Fdata.db\", {\n  readonly: true,\n});\n\nconst server = new McpServer({\n  name: \"sqlite-query\",\n  version: \"1.0.0\",\n});\n\nserver.tool(\n  \"query\",\n  \"对 SQLite 数据库执行只读 SQL 查询\",\n  {\n    sql: z.string().describe(\"要执行的 SQL SELECT 查询\"),\n  },\n  async ({ sql }) =&gt; {\n    const normalized = sql.trim().toUpperCase();\n    if (!normalized.startsWith(\"SELECT\")) {\n      return {\n        content: [{ type: \"text\", text: \"错误：仅允许 SELECT 查询。\" }],\n        isError: true,\n      };\n    }\n    try {\n      const rows = db.prepare(sql).all();\n      return {\n        content: [{ type: \"text\", text: JSON.stringify(rows, null, 2) }],\n      };\n    } catch (error) {\n      return {\n        content: [{ type: \"text\", text: `查询错误：${(error as Error).message}` }],\n        isError: true,\n      };\n    }\n  }\n);\n\nserver.tool(\n  \"list_tables\",\n  \"列出数据库中所有表及其架构\",\n  {},\n  async () =&gt; {\n    const tables = db\n      .prepare(\n        `SELECT name, sql FROM sqlite_master\n         WHERE type='table' AND name NOT LIKE 'sqlite_%'\n         ORDER BY name`\n      )\n      .all();\n    return {\n      content: [{ type: \"text\", text: JSON.stringify(tables, null, 2) }],\n    };\n  }\n);\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch3>步骤 3：构建并本地测试\u003C\u002Fh3>\n\u003Cpre>\u003Ccode class=\"language-bash\">npx tsc\necho '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-03-26\",\"capabilities\":{},\"clientInfo\":{\"name\":\"test\",\"version\":\"1.0\"}}}' | node dist\u002Findex.js\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>您将看到包含服务器能力的 JSON-RPC 响应。\u003C\u002Fp>\n\u003Ch3>步骤 4：用 Python 构建相同的服务器\u003C\u002Fh3>\n\u003Cp>对于 Python 开发者，以下是使用官方 MCP Python SDK 的等效实现：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-python\">import sqlite3\nimport json\nfrom mcp.server.fastmcp import FastMCP\n\nmcp = FastMCP(\"sqlite-query\")\nDB_PATH = \"data.db\"\n\n@mcp.tool()\ndef query(sql: str) -&gt; str:\n    \"\"\"对 SQLite 数据库执行只读 SQL 查询。\"\"\"\n    normalized = sql.strip().upper()\n    if not normalized.startswith(\"SELECT\"):\n        raise ValueError(\"仅允许 SELECT 查询。\")\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row\n    try:\n        cursor = conn.execute(sql)\n        rows = [dict(row) for row in cursor.fetchall()]\n        return json.dumps(rows, indent=2, default=str)\n    finally:\n        conn.close()\n\n@mcp.tool()\ndef list_tables() -&gt; str:\n    \"\"\"列出数据库中所有表及其架构。\"\"\"\n    conn = sqlite3.connect(DB_PATH)\n    conn.row_factory = sqlite3.Row\n    try:\n        cursor = conn.execute(\n            \"SELECT name, sql FROM sqlite_master \"\n            \"WHERE type='table' AND name NOT LIKE 'sqlite_%'\"\n        )\n        tables = [dict(row) for row in cursor.fetchall()]\n        return json.dumps(tables, indent=2)\n    finally:\n        conn.close()\n\nif __name__ == \"__main__\":\n    mcp.run(transport=\"stdio\")\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Ch2 id=\"claude-desktop\">连接到 Claude Desktop\u003C\u002Fh2>\n\u003Cp>Claude Desktop 原生支持 MCP server。要连接您的服务器，请编辑 Claude Desktop 配置文件：\u003C\u002Fp>\n\u003Cp>\u003Cstrong>macOS：\u003C\u002Fstrong> \u003Ccode>~\u002FLibrary\u002FApplication Support\u002FClaude\u002Fclaude_desktop_config.json\u003C\u002Fcode>\n\u003Cstrong>Windows：\u003C\u002Fstrong> \u003Ccode>%APPDATA%\\Claude\\claude_desktop_config.json\u003C\u002Fcode>\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  \"mcpServers\": {\n    \"sqlite-query\": {\n      \"command\": \"node\",\n      \"args\": [\"\u002Fabsolute\u002Fpath\u002Fto\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"DB_PATH\": \"\u002Fabsolute\u002Fpath\u002Fto\u002Fyour\u002Fdata.db\"\n      }\n    }\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>重启 Claude Desktop。您将在聊天界面中看到一个锤子图标，表示可用的 MCP 工具。现在您可以向 Claude 提问，例如“数据库中有哪些表？“或“按注册日期显示前 10 个用户”，Claude 将使用您的 MCP server 直接查询数据库。\u003C\u002Fp>\n\u003Ch2 id=\"cursor\">连接到 Cursor\u003C\u002Fh2>\n\u003Cp>Cursor 也支持 MCP server。在项目根目录的 \u003Ccode>.cursor\u002Fmcp.json\u003C\u002Fcode> 中添加配置：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  \"mcpServers\": {\n    \"sqlite-query\": {\n      \"command\": \"node\",\n      \"args\": [\".\u002Fdist\u002Findex.js\"],\n      \"env\": {\n        \"DB_PATH\": \".\u002Fdata.db\"\n      }\n    }\n  }\n}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>保存后重启 Cursor。MCP 工具将出现在 AI 助手面板中，可在代码生成和调试会话期间调用。\u003C\u002Fp>\n\u003Ch2 id=\"mcp-server\">测试和调试您的 MCP Server\u003C\u002Fh2>\n\u003Ch3>使用 MCP Inspector\u003C\u002Fh3>\n\u003Cp>MCP Inspector 是官方调试工具。它提供了与服务器交互的 Web UI：\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">npx @modelcontextprotocol\u002Finspector node dist\u002Findex.js\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>这将在 \u003Ccode>http:\u002F\u002Flocalhost:5173\u003C\u002Fcode> 打开浏览器界面，您可以在其中：\u003C\u002Fp>\n\u003Cul>\n\u003Cli>查看所有已注册的 tools、resources 和 prompts\u003C\u002Fli>\n\u003Cli>使用自定义输入调用工具并检查响应\u003C\u002Fli>\n\u003Cli>实时监控 JSON-RPC 消息流\u003C\u002Fli>\n\u003Cli>通过发送格式错误的请求测试错误处理\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3>常见调试问题\u003C\u002Fh3>\n\u003Ctable>\u003Cthead>\u003Ctr>\u003Cth>问题\u003C\u002Fth>\u003Cth>原因\u003C\u002Fth>\u003Cth>解决方案\u003C\u002Fth>\u003C\u002Ftr>\u003C\u002Fthead>\u003Ctbody>\n\u003Ctr>\u003Ctd>Server 未出现在 Claude Desktop 中\u003C\u002Ftd>\u003Ctd>配置路径或 JSON 语法错误\u003C\u002Ftd>\u003Ctd>验证 JSON，检查绝对路径\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>“Tool not found” 错误\u003C\u002Ftd>\u003Ctd>Server 在连接前未注册 tools\u003C\u002Ftd>\u003Ctd>在调用 \u003Ccode>server.connect()\u003C\u002Fcode> 之前注册 tools\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>工具调用超时\u003C\u002Ftd>\u003Ctd>长时间运行的操作无进度\u003C\u002Ftd>\u003Ctd>通过 \u003Ccode>server.sendProgress()\u003C\u002Fcode> 添加进度通知\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>stderr 输出破坏协议\u003C\u002Ftd>\u003Ctd>Console.log 写入 stdout（stdio transport）\u003C\u002Ftd>\u003Ctd>使用 stdio 时用 \u003Ccode>console.error()\u003C\u002Fcode> 进行日志记录\u003C\u002Ftd>\u003C\u002Ftr>\n\u003Ctr>\u003Ctd>空闲后连接断开\u003C\u002Ftd>\u003Ctd>Transport 超时\u003C\u002Ftd>\u003Ctd>实现心跳或使用 HTTP transport\u003C\u002Ftd>\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\n\u003Ch2 id=\"\">生产环境最佳实践\u003C\u002Fh2>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>输入验证\u003C\u002Fstrong>：始终验证和清理工具输入。使用 Zod schema（TypeScript）或 Pydantic 模型（Python）进行严格的类型检查。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>默认只读\u003C\u002Fstrong>：从只读访问开始。仅在明确需要时添加写入功能，并始终要求确认破坏性操作。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>错误处理\u003C\u002Fstrong>：返回带有 \u003Ccode>isError: true\u003C\u002Fcode> 的结构化错误消息。永远不要暴露内部堆栈跟踪或数据库连接字符串。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>日志记录\u003C\u002Fstrong>：记录所有工具调用的时间戳、输入和执行持续时间。使用 stdio transport 时使用 stderr 进行日志记录（而非 stdout）。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>速率限制\u003C\u002Fstrong>：实现按工具的速率限制，防止失控的 AI 循环使后端服务不堪重负。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>超时设置\u003C\u002Fstrong>：为所有工具处理程序设置执行超时。AI 模型可能会调用触发昂贵查询的工具——保护您的基础设施。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>环境隔离\u003C\u002Fstrong>：使用环境变量进行所有配置。永远不要硬编码数据库 URL、API 密钥或文件路径。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003Cli>\n\u003Cp>\u003Cstrong>版本管理\u003C\u002Fstrong>：遵循 MCP server 的语义版本控制。\u003Ccode>initialize\u003C\u002Fcode> 握手包含版本协商——破坏性更改需要主版本号升级。\u003C\u002Fp>\n\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Ch2 id=\"\">常见问题\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>问：MCP 和 function calling 有什么区别？\u003C\u002Fstrong>\n答：Function calling（OpenAI、Anthropic 等使用）在每个 API 请求中内联定义工具。MCP 将工具定义外部化到独立服务器中，任何 MCP 兼容的 host 都可以发现和使用。Function calling 是按请求的；MCP 是具有有状态会话的持久协议。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：我可以在 Claude 以外的模型中使用 MCP 吗？\u003C\u002Fstrong>\n答：可以。MCP 是开放协议。截至 2026 年初，OpenAI、Google DeepMind 和 Microsoft 已在其平台中采用 MCP 支持。任何实现 MCP client 的 AI 应用程序都可以连接到任何 MCP server。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：MCP 仅用于本地工具吗？\u003C\u002Fstrong>\n答：不是。虽然 stdio transport 设计用于本地服务器，但 HTTP+SSE 和 Streamable HTTP transport 支持远程 MCP server。您可以将 MCP server 部署为可通过网络访问的云服务。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：MCP 如何处理身份验证？\u003C\u002Fstrong>\n答：该协议支持远程服务器的 OAuth 2.0。本地 stdio 服务器继承 host 进程的安全上下文。对于企业部署，MCP gateway 可以集中身份验证和授权。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：我可以用什么语言构建 MCP server？\u003C\u002Fstrong>\n答：官方 SDK 支持 TypeScript、Python、Java、Kotlin、C# 和 Swift。社区 SDK 涵盖 Rust、Go、Ruby 和 PHP。该协议与语言无关——任何可以通过 stdio 或 HTTP 读写 JSON-RPC 的语言都可以实现 MCP server。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>问：如何在不重启 host 的情况下更新 MCP server？\u003C\u002Fstrong>\n答：MCP 支持能力变更通知。当服务器的工具发生变化时，它可以发送 \u003Ccode>notifications\u002Ftools\u002Flist_changed\u003C\u002Fcode> 消息，提示 client 重新获取工具列表。对于 stdio 服务器，host 通常需要重启。HTTP 服务器可以在不重启 host 的情况下更新。\u003C\u002Fp>\n","zh","b0000000-0000-0000-0000-000000000001",true,"2026-03-28T10:44:38.523599Z","用 TypeScript 和 Python 构建 MCP server 的分步教程。连接到 Claude Desktop 或 Cursor，使用 MCP Inspector 测试，并部署到生产环境。","mcp server 教程",null,"index, follow",[21,26],{"id":22,"name":23,"slug":24,"created_at":25},"c0000000-0000-0000-0000-000000000008","AI","ai","2026-03-28T10:44:21.513630Z",{"id":27,"name":28,"slug":29,"created_at":25},"c0000000-0000-0000-0000-000000000002","TypeScript","typescript","工程",[32,38,44],{"id":33,"title":34,"slug":35,"excerpt":36,"locale":12,"category_name":30,"published_at":37},"d0000000-0000-0000-0000-000000000668","为什么Bali在2026年正在成为东南亚的影响力科技中心","weishenme-bali-2026-zhengzai-chengwei-dongnanya-yingxiangli-keji-zhongxin","Bali在东南亚创业生态系统中排名第16位。随着Web3构建者、AI可持续发展初创公司和生态旅游科技公司的集中，该岛正在打造区域影响力科技之都的独特定位。","2026-03-28T10:44:48.898750Z",{"id":39,"title":40,"slug":41,"excerpt":42,"locale":12,"category_name":30,"published_at":43},"d0000000-0000-0000-0000-000000000667","ASEAN数据保护拼图：开发者合规清单","asean-shuju-baohu-pintu-kaifazhe-heguiqingdan","七个ASEAN国家现已拥有全面的数据保护法律，各自具有不同的同意模型、本地化要求和处罚结构。这是一份为构建多国应用程序的开发者准备的实用合规清单。","2026-03-28T10:44:48.893467Z",{"id":45,"title":46,"slug":47,"excerpt":48,"locale":12,"category_name":30,"published_at":49},"d0000000-0000-0000-0000-000000000666","Indonesia 290亿美元数字化转型：软件公司的机遇","indonesia-290yi-meiyuan-shuzihua-zhuanxing-ruanjian-gongsi-jiyu","Indonesia IT服务市场预计在2026年达到290.3亿美元，高于2025年的243.7亿美元。云基础设施、AI、电子商务和数据中心正在推动东南亚最快的增长。","2026-03-28T10:44:48.875457Z",{"id":13,"name":51,"slug":52,"bio":53,"photo_url":18,"linkedin":18,"role":54,"created_at":55,"updated_at":55},"Open Soft Team","open-soft-team","The engineering team at Open Soft, building premium software solutions from Bali, Indonesia.","Engineering Team","2026-03-28T08:31:22.226811Z"]