文档中心 / SDK 教程 / 定制篇

集成 MCP

Model Context Protocol(MCP)把「外部系统能力」封装成标准工具接口,让模型通过统一协议读写仓库、文档、数据库等。Cody SDK 在进程内连接 MCP 服务器,把远端或本地进程暴露的工具并入 Agent 的工具集;你也可以绕过对话,直接列出并调用这些工具。

本篇假设你已按第 01 篇设置环境变量(模型使用 qwen3.5-plus):

export CODY_MODEL=qwen3.5-plus
export CODY_MODEL_API_KEY=sk-xxx
export CODY_MODEL_BASE_URL=https://coding.dashscope.aliyuncs.com/v1

两种传输:stdio 与 HTTP

Cody 支持两类 MCP 传输,分别对应「本地子进程」与「远程 HTTP 端点」:

传输Builder 方法典型场景
stdio mcp_stdio_server() 本机启动 npx、可执行文件等子进程,通过标准输入输出与 MCP 通信(例如官方 GitHub MCP 包)。
HTTP mcp_http_server() 连接云托管或自建 URL,用请求头传递鉴权(例如飞书 MCP 网关)。
与模型无关。 MCP 只负责工具侧;演示仍用通义千问 qwen3.5-plus。若要在代码里显式指定模型,可用 Cody().model("qwen3.5-plus").base_url(...).api_key(...) 链式配置。

stdio 示例:接入 GitHub MCP

下面是一段可直接运行的脚本:用 npx 拉取 @modelcontextprotocol/server-github,把 GITHUB_TOKEN 注入子进程环境,并开启首次 run() 时自动启动 MCP。跑通后再看各参数含义。

# 需要本机已安装 Node.js / npx
import asyncio

from cody.sdk import Cody


async def main() -> None:
    client = (
        Cody()
        .workdir(".")
        .mcp_stdio_server(
            name="github",
            command="npx",
            args=["-y", "@modelcontextprotocol/server-github"],
            env={"GITHUB_TOKEN": "ghp_xxx"},  # 换成你的 fine-grained 或 classic token
        )
        .auto_start_mcp(True)
        .build()
    )

    async with client:
        result = await client.run("列出我最近的 GitHub Pull Request,简要说明每个 PR 的状态。")
        print(result.output)


if __name__ == "__main__":
    asyncio.run(main())

这段代码在做什么

安全提示。 不要把真实 token 写进仓库;开发时用环境变量拼接 env={"GITHUB_TOKEN": os.environ["GITHUB_TOKEN"]} 更安全。下一篇「安全与控制」会进一步收紧权限与路径策略。

HTTP 示例:飞书 MCP 端点

远程 MCP 只需 URL 与可选请求头。飞书(Lark)提供托管端点时,通常用自定义头传递 UAT / 令牌:

import asyncio

from cody.sdk import Cody


async def main() -> None:
    client = (
        Cody()
        .workdir(".")
        .mcp_http_server(
            name="feishu",
            url="https://mcp.feishu.cn/mcp",
            headers={"X-Lark-MCP-UAT": "token"},  # 按飞书文档替换为真实令牌
        )
        .build()
    )

    # 未设置 auto_start_mcp 时须显式启动(也可改为链式 .auto_start_mcp(True))
    async with client:
        await client.start_mcp()
        result = await client.run("根据我最近的飞书文档,总结本周行动项。")
        print(result.output)


if __name__ == "__main__":
    asyncio.run(main())

若省略上面的 start_mcp(),请改为在 Builder 上链式 .auto_start_mcp(True),否则首次 run() 不会替你连接 MCP(见下文对比表)。

多服务器组合

多个 mcp_stdio_server / mcp_http_server 可以叠在同一 Builder 上,Agent 会同时看到各服务器导出的工具,由模型自行选用:

client = (
    Cody()
    .workdir(".")
    .mcp_stdio_server(
        name="github",
        command="npx",
        args=["-y", "@modelcontextprotocol/server-github"],
        env={"GITHUB_TOKEN": "ghp_xxx"},
    )
    .mcp_http_server(
        name="feishu",
        url="https://mcp.feishu.cn/mcp",
        headers={"X-Lark-MCP-UAT": "token"},
    )
    .auto_start_mcp(True)
    .build()
)
调试建议。 若只想确认两端是否都连上,可对 Agent 提问「当前有哪些 MCP 工具?」或下文直接用 mcp_list_tools() 打印清单。

auto_start_mcpawait client.start_mcp()

二者解决同一问题(拉起 MCP 连接),时机不同:

方式行为适用
auto_start_mcp(True) 首次 run() / stream() 前由 SDK 自动调用内部启动逻辑。 大多数应用代码,少写样板。
await client.start_mcp() 你在 async with client 体内显式控制启动时刻。 需要在对话前预热、先 mcp_list_tools、或严格编排启动顺序时。
client = (
    Cody()
    .workdir(".")
    .mcp_stdio_server(
        name="github",
        command="npx",
        args=["-y", "@modelcontextprotocol/server-github"],
    )
    .build()
)

async with client:
    await client.start_mcp()  # 手动启动,不依赖 auto_start_mcp
    # … 此处可安全调用 mcp_list_tools / mcp_call …

运行时:add_mcp_server

配置在构建阶段未知时(例如按租户动态下发),可在已进入异步上下文后追加服务器。transport"stdio""http";stdio 用 command / args / env,HTTP 用 url / headers

async with client:
    await client.add_mcp_server(
        name="notion",
        transport="http",
        url="https://example.com/mcp",
        headers={"Authorization": "Bearer ..."},
    )
    await client.add_mcp_server(
        name="gh",
        transport="stdio",
        command="npx",
        args=["-y", "@modelcontextprotocol/server-github"],
        env={"GITHUB_TOKEN": "ghp_xxx"},
    )

SDK 会把新服务器写入 core 配置并立即尝试启动;默认 transportstdio,因此纯 GitHub 场景也可省略 transport=,与仓库内 cody/sdk/examples/mcp_demo.py 一致。

mcp_list_toolsmcp_call

不必经过大模型,你也可以像调用普通异步 API 一样使用 MCP:mcp_list_tools() 返回已连接服务器上的工具元数据;mcp_call 的第一个参数为 "服务器名/工具名",第二个为 JSON 参数字典。

import asyncio

from cody.sdk import Cody


async def main() -> None:
    client = (
        Cody()
        .workdir(".")
        .mcp_stdio_server(
            name="github",
            command="npx",
            args=["-y", "@modelcontextprotocol/server-github"],
        )
        .build()
    )

    async with client:
        await client.start_mcp()

        tools = await client.mcp_list_tools()
        # 每项含 name(含 server/ 前缀)、description、input_schema、server 等

        result = await client.mcp_call("github/list-repos", {"per_page": 5})
        print(result)


if __name__ == "__main__":
    asyncio.run(main())
若未配置或未启动任何 MCP,mcp_list_tools() 返回空列表;此时调用 mcp_call 会触发配置错误。请确保已 start_mcp() 或已完成带 MCP 的 run()

小结

你现在已经能够:用 stdio 跑 GitHub 官方 MCP、用 HTTP 接飞书类远程端点、把多台服务器拼进同一客户端、在自动与手动启动之间做选择,并在运行时用 add_mcp_server 扩展连接,用 mcp_list_tools / mcp_call 做直连调试。

下一篇 09. 安全与控制 将把 Agent、工具与 MCP 放进更严格的安全与策略语境里——建议连贯阅读。

← 上一篇 使用 Skills