# MCP 服务器调试指南

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

<!-- markdownlint-disable GHD046 GHD005 -->

<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

## 目录

* [快速诊断](#quick-diagnostics)
* [独立测试 MCP 服务器](#testing-mcp-servers-independently)
* [常见问题](#common-issues)
* [特定平台问题](#platform-specific-issues)
* [高级调试](#advanced-debugging)

## 快速诊断

### 清单

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

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

### 启用 MCP 调试日志记录

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

```typescript
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` 请求：

```bash
# 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
```

**预期响应：**

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

### 测试工具列表

初始化后，请求工具列表：

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

**预期响应：**

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

### 交互式测试脚本

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

```bash
#!/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
```

用法：

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

## 常见问题

### 服务器未启动

**症状：** 没有显示任何工具，日志中没有错误。

**原因和解决方案：**

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

**通过手动运行进行调试：**

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

### 服务器启动但工具未显示

**症状：** 服务器进程运行，但没有可用的工具。

**原因和解决方案：**

1. **配置中未启用的工具：**

   ```typescript
   mcpServers: {
     "server": {
       // ...
       tools: ["*"],  // Must be "*" or list of tool names
     },
   }
   ```

2. **服务器不公开工具：**
   * 使用`tools/list`请求手动测试
   * 检查服务器是否实现了 `tools/list` 方法

3. **初始化握手失败：**
   * 服务器必须正确响应 `initialize`
   * 服务器必须处理 `notifications/initialized`

### 列出但从未调用过的工具

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

**原因和解决方案：**

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

   ```typescript
   // 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. **工具说明不清楚：**

   ```typescript
   // 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. **增加超时时间：**

   ```typescript
   mcpServers: {
     "slow-server": {
       // ...
       timeout: 300000,  // 5 minutes
     },
   }
   ```

2. **优化服务器性能：**
   * 添加进度日志记录以识别瓶颈
   * 考虑异步操作
   * 检查是否存在阻塞式 I/O

3. **对于长时间运行的工具**，请考虑流式处理响应（如果受支持）。

### JSON-RPC 错误

**症状：** 解析错误，无效请求错误。

**常见原因：**

1. **服务器错误地写入 stdout：**
   * 调试输出被发送到 stdout 而不是 stderr
   * 额外的换行符或空格
   ```typescript
   // Wrong - pollutes stdout
   console.log("Debug info");

   // Correct - use stderr for debug
   console.error("Debug info");
   ```

2. **编码问题：**
   * 确保 UTF-8 编码
   * 无 BOM （字节顺序标记）

3. **消息框架：**
   * 每个消息必须是完整的 JSON 对象
   * 以换行符分隔（每行一条消息）

## 特定于平台的问题

### Windows操作系统

#### .NET控制台应用/工具

<!-- docs-validate: hidden -->

```csharp
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> { "*" },
            }
        };
    }
}
```

<!-- /docs-validate: hidden -->

```csharp
// 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 命令

<!-- docs-validate: hidden -->

```csharp
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> { "*" },
            }
        };
    }
}
```

<!-- /docs-validate: hidden -->

```csharp
// 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 阻止

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

#### Homebrew 路径

<!-- docs-validate: hidden -->

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

const mcpServers: Record<string, MCPStdioServerConfig> = {
  "my-server": {
    command: "/opt/homebrew/bin/node",
    args: ["/path/to/server.js"],
    tools: ["*"],
  },
};
```

<!-- /docs-validate: hidden -->

```typescript
// 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

#### 权限问题

```bash
chmod +x /path/to/mcp-server
```

#### 缺少共享库

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

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

## 高级调试

### 捕获所有 MCP 流量

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

```bash
#!/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"
```

使用它：

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

### 使用 MCP 检查器进行检查

使用官方 MCP 检查器工具：

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

这提供了一个 Web 用户界面，用于：

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

### 协议版本不匹配

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

```json
// 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 调试日志
* [ ] 任何错误消息

## 另见

* [Using MCP servers with the GitHub Copilot SDK](/zh/copilot/how-tos/copilot-sdk/features/mcp) - 配置和设置
* [调试指南](/zh/copilot/how-tos/copilot-sdk/troubleshooting/debugging) - SDK 范围的调试
* [MCP 规范](https://modelcontextprotocol.io/) - 官方协议文档