agentmentoragentmentor

第 05 节:stdio、HTTP 和一次连接的生命周期

本节 objectives:

  • 能区分 stdio 和 Streamable HTTP 的适用场景。
  • 能解释 initialize、capability negotiation、operation、shutdown。
  • 能读懂一个最小 MCP server 启动配置。

先修:知道 server 会暴露 tools/resources/prompts | 上一节 << 04 | 下一节 06 >>

协议不是"代码跑了就行"

前几节你写了 server.connect(transport)。这行看起来像普通启动代码,但背后有协议生命周期。

MCP spec 把连接生命周期分成 initialization、operation、shutdown:初始化阶段协商协议版本和能力,运行阶段正常收发请求,关闭阶段优雅结束连接。1 这也是为什么一个 server 不只是"开个 HTTP endpoint"或"跑个脚本"。

讲解

本地入门常用 stdio。host 启动你的 server 进程,server 从 stdin 收 JSON-RPC 消息,从 stdout 回消息。这适合本地文件、CLI、repo 工具,也天然和用户机器上的权限边界贴近。

远程或多客户端场景会用 HTTP transport。HTTP 更适合部署成服务,但也带来认证、Host/Origin 校验、网络暴露、session 管理等问题。官方 SDK 文档在 HTTP 相关部分反复强调 Host/Origin 验证和 auth 不能当作附属品。2

生命周期可以这样记:

text
initialize: client 问 server 支持什么,双方确认版本和 capabilitiesoperation: list tools/resources/prompts, call tool, read resourceshutdown: 连接结束,清理状态

capability negotiation 很重要。一个 server 不是靠 README 告诉 host 自己有什么,而是在连接时把能力暴露给 client。

跟我做一遍(worked example)

一个本地 stdio server 的配置通常长这样:

json
{  "mcpServers": {    "notes-lab": {      "command": "node",      "args": ["/absolute/path/to/mcp-notes-lab/server.mjs"]    }  }}

读这个配置:

  • notes-lab 是 host 里显示的 server 名。
  • command 是 host 要启动的进程。
  • args 是传给进程的参数。
  • 这不是 HTTP URL。host 会直接 spawn 本地进程,用 stdio 通信。

如果你的 server 需要环境变量,不要硬编码 token:

json
{  "mcpServers": {    "issue-tracker": {      "command": "node",      "args": ["/absolute/path/to/issue-server/server.mjs"],      "env": {        "ISSUE_API_BASE": "https://issues.example.com"      }    }  }}

密钥要走 host 支持的安全配置方式或本机环境变量,不要写进课程、仓库、示例配置。

换你补全(faded example)

你写了一个 server,文件在 /Users/you/tools/project-mcp/server.mjs,希望 host 以 project-tools 名字启动它。请补全:

json
{  "mcpServers": {    "__________": {      "command": "__________",      "args": ["____________________________"]    }  }}

参考答案:

json
{  "mcpServers": {    "project-tools": {      "command": "node",      "args": ["/Users/you/tools/project-mcp/server.mjs"]    }  }}

关键是绝对路径。很多 host 从自己的工作目录启动子进程,相对路径可能在你的终端里能跑,在 host 里却找不到。

小结 + 通向下一节

stdio 适合本地、单用户、由 host 启动的工具;HTTP 适合远程服务,但安全和部署复杂度更高。无论哪种 transport,连接都要经过初始化、能力协商、运行、关闭。

下一节用 Inspector 把你写的 server 真正测一遍。能被 host 发现之前,先让测试工具发现它。

Footnotes

  1. MCP Lifecycle Specification — https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle

  2. MCP TypeScript SDK — https://github.com/modelcontextprotocol/typescript-sdk

练习

Level 1: 为你的 mcp-notes-lab/server.mjs 写一个 mcp.json 草稿。暂时不用接入真实 host。

提示 1

本地 server 默认信任"用户机器上这个 host 启动了我"。

提示 2

远程 server 要面对网络里的其他调用者。

提示 3

能本地解决的个人工具,先别急着远程化。

自评