MCP (Model Context Protocol)
MCP 是 Model Context Protocol 的实现,允许连接外部工具和资源。
概述
MCP 使 OpenCode 能够连接到外部服务器,获取额外的工具、提示词和资源。MCP 支持本地服务器(通过 stdio)和远程服务器(通过 HTTP/SSE)。
定义位置
packages/opencode/src/mcp/index.ts:31-109
MCP 对象
Resource
MCP 资源定义。
| 属性名 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 资源名称 |
uri | string | 是 | 资源 URI |
description | string | 否 | 资源描述 |
mimeType | string | 否 | MIME 类型 |
client | string | 是 | 客户端名称 |
Status
MCP 服务器连接状态(联合类型)。
| 状态类型 | 属性 | 说明 |
|---|---|---|
connected | - | 已连接 |
disabled | - | 已禁用(配置中 enabled: false) |
failed | error: string | 连接失败,包含错误信息 |
needs_auth | - | 需要身份验证 |
needs_client_registration | error: string | 需要客户端注册(缺少 clientId) |
MCP 配置
本地服务器
{
"mcp": {
"filesystem": {
"type": "local",
"command": ["npx", "-y", "@modelcontextprotocol/server-filesystem"],
"enabled": true,
"timeout": 30000,
"environment": {
"CUSTOM_ENV": "value",
},
},
},
}
远程服务器
{
"mcp": {
"gitlab": {
"type": "remote",
"url": "https://gitlab.com/api/v4/mcp/sse",
"enabled": true,
"timeout": 30000,
"headers": {
"Authorization": "Bearer ${TOKEN}",
},
"oauth": false, // 禁用 OAuth
},
},
}
远程服务器(带 OAuth)
{
"mcp": {
"remote-server": {
"type": "remote",
"url": "https://example.com/mcp",
"oauth": {
"clientId": "your-client-id",
"clientSecret": "your-client-secret",
"scope": "read write",
},
},
},
}
MCP 事件
| 事件名 | 类型 | 说明 |
|---|---|---|
mcp.tools.changed | server: string | 工具列表更新 |
mcp.browser.open.failed | mcpName, url: string | 浏览器打开失败 |
典型使用场景
1. 获取所有 MCP 状态
const statuses = await MCP.status()
for (const [name, status] of Object.entries(statuses)) {
console.log(`${name}: ${status.status}`)
if (status.status === "failed") {
console.log(` Error: ${status.error}`)
}
}
2. 获取所有可用的 MCP 工具
const tools = await MCP.tools()
for (const [name, tool] of Object.entries(tools)) {
console.log(`Tool: ${name}`)
console.log(` Description: ${tool.description}`)
}
3. 获取所有 MCP 提示词
const prompts = await MCP.prompts()
for (const [name, prompt] of Object.entries(prompts)) {
console.log(`Prompt: ${name}`)
console.log(` Description: ${prompt.description}`)
console.log(` Client: ${prompt.client}`)
}
4. 获取所有 MCP 资源
const resources = await MCP.resources()
for (const [name, resource] of Object.entries(resources)) {
console.log(`Resource: ${name}`)
console.log(` URI: ${resource.uri}`)
console.log(` MIME Type: ${resource.mimeType}`)
}
5. 执行 MCP 提示词
const result = await MCP.getPrompt(
"client-name", // MCP 客户端名称
"prompt-name", // 提示词名称
{
// 参数(可选)
param1: "value1",
},
)
if (result) {
// result.messages 包含提示词消息
console.log(result.messages)
}
6. 读取 MCP 资源
const result = await MCP.readResource(
"client-name", // MCP 客户端名称
"resource-uri", // 资源 URI
)
if (result) {
console.log(result.contents) // 资源内容
console.log(result.mimeType) // MIME 类型
}
7. 连接/断开 MCP 服务器
// 连接
await MCP.connect("my-mcp-server")
// 断开
await MCP.disconnect("my-mcp-server")
8. 添加新的 MCP 服务器(动态)
const result = await MCP.add("new-server", {
type: "remote",
url: "https://example.com/mcp",
enabled: true,
})
console.log(result.status["new-server"]) // 连接状态
OAuth 认证
启动 OAuth 流程
const { authorizationUrl } = await MCP.startAuth("my-mcp")
// 打开浏览器让用户授权
await open(authorizationUrl)
完成 OAuth 认证
// 在用户授权后,使用回调的授权码完成认证
const status = await MCP.finishAuth("my-mcp", authorizationCode)
console.log(status) // "connected" 或错误状态
移除 OAuth 凭证
await MCP.removeAuth("my-mcp")
检查 OAuth 状态
// 检查是否支持 OAuth
const supports = await MCP.supportsOAuth("my-mcp")
// 检查是否有存储的令牌
const hasTokens = await MCP.hasStoredTokens("my-mcp")
// 获取认证状态
const authStatus = await MCP.getAuthStatus("my-mcp")
// "authenticated" | "expired" | "not_authenticated"
MCP 工具转换
MCP 工具自动转换为 OpenCode 的 Tool 类型:
// MCP 工具定义
{
name: "my_tool",
description: "My tool description",
inputSchema: {
type: "object",
properties: {
param1: { type: "string" }
}
}
}
// 转换为 OpenCode Tool
Tool {
description: "My tool description",
inputSchema: {
type: "object",
properties: { ... },
additionalProperties: false
},
execute: async (args) => {
// 调用 MCP 服务器
return mcpClient.callTool({
name: "my_tool",
arguments: args
})
}
}
MCP 传输层
HTTP/SSE 传输
用于远程 MCP 服务器。
const transport = new StreamableHTTPClientTransport(new URL(url), {
authProvider, // OAuth 提供商(可选)
requestInit: {
// 额外的请求选项
headers: {
"Custom-Header": "value",
},
},
})
Stdio 传输
用于本地 MCP 服务器。
const transport = new StdioClientTransport({
stderr: "ignore",
command: "npx",
args: ["@modelcontextprotocol/server-filesystem"],
cwd: "/working/directory",
env: {
...process.env,
CUSTOM_ENV: "value",
},
})
MCP 连接流程
MCP 配置字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
type | string | 是 | "local" 或 "remote" |
enabled | boolean | 否 | 是否启用(默认 true) |
timeout | number | 否 | 连接超时(毫秒,默认 30000) |
command | string[] | 是* | 本地服务器的命令(type: "local") |
url | string | 是* | 远程服务器的 URL(type: "remote") |
headers | object | 否 | HTTP 请求头(远程服务器) |
environment | object | 否 | 环境变量(本地服务器) |
oauth | object | 否 | OAuth 配置(远程服务器) |
变更历史
| 版本 | 变更内容 | 日期 |
|---|---|---|
| v1 | 初始 MCP 实现 | - |
| v1.1 | 添加 OAuth 支持 | - |
| v1.2 | 添加资源支持 | - |