Skip to main content

MCP 服务器调试指南

本指南介绍在使用 Copilot SDK 时特定于 MCP(模型上下文协议)服务器的调试技术。

目录

快速诊断

清单

在深入潜水之前,请验证以下基础知识:

  • MCP 服务器可执行文件存在且可运行
  • 命令路径正确(怀疑时使用绝对路径)
  • 工具已启用(tools: ["*"] 或特定工具名称)
  • 服务器正确实现 MCP 协议(响应 initialize
  • 没有防火墙/防病毒阻止进程(Windows)

启用 MCP 调试日志记录

将环境变量添加到 MCP 服务器配置:

mcpServers: {
  "my-server": {
    type: "local",
    command: "/path/to/server",
    args: [],
    env: {
      MCP_DEBUG: "1",
      DEBUG: "*",
      NODE_DEBUG: "mcp",  // For Node.js MCP servers
    },
  },
}

独立测试 MCP 服务器

始终先在 SDK 外部测试 MCP 服务器。

手动协议测试

通过标准输入发送 initialize 请求:

# Unix/macOS
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | /path/to/your/mcp-server

# Windows (PowerShell)
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | C:\path\to\your\mcp-server.exe

预期响应:

{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"your-server","version":"1.0"}}}

测试工具列表

初始化后,请求工具列表:

echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | /path/to/your/mcp-server

预期响应:

{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"my_tool","description":"Does something","inputSchema":{...}}]}}

交互式测试脚本

创建测试脚本以交互方式调试 MCP 服务器:

#!/bin/bash
# test-mcp.sh

SERVER="$1"

# Initialize
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

# Send initialized notification
echo '{"jsonrpc":"2.0","method":"notifications/initialized"}'

# List tools
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'

# Keep stdin open
cat

用法:

./test-mcp.sh | /path/to/mcp-server

常见问题

服务器未启动

症状: 没有显示任何工具,日志中没有错误。

原因和解决方案:

原因解决方案
命令路径错误使用绝对路径: /usr/local/bin/server
缺少可执行权限
chmod +x /path/to/server运行
缺少依赖项使用 ldd (Linux) 检查或手动运行
工作目录问题在配置中设置cwd

通过手动运行进行调试:

# Run exactly what the SDK would run
cd /expected/working/dir
/path/to/command arg1 arg2

服务器启动但工具未显示

症状: 服务器进程运行,但没有可用的工具。

原因和解决方案:

  1. 配置中未启用的工具:

    mcpServers: {
      "server": {
        // ...
        tools: ["*"],  // Must be "*" or list of tool names
      },
    }
    
  2. 服务器不公开工具:

    • 使用tools/list请求手动测试
    • 检查服务器是否实现了 tools/list 方法
  3. 初始化握手失败:

    • 服务器必须正确响应 initialize
    • 服务器必须处理 notifications/initialized

列出但从未调用过的工具

症状: 工具显示在调试日志中,但模型不使用它们。

原因和解决方案:

  1. 提示显然不需要该工具:

    // Too vague
    await session.sendAndWait({ prompt: "What's the weather?" });
    
    // Better - explicitly mentions capability
    await session.sendAndWait({ 
      prompt: "Use the weather tool to get the current temperature in Seattle" 
    });
    
  2. 工具说明不清楚:

    // Bad - model doesn't know when to use it
    { name: "do_thing", description: "Does a thing" }
    
    // Good - clear purpose
    { name: "get_weather", description: "Get current weather conditions for a city. Returns temperature, humidity, and conditions." }
    
  3. 工具架构问题:

    • 确保 inputSchema 有效 JSON 架构
    • 必填字段必须位于数组中required

系统超时错误

症状:MCP tool call timed out 错误。

解决方案:

  1. 增加超时时间:

    mcpServers: {
      "slow-server": {
        // ...
        timeout: 300000,  // 5 minutes
      },
    }
    
  2. 优化服务器性能:

    • 添加进度日志记录以识别瓶颈
    • 考虑异步操作
    • 检查是否存在阻塞式 I/O
  3. 对于长时间运行的工具,请考虑流式处理响应(如果受支持)。

JSON-RPC 错误

症状: 解析错误,无效请求错误。

常见原因:

  1. 服务器错误地写入 stdout:

    • 调试输出被发送到 stdout 而不是 stderr
    • 额外的换行符或空格
    // Wrong - pollutes stdout
    console.log("Debug info");
    
    // Correct - use stderr for debug
    console.error("Debug info");
    
  2. 编码问题:

    • 确保 UTF-8 编码
    • 无 BOM (字节顺序标记)
  3. 消息框架:

    • 每个消息必须是完整的 JSON 对象
    • 以换行符分隔(每行一条消息)

特定于平台的问题

Windows操作系统

.NET控制台应用/工具

using GitHub.Copilot;

