mcpdo 连接客户端
社区译文;来源: MCP 80041ab0
mcpdo 是一个实验性命令行客户端,与 mcp-inspector 一同发布在 @modelcontextprotocol/inspector 包中。CLI 客户端是连接、运行一个 --method 然后断开,而 mcpdo 会连接一次并保持连接打开,因此你可以从任意 shell 针对它运行多条命令,就像 ssh-agent 保持密钥已加载那样。
mcp-inspector --cli | mcpdo | |
|---|---|---|
| 生命周期 | 连接、执行一个 --method、断开 | 连接一次,运行多条命令 |
| 状态 | 各次运行之间无状态 | 由守护进程持有的具名连接 |
| 最适合 | CI 断言、每次运行一个 JSON 块 | 探索服务器、代理使用工具、在单个会话上走多步流程(任务、订阅、elicitation) |
连接由本地后台守护进程 mcpdod 持有,mcpdo 按需启动它,并在最后一个连接关闭后停止它。你永远不需要手动启动它。它暴露什么、如何受到保护,见 mcpdo 连接守护进程。
观看 mcpdo 教程视频。
安装
mcpdo 是同一个包中的第二个 bin,因此请全局安装该包,或用 npx -p 运行它:
npm install -g @modelcontextprotocol/inspector
mcpdo --help
# or without installing
npx -p @modelcontextprotocol/inspector mcpdo --help快速开始
mcpdo servers/list # catalog entries you can connect
mcpdo connect my-server # connect a catalog entry
mcpdo @my-server tools/list
mcpdo @my-server tools/call echo message:=hi
mcpdo @my-server resources/read file:///tmp/notes.txt
mcpdo connections/list # what's open
mcpdo disconnect my-servermcpdo help 或 mcpdo <command> --help 会打印完整、权威的命令与 flag 列表。
选择要连接的对象
connect 接受 catalog 条目名或临时目标:
mcpdo connect my-server # from the default catalog
mcpdo connect my-server --config ./mcp.json # from a read-only config file
mcpdo connect https://example.com/mcp # ad-hoc HTTP/SSE server
mcpdo connect node build/index.js # ad-hoc stdio servercatalog 和 --config 的行为与其他客户端完全一致(参见配置与 flag):默认 catalog 是 ~/.mcp-inspector/mcp.json,可用 --catalog 或 MCP_CATALOG_PATH 覆盖。servers/list 和 servers/show <name> 从磁盘读取条目。connections/* 显示守护进程当前持有的内容。没有任何命令用于编辑 catalog;请直接编辑文件。
stdio 服务器运行时使用执行 connect 的那个 shell 的工作目录和命令解析环境,而不是守护进程的,因此相对路径和裸命令名会符合你的预期。
定位一个连接
catalog 连接以其实目名命名。临时连接以其第一个 token(node、docker 或 URL 本身)命名,除非你在连接时用 @name 为它命名:
mcpdo connect @api https://example.com/mcp在每条命令上用 @name 或 --connection <name>(简写 --conn)指定连接。以 URL 命名的连接只能用 --conn <url> 定位,因为 @name 只接受字母、数字、_、. 和 -:
mcpdo @my-server tools/list
mcpdo --conn my-server tools/list省略名称会回退到最近使用的连接,但仅在交互式 TTY 上如此。在脚本或代理中,stdin 不是 TTY,此时不带连接名的命令会报错,从而确保后台任务绝不会作用在你上次使用的那个服务器上。设置 MCP_ALLOW_DEFAULT_CONNECTION=1 可以允许这种回退。
连接会自愈:中断的传输(过期 HTTP 会话、退出的 stdio 子进程)会在下次使用时用已存储的凭据透明地重新建立。只有 auth_required 错误需要你重新运行 connect。
一个连接一次只运行一个调用。来自其他 shell 的命令会排在进行中的调用之后,而当某个调用因信息征询挂起时,该连接上的新调用会被拒绝,直到它被回答。长时间调用不会阻塞其他连接。
任务
需要任务支持的工具会被普通的 tools/call 拒绝;加上 --task 即可发起任务增强调用。它仍会阻塞直到任务完成,然后打印最终结果:
mcpdo @my-server tools/call --task start_job size:=large如果任务进入 input_required,其问题会像任何其他信息征询一样被处理。
输出
| Flag | 输出 |
|---|---|
--format text(默认) | 人类可读;在 TTY 上带 ANSI 样式,除非设置了 --plain 或 NO_COLOR。 |
--format json | 美化打印的负载,不带 { result } 信封。适用于脚本和代理。 |
全局 flag 有 --format、--plain、--connection / --conn、--catalog / --config 和 --stored-auth-only。它们可以放在子命令之前或之后,但必须在任何 -- 之前。@name 简写必须放在子命令之前。
面向终端的文本(结果、信息征询提示、守护进程错误)会被剥离控制字符,因此服务器无法改写你的终端。--format json 保持原样。
授权
mcpdo 与其他 Inspector 客户端共享 oauth.json 和机密存储,因此你已在别处授权过的服务器连接时无需提示。OAuth 在连接时运行。会话中途的 step-up 由一次性 CLI 处理,而不是 mcpdo。
| 命令 | 作用 |
|---|---|
mcpdo connect <name> --relogin(-r) | 在连接前清除该服务器已存储的 token(仅 HTTP/SSE),若服务器要求身份验证则会重新登录。 |
mcpdo disconnect <name> --clear-auth(-c) | 关闭连接并清除其已存储的 token,使下一次 connect 重新登录。 |
mcpdo auth/list | 已存储的凭据,每条都标注其"以何名被知"的 catalog 或连接名,并在某个打开连接持有时标为 ● live。 |
mcpdo auth/clear <url-or-name> | 按存储 URL 或友好名称清除一条已存储的凭据。--all --yes 清除全部。 |
mcpdo auth/ema-login / auth/ema-status / auth/ema-logout | 企业托管授权:登录 IdP 一次,之后静默连接 EMA 服务器。 |
当需要浏览器登录,而 stdin 和 stderr 都不是 TTY(且 MCP_AUTO_OPEN_ENABLED 未被强制开启)时,connect 会立即以退出码 0 结束,并返回 pendingAuth: true 和一个 authUrl。请把该 URL 转交给将要登录的人。一旦其完成登录,连接会自行完成:下一条真实的命令会完成该连接,其间 connections/list 会报告 pendingAuthSignedIn。不要为了修复待处理的登录而反复重连。
在没有操作系统钥匙串的主机上,mcpdo 会把 token 存入共享的 secrets.json 文件,而绝不存入内存,因为它的命令与守护进程是不同进程。除非你提供密钥,否则该文件是明文;参见机密存储于何处。
信息征询
当服务器在调用中途提问时(legacy 的 elicitation/create、modern 的 MRTR 轮次,或进入 input_required 的任务):
- 在交互式 TTY 上,
mcpdo会就地提示。表单模式会为每个字段渲染一条提示,并带一个复核步骤。URL 模式会打印 URL 并等待你确认已完成。 - 从脚本或代理中(
--format json,或没有 TTY),命令会返回带elicitationId的elicitationPending,而该调用会挂起在守护进程上。可从任意 shell 回答它:
mcpdo elicitation/respond <elicitationId> approved:=true # form fields as key:=value or JSON
mcpdo elicitation/respond <elicitationId> --done # URL mode: I finished
mcpdo elicitation/respond <elicitationId> --decline # form mode only
mcpdo elicitation/respond <elicitationId> --cancel # either mode挂起的信息征询会在 10 分钟后被取消,且一个连接同时只持有一个;在它被回答之前,该连接上的其他调用会被拒绝。URL 模式绝不会自动接受。若要完全避免服务器提问,可用 --elicit off 连接。--elicit url、form 或 both(默认)选择声明哪些模式。
协议世代
mcpdo 与其他客户端协商相同的协议世代。connect --era legacy|auto|modern 会覆盖 catalog 条目的 protocolEra,并且是为临时目标设置它的唯一方式。connections/list 会为每个连接标注 [legacy] 或 [modern],connections/show <name> 会给出协商后的版本、服务器信息、能力,以及(在探测过服务器时)受支持版本列表。
守护进程
| 命令 | 作用 |
|---|---|
mcpdo daemon status | 是否有守护进程在运行,以及它的连接和空闲倒计时。 |
mcpdo daemon stop | 关闭所有连接并停止守护进程。 |
eval "$(mcpdo private)" | 让当前 shell 拥有自己的守护进程和连接。 |
默认情况下,你运行 mcpdo 的每个 shell 共享同一个守护进程,因此在一个终端中打开的连接可以在另一个终端使用。mcpdo private 会导出 MCP_INSPECTOR_DAEMON_DIR 和 MCP_INSPECTOR_DAEMON_TOKEN,使当前 shell 获得独立的守护进程。这只隔离连接,并不是防范以你的身份运行的其他进程的安全边界。
守护进程会在最后一个连接关闭后大约一分钟退出。升级前启动的守护进程会继续运行旧代码直到那时,因此升级包之后请运行 mcpdo daemon stop。
隔离不受信任的 stdio 服务器
守护进程的 token 控制谁能命令守护进程,而不是服务器能做什么。stdio 服务器以你的完整用户权限运行。若要约束一个你不完全信任的服务器,请把 stdio 命令变成一个容器:
mcpdo connect @sandboxed -- docker run -i --rm --network none -v "$PWD:/work:ro" <server-image>如果没有 @sandboxed,该连接会被命名为 docker。
请按服务器需要调整网络和挂载 flag。HTTP 和 SSE 服务器不运行本地代码,因此不需要进程隔离。
环境变量
mcpdo 读取与其他客户端相同的 catalog、存储和机密存储变量(参见环境变量),另外还有:
| 变量 | 作用 |
|---|---|
MCP_INSPECTOR_DAEMON_DIR | 存放守护进程 socket、锁、token 和日志的目录。设置了 MCP_STORAGE_DIR 时默认为它,否则为 ~/.mcp-inspector。由 mcpdo private 设置。 |
MCP_INSPECTOR_DAEMON_TOKEN | 向守护进程出示或用于启动守护进程的 IPC token。未设置时,启动守护进程的那条 mcpdo 命令会生成一个,守护进程将其发布到 mcpdod.token。由 mcpdo private 设置。 |
MCP_ALLOW_DEFAULT_CONNECTION | 设为 1 时,即使 stdin 不是 TTY,不带 @name / --connection 的命令也会使用最近使用的连接。 |
在编码代理中使用 mcpdo
该包附带一个 agent skill,教会代理驱动 mcpdo:它持有的连接会扩展代理的工具集,并且它知道要转交登录 URL 并回答挂起的信息征询。mcpdo agent-help 打印该指南,mcpdo agent-help --skill-path 打印可安装 skill 文件的路径,mcpdo agent-help --instructions 打印一段可追加到项目 CLAUDE.md 或 AGENTS.md 的内容。