注意
这是一个不断发展的功能。 有关正在进行的讨论,请参阅问题 #36。
什么是 MCP?
模型上下文协议(MCP) 是将 AI 助手连接到外部工具和数据源的开放标准。 MCP 服务器可以:
- 执行代码或脚本
- 查询数据库
- 访问文件系统
- 调用外部 API
- 等等
服务器类型
SDK 支持两种类型的 MCP 服务器:
| 类型 | Description | 用例 |
|---|---|---|
| Local/Stdio | 作为子进程运行,通过 stdin/stdout 进行通信 | 本地工具、文件访问、自定义脚本 |
| HTTP/SSE | 通过 HTTP 访问的远程服务器 | 共享服务、云托管工具 |
Configuration
检查配置和生命周期
session.rpc.mcp.listConfigured() 是无参数的被动库存读取。
它不会启动或重启服务器、进行身份验证、应用沙盒策略或等待服务器启动。 配置发现和策略筛选确定哪些服务器会出现及其 enabled 值。
此实验性 RPC 需要 SDK 与运行时发布版本对齐。 其先前的预发行版响应允许省略 live;使用所需生命周期协定的 SDK 不支持这种较旧的响应形式。 提供外部运行时时,请将其与 SDK 一起更新。 整体协议版本保持不变,不标识此实验性合同修订。
每个条目都包含 live.status。 没有具体化运行时服务器的已配置服务器会报告现有 状态,即使 为 。 已被显式停止的运行时服务器会报告 stopped。 实例化服务器报告其实际生命周期,包括pending、connected、needs-auth和failed;故障包括live.error(如果可用)。
配置和生命周期描述了不同的事实。 如果服务器的 URL、身份验证或配置源在旧连接保持活动状态时发生更改,清单仍会报告该连接的实际生命周期。
connected 状态并不意味着已应用最新配置。
运行时拥有此观测结果;客户端不能仅根据服务器名称替换缓存状态。
Inventory 会对并发图替换进行有限次数的重试,如果无法获取一致的快照,则返回错误。 它从不省略 live 来隐藏图竞争条件。
仅名称的 startServer 或 restartServer 在冷会话恢复后无需先调用 list,仅解析并初始化所请求的服务器。
这包括用户和插件配置,以及通过 githubMcpToolConfig 配置的内置 GitHub 服务器配置。 它不会启动其他已配置服务器,也不会覆盖已禁用状态、身份验证要求、沙盒策略或配置源优先级。
Node.js/TypeScript
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
model: "gpt-5",
mcpServers: {
// Local MCP server (stdio)
"my-local-server": {
type: "local",
command: "node",
args: ["./mcp-server.js"],
env: { DEBUG: "true" },
cwd: "./servers",
tools: ["*"], // "*" = all tools, [] = none, or list specific tools
timeout: 30000,
},
// Remote MCP server (HTTP)
"github": {
type: "http",
url: "https://api.githubcopilot.com/mcp/",
headers: { "Authorization": "Bearer ${TOKEN}" },
tools: ["*"],
},
},
});
Python
import asyncio
from copilot import CopilotClient
from copilot.session import PermissionHandler
async def main():
client = CopilotClient()
await client.start()
session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-5", mcp_servers={
# Local MCP server (stdio)
"my-local-server": {
"type": "local",
"command": "python",
"args": ["./mcp_server.py"],
"env": {"DEBUG": "true"},
"cwd": "./servers",
"tools": ["*"],
"timeout": 30000,
},
# Remote MCP server (HTTP)
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {"Authorization": "Bearer ${TOKEN}"},
"tools": ["*"],
},
})
response = await session.send_and_wait("List my recent GitHub notifications")
print(response.data.content)
await client.stop()
asyncio.run(main())
Go
package main
import (
"context"
"log"
copilot "github.com/github/copilot-sdk/go"
)
func main() {
ctx := context.Background()
client := copilot.NewClient(nil)
if err := client.Start(ctx); err != nil {
log.Fatal(err)
}
defer client.Stop()
session, err := client.CreateSession(ctx, &copilot.SessionConfig{
Model: "gpt-5",
MCPServers: map[string]copilot.MCPServerConfig{
"my-local-server": copilot.MCPStdioServerConfig{
Command: "node",
Args: []string{"./mcp-server.js"},
Tools: []string{"*"},
},
},
})
if err != nil {
log.Fatal(err)
}
defer session.Disconnect()
// Use the session...
}
.NET
using GitHub.Copilot;
await using var client = new CopilotClient();
await using var session = await client.CreateSessionAsync(new SessionConfig
{
Model = "gpt-5",
McpServers = new Dictionary<string, McpServerConfig>
{
["my-local-server"] = new McpStdioServerConfig
{
Command = "node",
Args = new List<string> { "./mcp-server.js" },
Tools = new List<string> { "*" },
},
},
});
按会话禁用已配置的服务器
将 disabledMcpServers 设置为不得在会话中运行的确切 MCP 服务器名称。
该设置的范围限定为单个创建或恢复请求;它不会修改全局 MCP 设置或服务器配置。
const session = await client.createSession({
mcpServers: {
filesystem: { type: "local", command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "."] },
github: { type: "http", url: "https://api.githubcopilot.com/mcp/" },
},
disabledMcpServers: ["github"],
});
| SDK | 配置属性 |
|---|---|
| Node.js | disabled |
| Python | disabled_mcp_ |
| Go | Disabled |
| .NET | Disabled |
| Java | set |
| Rust | with_disabled_ |
在创建会话时以及进行冷恢复时,已禁用的服务器不会启动,运行时也不会发起对其的身份验证。 常驻恢复无法撤消运行时已经生成的服务器。 名称完全一致。
列出和检索提示
实验生成的 MCP 命名空间提供线协议 JSON-RPC 方法 session.mcp.prompts.list 和 session.mcp.prompts.get。 使用以下特定于语言的 SDK 访问器进行调用。 这些方法针对当前会话中的一个连接的服务器;它们不会合并来自多个服务器的结果。
| SDK | 列出提示词 | 获取提示词 |
|---|---|---|
| Node.js | session.rpc.mcp.prompts.list(...) | session.rpc.mcp.prompts.get(...) |
| Python | session.rpc.mcp.prompts.list(...) | session.rpc.mcp.prompts.get(...) |
| Go | session.RPC.MCP.Prompts().List(...) | session.RPC.MCP.Prompts().Get(...) |
| .NET | session.Rpc.Mcp.Prompts.List | session.Rpc.Mcp.Prompts.Get |
| Java | session.get | session.get |
| Rust | session.rpc().mcp().prompts().list(...) | session.rpc().mcp().prompts().get(...) |
列表需要 serverName 并接受可选的不透明 cursor。 每个调用返回一页已定义类型的提示定义和可选的 nextCursor。
在另一个列表调用中传递该游标以请求下一页。 定义包括名称、可选标题和说明以及参数定义。
省略的参数 required 标志仍然与 false 区别开来。
获取提示词需要 serverName 和 promptName,并可选择提供 arguments 字典,其值为字符串。 省略 arguments 会使 MCP 请求的参数不存在;传递 {} 会发送显式空字典。
运行时保留了对服务器的这种区别。 结果包含一个可选说明和具有类型化角色和不透明的 JSON content的有序消息。
在解释内容块之前检查每个内容块 type ;内容不会平展为文本。 嵌套资源、批注、元数据、不熟悉的内容类型和其他内容字段保留其 JSON 结构。 类型化描述符、消息和结果封套上的服务器扩展可在 additionalProperties 下找到。 名为 additionalProperties 的服务器扩展本身将保留为该映射中的条目,而不是合并到其中。
协议的顶级 resultType: "complete" 判别器由运行时使用;它不会作为 SDK 字段或服务器扩展返回。
如果运行时无法保留原始响应(包括超过 1 MiB 捕获限制的 stdio 响应帧),则请求会显式失败。
返回的提示消息不会自动发送到模型,也不会用于执行工具或获取所引用的资源。 应用程序决定如何使用结果。 生成该结果时,MCP 服务器可以通过多轮往返继续请求采样或信息征集。 这些请求使用与其他 MCP 操作相同的配置的主机响应程序;提示检索不会授予其他权限或绕过主机的决定。 缺少响应方或响应方错误会导致请求失败,并且会将 elicitation 拒绝原样返回给服务器。 仅状态的延续操作不调用任何一个响应器。
在现有 mcp.prompts.list_changed 会话事件后,再次列出指定服务器的提示以刷新应用程序的视图。
在 MCP 启动之前应用沙盒策略
在构造过程中传递给sandboxConfig``createSession或resumeSession应用沙盒策略,然后发现根配置、插件或显式配置的 MCP 服务器启动。 它接受与 . 相同的配置 session.rpc.options.update({ sandboxConfig })。
const sandboxConfig = {
enabled: true,
sandboxMcpServers: true,
userPolicy: { network: { allowOutbound: false } },
};
const session = await client.createSession({
onPermissionRequest: approveAll,
sandboxConfig,
});
在冷恢复时重新提供配置;遗漏会保留居民会话的当前策略。 居民简历无法撤消已启动的进程。 托管策略验证使用与选项更新相同的直接主机语义:冲突的请求无法创建或恢复,而不是回退到未装箱的会话,并 data.code 设置为 managed_sandbox_policy_conflict JSON-RPC 错误。 运行时不会为此显式主机配置分配派生 sandboxConfigSource 的设置。
以后相同的 options.update({ sandboxConfig }) 操作不会重启 MCP 服务器,包括托管策略何时规范化配置。 其他有效的 MCP 沙盒策略会保留通常的重启行为。
version根据应用程序对此功能所需的最低运行时版本检查 (server.connect``ConnectResult) 返回的运行时。 SDK 协议版本不是每个功能的功能信号。 较旧的运行时忽略未知的创建/恢复字段,因此支持它们的应用程序可以在打开时发送 sandboxConfig ,并在后续选项更新中重复它。 在支持运行时时,该更新是无害的,但在更新到达之前,较旧的运行时仍然可以启动 MCP;当从第一个进程进行限制时,需要支持运行时版本。
工具配置
可以使用 tools 字段控制 MCP 服务器可用的工具。
允许使用所有工具
使用 "*" 来启用 MCP 服务器提供的所有工具:
tools: ["*"]
允许使用特定工具
提供用于限制访问的工具名称列表:
tools: ["bash", "edit"]
只有列出的工具可供代理使用。
禁用所有工具
使用空数组禁用所有工具:
tools: []
Notes
- 该
tools字段定义允许的工具。 - 没有单独的
allow或disallow配置 - 工具访问直接通过此列表进行控制。
快速入门:文件系统 MCP 服务器
下面是使用官方 @modelcontextprotocol/server-filesystem MCP 服务器的完整工作示例:
import { CopilotClient } from "@github/copilot-sdk";
async function main() {
const client = new CopilotClient();
// Create session with filesystem MCP server
const session = await client.createSession({
mcpServers: {
filesystem: {
type: "local",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
tools: ["*"],
},
},
});
console.log("Session created:", session.sessionId);
// The model can now use filesystem tools
const result = await session.sendAndWait({
prompt: "List the files in the allowed directory",
});
console.log("Response:", result?.data?.content);
await session.disconnect();
await client.stop();
}
main();
Output:
Session created: 18b3482b-bcba-40ba-9f02-ad2ac949a59a
Response: The allowed directory is `/tmp`, which contains various files
and subdirectories including temporary system files, log files, and
directories for different applications.
提示
可以使用 MCP 服务器目录中的任何 MCP 服务器。 常用选项包括 @modelcontextprotocol/server-github、 @modelcontextprotocol/server-sqlite和 @modelcontextprotocol/server-puppeteer。
配置选项
本地/stdio 服务器
| 财产 | 类型 | 必选 | Description |
|---|---|---|---|
type | |||
"local" 或 "stdio" | 否 | 服务器类型(默认为本地) | |
command | string | Yes | 要执行的命令 |
args | string[] | Yes | 命令参数 |
env | object | 否 | 环境变量 |
cwd | string | 否 | 工作目录 |
tools | string[] | 否 | 要启用的工具(["*"] 表示全部启用,[] 都不启用) |
timeout | number | 否 | 超时(以毫秒为单位) |
远程服务器 (HTTP/SSE)
| 财产 | 类型 | 必选 | Description |
|---|---|---|---|
type | |||
"http" 或 "sse" | Yes | 服务器类型 | |
url | string | Yes | 服务器 URL |
headers | object | 否 | HTTP 标头(例如,用于身份验证) |
oauthClientId | string | 否 | 静态配置的 OAuth 客户端的非空客户端 ID |
oauthScopes | string[] | 否 | 有效 RFC 6749 作用域令牌的非空数组。 要求 oauthClientId;当服务器质询省略作用域或提供空作用域时,在受保护资源元数据回退之前使用。 |
oauthPublicClient | boolean | 否 | 配置的 OAuth 客户端是否为公共客户端,并且不需要客户端密钥 |
oauthGrantType | string | 否 | 配置的客户端的 OAuth 授予类型,例如 client_credentials |
tools | string[] | 否 | 要启用的工具 |
timeout | number | 否 | 超时(以毫秒为单位) |
远程服务器的 OAuth 归属
为每个身份验证尝试选择一种 OAuth 归属模型:
- 运行时管理的环回:在没有重定向 URI 的情况下调用
session.mcp.oauth.login。 运行时将打开本地回调侦听器,并负责发现、PKCE、状态验证、令牌交换、持久化、刷新和重新连接。 - 运行时托管的回调:使用受信任的公共 HTTPS 重定向 URI 调用
session.mcp.oauth.login。 主机会收到回调,但 OAuth 协议和凭据仍由运行时负责管理。 - 主机管理的 OAuth:使用 SDK 的 MCP 身份验证请求处理程序并返回主机获取的访问令牌。 您的主机拥有授权令牌和刷新令牌。
不要为使用运行时管理的托管回调的身份验证尝试注册主机管理的 OAuth 处理程序。 等待远程服务器进入 needs-auth 状态,然后使用服务器名称和回调 URI 直接调用生成的 session.rpc.mcp.oauth.login 方法:
{
"serverName": "remote-mcp",
"redirectUri": "https://agent.example.com/oauth/callback"
}
所选的静态、CIMD 或动态注册的 OAuth 客户端必须声明该确切 URI。 URI 必须使用 HTTPS,并且不得包含查询或片段。
当需要浏览器交互时,结果包含 authorizationUrl 和 authorizationId。 在用户的浏览器中打开 authorizationUrl 并将 authorizationId 与目标会话保持关联。
授权服务器重定向到终结点后,调用生成的 session.rpc.mcp.oauth.complete 方法:
{
"authorizationId": "<opaque-state>",
"callbackUrl": "https://agent.example.com/oauth/callback?code=...&state=..."
}
从配置的公共重定向源站和路径以及回调的原始查询构造 callbackUrl。 不要传递内部服务 URL 或信任客户端提供 Forwarded 或 X-Forwarded-* 标头。 运行时在接受交付之前验证源、端口、路径、状态和 OAuth 响应。 令牌交换、持久化和 MCP 重新连接,然后异步继续。
将被拒绝的访问令牌交还给运行时
对于带有 reason: "refresh" 和 runtimeRefreshSupported: true 的主机 OAuth 请求,处理程序可以返回 { "kind": "runtimeRefresh" },而不是获取替换访问令牌。
运行时使用原始授权操作中的现有已保存授权许可执行非交互续订。 它不会启动新的同意流程或调用独立的 authenticationStateChanged 刷新 RPC。
替换项保留其已保存授权的来源,因此之后仍可采用有作用域的已存储令牌。 由主机直接提供的令牌未标记为存储令牌,并且无法被该接入路径覆盖。
仅当挂起的请求表明支持时返回此响应。 缺少某项能力时,结果为 false,并保留旧版令牌/取消约定。 如果处理程序对不具备该能力的请求返回移交,则 SDK 将改为发送 cancelled,因此挂起的请求不会保持打开状态。 提供的令牌优先于切换,取消仍然是取消。
| SDK | 能力 | 交接结果 |
|---|---|---|
| Node.js | request.runtime | { kind: "runtimeRefresh" } |
| Python | request["runtime | {"kind": "runtimeRefresh"} |
| Go | ||
MCPAuth 功能参数 | MCPAuth | |
| .NET | Mcp | Mcp |
| Java | ||
Mcp 功能参数 | Mcp | |
| Rust | Mcp | Mcp |
接受响应确认的是交接,而不是刷新、重新连接或工具完成。 对于已接受的移交,mcp.oauth_completed 会在原始授权预留达到其最终结果时发出一次。 它 outcome 仅使用现有值:恢复成功时为 token,取消或失败时为 cancelled。 持久化的 mcp.oauth_recovery_completed 事件携带相同的 requestId 和 serverName,并用于区分最终结果,包括重新连接:succeeded、cancelled 或 failed。 早于此事件的 SDK 版本会将其视为未知事件类型来接收。
在运行时接受 runtimeRefresh 响应之前,现有答复保持原有含义。 主机 { kind: "cancelled" } 回复拒绝请求;对于 refresh 请求,运行时可以请求重新授权。
如果没有主机回复,运行时会回退到其普通的本地 OAuth 处理,包括缓存的凭据,并且不会发出任何 mcp.oauth_recovery_completed 事件。
此更改不会将主机 cancelled 回复重新分类为“停止”。 原始调用只能通过已接受的 runtimeRefresh 交接来保留。
接受后,原始调用可以在凭据安装后重试,并重新连接,同时保留现有的会话、配置、策略和权限边界。 停止主轮次或结束会话会取消原始授权预留;停止的调用以后无法重试或发布结果。 已颁发的轮换授权交换可以在取消后完成持久化其替换内容,但无法安装过时的凭据、重新连接或恢复已取消的调用。
不可用的已保存授权或刷新失败会终止原始调用,而无需请求交互式重新授权。 失败的重新连接也会终止调用;成功获取令牌不是一个成功的工具结果。
并发调用会加入确切的正在进行的授权尝试并接收其最终结果。 连接的服务器、保留的访问令牌或以后的成功尝试并不证明其尝试成功。 每个幸存的调用在重试之前仍会重新检查其自己的目录库和工具权限;合并后的失败不会启动另一个交互式授权。
OAuth HTTP 时限适用于单个请求,而不适用于完整的交接流程或授权授予存储的完成过程。 取消可以在已发出的交换完成结算之前返回,会话处置等待跟踪的结算工作线程。 没有整体结算截止期限,因此主机不得将取消、移交验收或 HTTP 超时视为所有存储工作已完成的证据。
会话范围的 MCP 诊断
创建或恢复会话时设置 diagnostics: { sources: { mcp: { level: "debug" } } } 以选择加入 MCP 诊断。 每个源默认为 off.
启用的级别为 error、warning、info、debug 和 trace。 此设置与客户端的进程级 logLevel 分开。
警告
诊断条目可以在每个启用的级别包含用户提供的内容或服务器提供的内容:warning及以上级别可以包括服务器 stderr,而 debug 和 trace 还可以包含 MCP 有效负载、工具参数和路径。 将每个条目视为敏感项。 请勿自动将条目作为遥测上传,也不要在未经宿主端明确操作的情况下导出条目。
session.rpc.diagnostics生成的 API 允许主机配置和读取会话范围的有界的内存中诊断信息。 MCP 是第一个且当前仅受支持的源。 读取时使用 sources: ["mcp"] 显式选择它;读取操作不会启用捕获。 为每个输出表面使用一个可停止的读取循环并保留其游标。 读取循环拥有其游标和呈现;运行时拥有捕获、筛选、保留、游标过期和唤醒。
import { approveAll, CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
const stop = new AbortController();
const appendLine = (line: string) => console.log(line);
await client.start();
const session = await client.createSession({
onPermissionRequest: approveAll,
diagnostics: { sources: { mcp: { level: "debug" } } },
});
try {
let cursor: string | undefined;
while (!stop.signal.aborted) {
const page = await session.rpc.diagnostics.read({
sources: ["mcp"],
cursor,
max: 100,
waitMs: 30_000,
});
if (page.cursorStatus === "expired") {
appendLine("MCP diagnostic entries were dropped.");
}
for (const entry of page.entries) {
const detail = entry.details.data ? ` ${entry.details.data}` : "";
appendLine(
`${entry.timestamp} [${entry.level}] [${entry.source}:${entry.details.serverName}] ${entry.message}${detail}`,
);
}
cursor = page.cursor;
}
} finally {
await session.disconnect();
await client.stop();
}
中止信号在其当前有界读取完成后停止循环;它不会传递给 RPC 调用。 禁用捕获会唤醒挂起的读取操作。
MCP 为惰性启动:启用或读取诊断不会启动服务器。
在创建会话时配置 mcpServers,然后正常使用会话,或者对于已安装的服务器,可调用 session.rpc.mcp.startServer({ serverName }) 来排查初始化问题,而无需发出模型请求。
每个记录都有 source: "mcp"、时间戳、严重性、消息,以及针对非根代理的可选 agentId。 其类型 details 包含生命周期、协议、HTTP 或 stderr 类别、服务器名称、每次连接尝试对应的全新 connectionId,以及可选的协议方向和诊断数据。
MCP 保留上限为 1,024 条记录,且每个会话最多 4 MiB。 单个编码记录的上限为 16 KiB,并在截短时带有 truncated 标记。 读取默认为 100 条记录,最多接受 500 条记录,并且不会消耗其他读取器的数据。
如果过期游标上存在 droppedCount,则使用它以显示已知损失。
每次成功的读取都会返回游标和游标状态,包括空读取。 即使没有记录到达,也会保留返回的游标。 光标属于其源选区;更改该选区时,不要带光标开始操作。
缺少、空白、重复或不受支持的来源将被拒绝,格式错误的游标和无效的数字边界也是如此。 记录和捕获设置均不会保存在会话历史记录中。
调用 session.rpc.diagnostics.configure({ sources: { mcp: { level: "off" } } }) 以禁用 MCP 捕获并清除其保留的缓冲区。 配置更新的仅是显式命名的源,并返回有效的源级别。 拒绝空或未知的源配置;将来添加另一个受支持的源不会在未明确指定的情况下让现有调用方自动使用该源。
也停止主机的读取循环;日志记录关闭时读取会立即返回,而不是等待。 禁用日志记录时,一个挂起的长轮询被唤醒。 在驻留恢复期间省略 diagnostics 会保留其当前配置;冷加载会话则需要重新选择启用。
从初始 off 状态启用诊断可以开始捕获已处于活动状态的 MCP 连接。 禁用 configure({ sources: { mcp: { level: "off" } } })诊断后,重新启用可以恢复对相同实时连接及其现有连接 ID 的捕获。 禁用诊断时已在处理中的记录将被丢弃。
运行时在条目到达此 API 之前从 HTTP 诊断中删除已配置和结构化识别的凭据,但这并不能保证不存在任意由服务器提供的机密。 它不公开请求或响应标头映射。 只有选定的元数据(例如 Content-Type、Accept 和 MCP-Protocol-Version)才可被捕获,但其值仍然不受信任,并且可能包含敏感内容。 身份验证标头、Cookie、会话 ID、查询值、URL userinfo 和片段会被省略。 URL 路径会保留进行故障排除,因此不要在路径段中放置凭据。
协议有效负载和 stderr 还可以包含用户内容或任意服务器提供的机密。
故障排除
工具未显示或未被调用
-
验证 MCP 服务器是否正确启动
- 检查命令和参数是否正确
- 确保服务器进程在启动时不会崩溃
- 在 stderr 中查找错误输出
-
检查工具配置
- 确保
tools已设置为["*"]或列出所需的特定工具 - 空数组
[]意味着未启用任何工具
- 确保
-
验证远程服务器的连接性
- 确保 URL 可访问
- 检查身份验证标头是否正确
常见问题
| Issue | 解决方案 |
|---|---|
| “找不到 MCP 服务器” | 验证命令路径是否正确且可执行 |
| “连接被拒绝”(HTTP) | 检查 URL 并确保服务器正在运行 |
| “超时”错误 | 增加timeout的值,或检查服务器性能 |
| 工具虽然在正常运行但没有被调用 | 请确保提示明确指明工具的功能 |
有关详细的调试指南,请参阅 MCP 服务器调试指南。
相关资源
- 模型上下文协议规范
- MCP 服务器目录 - 社区 MCP 服务器
- GitHub MCP 服务器 - 官方GitHub MCP 服务器
- 构建你的第一个由 Copilot 提供支持的应用 - SDK 基础知识和自定义工具
- 调试指南 - SDK 范围的调试
另见
- MCP 服务器调试指南 - 详细的 MCP 故障排除
- 问题 9 - 原始 MCP 工具使用情况问题
- 问题 #36 - MCP 文档跟踪问题