public static class McpDotnetConfigExample
{
    public static void Main()
    {
        var servers = new Dictionary<string, McpServerConfig>
        {
            ["my-dotnet-server"] = new McpStdioServerConfig
            {
                Command = @"C:\Tools\MyServer\MyServer.exe",
                Args = new List<string>(),
                WorkingDirectory = @"C:\Tools\MyServer",
                Tools = new List<string> { "*" },
            },
            ["my-dotnet-tool"] = new McpStdioServerConfig
            {
                Command = "dotnet",
                Args = new List<string> { @"C:\Tools\MyTool\MyTool.dll" },
                WorkingDirectory = @"C:\Tools\MyTool",
                Tools = new List<string> { "*" },
            }
        };
    }
}
// Correct configuration for .NET exe
["my-dotnet-server"] = new McpStdioServerConfig
{
    Command = @"C:\Tools\MyServer\MyServer.exe",  // Full path with .exe
    Args = new List<string>(),
    WorkingDirectory = @"C:\Tools\MyServer",  // Set working directory
    Tools = new List<string> { "*" },
}

// For dotnet tool (DLL)
["my-dotnet-tool"] = new McpStdioServerConfig
{
    Command = "dotnet",
    Args = new List<string> { @"C:\Tools\MyTool\MyTool.dll" },
    WorkingDirectory = @"C:\Tools\MyTool",
    Tools = new List<string> { "*" },
}

npx 命令

using GitHub.Copilot;

public static class McpNpxConfigExample
{
    public static void Main()
    {
        var servers = new Dictionary<string, McpServerConfig>
        {
            ["filesystem"] = new McpStdioServerConfig
            {
                Command = "cmd",
                Args = new List<string> { "/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "C:\\allowed\\path" },
                Tools = new List<string> { "*" },
            }
        };
    }
}
// Windows needs cmd /c for npx
["filesystem"] = new McpStdioServerConfig
{
    Command = "cmd",
    Args = new List<string> { "/c", "npx", "-y", "@modelcontextprotocol/server-filesystem", "C:\\allowed\\path" },
    Tools = new List<string> { "*" },
}

路径问题

  • 使用原始字符串 (@"C:\path") 或正斜杠 ("C:/path"
  • 尽可能避免路径中的空格
  • 如果需要空格,请确保正确引用

防病毒/防火墙

Windows Defender或其他 AV 可能会阻止:

  • 新的可执行文件
  • 通过 stdin/stdout 进行通信的过程

解决 方案: 为 MCP 服务器可执行文件添加排除项。

macOS

Gatekeeper 阻止

# If the server is blocked
xattr -d com.apple.quarantine /path/to/mcp-server

Homebrew 路径

import { MCPStdioServerConfig } from "@github/copilot-sdk";

const mcpServers: Record<string, MCPStdioServerConfig> = {
  "my-server": {
    command: "/opt/homebrew/bin/node",
    args: ["/path/to/server.js"],
    tools: ["*"],
  },
};
// GUI apps may not have /opt/homebrew in PATH
mcpServers: {
  "my-server": {
    command: "/opt/homebrew/bin/node",  // Full path
    args: ["/path/to/server.js"],
  },
}

Linux

权限问题

chmod +x /path/to/mcp-server

缺少共享库

# Check dependencies
ldd /path/to/mcp-server

# Install missing libraries
apt install libfoo  # Debian/Ubuntu
yum install libfoo  # RHEL/CentOS

高级调试

捕获所有 MCP 流量

创建包装器脚本以记录所有通信:

#!/bin/bash
# mcp-debug-wrapper.sh

LOG="./mcp-debug-$(date +%s).log"
ACTUAL_SERVER="$1"
shift

echo "=== MCP Debug Session ===" >> "$LOG"
echo "Server: $ACTUAL_SERVER" >> "$LOG"
echo "Args: $@" >> "$LOG"
echo "=========================" >> "$LOG"

# Tee stdin/stdout to log file
tee -a "$LOG" | "$ACTUAL_SERVER" "$@" 2>> "$LOG" | tee -a "$LOG"

使用它:

mcpServers: {
  "debug-server": {
    command: "/path/to/mcp-debug-wrapper.sh",
    args: ["/actual/server/path", "arg1", "arg2"],
  },
}

使用 MCP 检查器进行检查

使用官方 MCP 检查器工具:

npx @modelcontextprotocol/inspector /path/to/your/mcp-server

这提供了一个 Web 用户界面,用于:

  • 发送测试请求
  • 查看响应
  • 检查工具架构

协议版本不匹配

检查服务器是否支持 SDK 使用的协议版本:

// In initialize response, check protocolVersion
{"result":{"protocolVersion":"2024-11-05",...}}

如果版本不匹配,请更新 MCP 服务器库。

调试清单

提交问题或寻求帮助时,请收集:

  • SDK 语言和版本
  • CLI 版本 (copilot --version
  • MCP 服务器类型(Node.js、Python、.NET、Go、Rust 等)
  • 完整的 MCP 服务器配置(隐去机密信息)
  • 手动 initialize 测试的结果
  • 手动 tools/list 测试的结果
  • SDK 调试日志
  • 任何错误消息

另见