6.4 MCP协议服务器

MCP(Model Context Protocol)是Anthropic开发的开放协议,让AI能够安全地与外部工具和数据源交互。OpenCode原生支持MCP,可以轻松扩展AI的能力。

什么是MCP

MCP(Model Context Protocol,模型上下文协议)是一个标准化的协议,定义了AI模型与外部系统之间的通信方式:

核心概念

  • 工具(Tools) - AI可以调用的函数,如查询数据库、发送请求
  • 资源(Resources) - AI可以访问的数据源,如文件、API
  • 提示(Prompts) - 预定义的提示模板

MCP的优势

  • 标准化 - 统一的协议,兼容多种AI工具
  • 安全性 - 明确的权限控制和访问边界
  • 可扩展 - 轻松添加新的工具和数据源
  • 开放生态 - 丰富的开源MCP服务器可用

配置MCP服务器

基本配置结构

{
  "mcp": {
    "servers": {
      "server-name": {
        "type": "stdio",
        "command": "command-to-run",
        "args": ["arg1", "arg2"],
        "env": {
          "ENV_VAR": "value"
        }
      }
    }
  }
}

配置项说明

配置项类型说明
typestring连接类型:stdio(标准输入输出)或sse(Server-Sent Events)
commandstring启动MCP服务器的命令
argsstring[]命令参数
envobject环境变量
urlstringSSE类型时的服务器URL

stdio类型配置

最常用的类型,通过标准输入输出与MCP服务器通信:

{
  "mcp": {
    "servers": {
      "filesystem": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/dir"]
      }
    }
  }
}

SSE类型配置

通过HTTP SSE连接远程MCP服务器:

{
  "mcp": {
    "servers": {
      "remote-server": {
        "type": "sse",
        "url": "https://mcp-server.example.com/sse"
      }
    }
  }
}

常见用例

文件系统访问

允许AI访问特定目录的文件:

{
  "mcp": {
    "servers": {
      "filesystem": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
      }
    }
  }
}

数据库查询

让AI能够查询数据库:

{
  "mcp": {
    "servers": {
      "postgres": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-postgres"],
        "env": {
          "DATABASE_URL": "postgresql://user:pass@localhost:5432/mydb"
        }
      }
    }
  }
}

GitHub集成

让AI能够与GitHub交互:

{
  "mcp": {
    "servers": {
      "github": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-github"],
        "env": {
          "GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"
        }
      }
    }
  }
}

Web搜索

让AI能够搜索网络:

{
  "mcp": {
    "servers": {
      "brave-search": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-brave-search"],
        "env": {
          "BRAVE_API_KEY": "your-api-key"
        }
      }
    }
  }
}

Slack集成

让AI能够发送Slack消息:

{
  "mcp": {
    "servers": {
      "slack": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-slack"],
        "env": {
          "SLACK_BOT_TOKEN": "xoxb-xxxxxxxxxxxx"
        }
      }
    }
  }
}

示例配置

完整的多服务器配置

{
  "mcp": {
    "servers": {
      "filesystem": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-filesystem", "./"],
        "env": {}
      },
      "github": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-github"],
        "env": {
          "GITHUB_TOKEN": "${GITHUB_TOKEN}"
        }
      },
      "postgres": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-postgres"],
        "env": {
          "DATABASE_URL": "${DATABASE_URL}"
        }
      },
      "memory": {
        "type": "stdio",
        "command": "npx",
        "args": ["-y", "@modelcontextprotocol/server-memory"]
      }
    }
  }
}

使用Python MCP服务器

{
  "mcp": {
    "servers": {
      "custom-python": {
        "type": "stdio",
        "command": "python",
        "args": ["-m", "my_mcp_server"],
        "env": {
          "PYTHONPATH": "/path/to/modules"
        }
      }
    }
  }
}

使用Docker运行MCP服务器

{
  "mcp": {
    "servers": {
      "docker-mcp": {
        "type": "stdio",
        "command": "docker",
        "args": [
          "run", "--rm", "-i",
          "-v", "/path/to/data:/data",
          "mcp-server-image"
        ]
      }
    }
  }
}

常用MCP服务器

官方MCP服务器
  • @modelcontextprotocol/server-filesystem - 文件系统访问
  • @modelcontextprotocol/server-github - GitHub API
  • @modelcontextprotocol/server-postgres - PostgreSQL数据库
  • @modelcontextprotocol/server-sqlite - SQLite数据库
  • @modelcontextprotocol/server-memory - 知识图谱记忆
  • @modelcontextprotocol/server-brave-search - Brave搜索
  • @modelcontextprotocol/server-google-maps - Google地图
  • @modelcontextprotocol/server-slack - Slack集成
  • @modelcontextprotocol/server-puppeteer - 浏览器自动化

MCP工具权限

MCP服务器提供的工具同样受OpenCode权限系统控制:

{
  "permission": {
    "mcp:filesystem:read_file": "allow",
    "mcp:filesystem:write_file": "ask",
    "mcp:github:create_issue": "ask",
    "mcp:postgres:query": "ask"
  }
}

调试MCP服务器

查看MCP日志

# 启用MCP调试日志
export OPENCODE_MCP_DEBUG=true
opencode

测试MCP服务器

# 手动启动MCP服务器测试
npx -y @modelcontextprotocol/server-filesystem ./

# 发送测试请求
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | npx -y @modelcontextprotocol/server-filesystem ./

自定义MCP服务器

可以使用MCP SDK创建自定义服务器:

TypeScript示例

// my-mcp-server/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server(
  { name: "my-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

server.setRequestHandler("tools/list", async () => ({
  tools: [{
    name: "my_tool",
    description: "My custom tool",
    inputSchema: {
      type: "object",
      properties: {
        input: { type: "string" }
      }
    }
  }]
}));

server.setRequestHandler("tools/call", async (request) => {
  if (request.params.name === "my_tool") {
    return { content: [{ type: "text", text: "Tool executed!" }] };
  }
});

const transport = new StdioServerTransport();
server.connect(transport);

Python示例

# my_mcp_server/__main__.py
import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server

app = Server("my-server")

@app.list_tools()
async def list_tools():
    return [{
        "name": "my_tool",
        "description": "My custom tool",
        "inputSchema": {
            "type": "object",
            "properties": {"input": {"type": "string"}}
        }
    }]

@app.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "my_tool":
        return [{"type": "text", "text": "Tool executed!"}]

async def main():
    async with stdio_server() as (read, write):
        await app.run(read, write)

asyncio.run(main())
安全提示
  • 仔细审查第三方MCP服务器的代码
  • 只授予必要的最小权限
  • 敏感信息使用环境变量传递,不要硬编码
  • 定期更新MCP服务器以获取安全补丁

故障排除

MCP服务器无法启动

  • 检查command路径是否正确
  • 确认依赖已安装(如npx需要Node.js)
  • 查看错误日志获取详细信息

工具调用失败

  • 检查环境变量是否正确设置
  • 确认API密钥有效
  • 验证网络连接(对于需要网络的服务器)

下一步

扩展功能介绍完毕,接下来学习OpenCode的SDK使用和开发集成。