opencode MCP(Model Context Protocol)配置手册

opencode MCP(Model Context Protocol)配置手册

什么是 MCP

MCP(Model Context Protocol)是一种开放协议,允许外部服务以标准化方式向 LLM 暴露工具(Tool)、提示词(Prompt)和资源(Resource)。opencode 作为 MCP 客户端,可连接任意 MCP 服务器,将其提供的工具直接注入到 LLM 上下文中。


配置位置

MCP 服务器在 opencode.json / opencode.jsoncmcp 字段中配置:

kotlin 复制代码
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "<服务器名称>": { /* McpLocalConfig 或 McpRemoteConfig */ }
  }
}

配置文件查找顺序(项目级优先):

优先级 路径
1 <project>/opencode.json
2 <project>/opencode.jsonc
3 <project>/.opencode/opencode.json
4 <project>/.opencode/opencode.jsonc
5 ~/.config/opencode/opencode.json(全局)

服务器类型

opencode 支持两种 MCP 服务器类型:

local --- 本地进程(stdio)

通过子进程 stdin/stdout 通信,适合本地命令行工具。

json 复制代码
{
  "mcp": {
    "filesystem": {
      "type": "local",
      "command": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
      "environment": {
        "NODE_ENV": "production"
      },
      "enabled": true,
      "timeout": 10000
    }
  }
}

字段说明:

字段 类型 必填 默认值 说明
type "local" --- 固定值
command string[] --- 启动命令及参数,第一个元素为可执行文件
environment Record<string, string> --- --- 注入到子进程的额外环境变量(会合并 process.env
enabled boolean --- true 设为 false 则跳过启动
timeout number(ms) --- 30000 单次请求超时时间

remote --- 远程服务器(HTTP / SSE)

通过 HTTP 协议连接,优先尝试 StreamableHTTP,回退到 SSE。

json 复制代码
{
  "mcp": {
    "my-api": {
      "type": "remote",
      "url": "https://example.com/mcp",
      "headers": {
        "Authorization": "Bearer <token>"
      },
      "enabled": true,
      "timeout": 15000
    }
  }
}

字段说明:

字段 类型 必填 默认值 说明
type "remote" --- 固定值
url string --- MCP 服务器 URL
headers Record<string, string> --- --- 随每次请求发送的 HTTP 头(如 API Key)
oauth `McpOAuthConfig \ false` --- 自动检测
enabled boolean --- true 设为 false 则跳过连接
timeout number(ms) --- 30000 单次请求超时时间

OAuth 认证(remote 专属)

远程服务器默认启用 OAuth 自动检测。若服务器返回 401,opencode 会触发 OAuth 流程。

OAuth 配置字段(oauth 对象)

字段 类型 说明
clientId string 预注册的 OAuth Client ID;不提供时尝试动态注册(RFC 7591)
clientSecret string OAuth Client Secret(部分服务器需要)
scope string 请求的 OAuth scope,空格分隔
redirectUri string 回调地址,默认 http://127.0.0.1:19876/mcp/oauth/callback

禁用 OAuth

json 复制代码
{
  "mcp": {
    "my-api": {
      "type": "remote",
      "url": "https://example.com/mcp",
      "oauth": false
    }
  }
}

OAuth 完整示例

json 复制代码
{
  "mcp": {
    "my-oauth-server": {
      "type": "remote",
      "url": "https://example.com/mcp",
      "oauth": {
        "clientId": "my-client-id",
        "clientSecret": "my-client-secret",
        "scope": "read write",
        "redirectUri": "http://127.0.0.1:19876/mcp/oauth/callback"
      }
    }
  }
}

禁用已配置的服务器

两种方式均可:

json 复制代码
// 方式一:在配置对象中设置 enabled: false
"filesystem": {
  "type": "local",
  "command": ["npx", "-y", "@modelcontextprotocol/server-filesystem"],
  "enabled": false
}

// 方式二:简化写法(legacy)
"filesystem": { "enabled": false }

全局超时配置

experimental 字段中可设置全局 MCP 超时,优先级低于各服务器的 timeout 字段:

json 复制代码
{
  "experimental": {
    "mcp_timeout": 30000
  }
}
配置 优先级
单个服务器 timeout 字段
experimental.mcp_timeout
内置默认值(30000ms)

CLI 管理命令

ini 复制代码
# 添加 MCP 服务器(交互式)
opencode mcp add

# 列出所有已配置服务器及状态
opencode mcp list

# OAuth 认证(交互式)
opencode mcp auth [name]

# 查看 OAuth 认证状态列表
opencode mcp auth list

# 登出(清除 OAuth 凭证)
opencode mcp logout [name]

# 调试 OAuth 连接
opencode mcp debug <name>

服务器连接状态

状态 说明
connected 已成功连接
disabled enabled: false,跳过启动
failed 连接失败,附带错误信息
needs_auth 需要完成 OAuth 认证(运行 opencode mcp auth <name>
needs_client_registration 服务器不支持动态注册,需在 oauth.clientId 中提供预注册 ID

工具命名规则

MCP 工具注册到 LLM 时,名称为:

xml 复制代码
<sanitized_server_name>_<sanitized_tool_name>

其中 sanitize 规则:所有非 [a-zA-Z0-9_-] 字符替换为 _

例如:服务器名 my-server、工具名 list_files → LLM 看到的工具名为 my_server_list_files


传输协议优先级(remote 类型)

连接远程服务器时,opencode 按以下顺序尝试:

  1. StreamableHTTP@modelcontextprotocol/sdk/client/streamableHttp
  2. SSE@modelcontextprotocol/sdk/client/sse

任一方式连接成功即停止。若服务器返回 401,则进入 OAuth 流程,不再尝试其他传输方式。


OAuth Token 存储

OAuth 凭证(access token、refresh token、client info)存储在本地文件系统,路径由 McpAuth 管理(位于 XDG 数据目录)。Token 过期后可通过 opencode mcp auth <name> 重新认证,或 opencode mcp logout <name> 清除。


完整配置示例

kotlin 复制代码
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "mcp_timeout": 30000
  },
  "mcp": {
    // 本地 stdio 服务器
    "filesystem": {
      "type": "local",
      "command": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"],
      "environment": {
        "NODE_ENV": "production"
      },
      "timeout": 10000
    },

    // 本地 opencode 内置服务器
    "opencode-tools": {
      "type": "local",
      "command": ["opencode", "x", "@modelcontextprotocol/server-github"],
      "environment": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxx"
      }
    },

    // 远程服务器,使用 API Key 认证
    "my-api": {
      "type": "remote",
      "url": "https://api.example.com/mcp",
      "headers": {
        "Authorization": "Bearer sk-xxx",
        "X-Custom-Header": "value"
      },
      "oauth": false
    },

    // 远程服务器,使用 OAuth 动态注册
    "oauth-server": {
      "type": "remote",
      "url": "https://oauth.example.com/mcp"
    },

    // 远程服务器,使用预注册 OAuth Client
    "oauth-server-manual": {
      "type": "remote",
      "url": "https://secure.example.com/mcp",
      "oauth": {
        "clientId": "my-client-id",
        "clientSecret": "my-secret",
        "scope": "tools:read tools:write"
      }
    },

    // 已禁用的服务器
    "disabled-server": {
      "type": "local",
      "command": ["some-mcp-server"],
      "enabled": false
    }
  }
}

MCP 工具注入到 LLM 的完整流程

MCP 服务器本质上是一个工具提供方 。opencode 启动时连接 MCP 服务器、拉取工具列表,每次调用 LLM 时把这些工具和内置工具(bash、read、edit 等)合并在一起发给模型。模型决定调用哪个工具,opencode 把请求转发给 MCP 服务器执行,把结果返回给模型。

vbscript 复制代码
opencode 启动
  └─ 连接每个 MCP Server,拉取工具列表,缓存在内存

用户发消息
  └─ 合并工具:内置工具 + 所有 MCP 工具
  └─ 连同系统提示、对话历史一起发给 LLM

LLM 响应(决定调用某工具)
  └─ opencode 拦截工具调用
       ├─ 触发 tool.execute.before 插件钩子
       ├─ 权限确认
       ├─ 转发给 MCP Server 执行
       ├─ 触发 tool.execute.after 插件钩子
       └─ 将结果写入对话历史

再次调用 LLM(携带工具结果)
  └─ LLM 生成最终回复,或继续调用下一个工具

示例 1:工具命名规则

MCP 工具注入 LLM 时,名称改为 服务器名_工具名,非字母数字字符统一替换为 _

配置两个 MCP 服务器:

perl 复制代码
{
  "mcp": {
    "fs": {
      "type": "local",
      "command": ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    },
    "my-github": {
      "type": "local",
      "command": ["npx", "-y", "@modelcontextprotocol/server-github"]
    }
  }
}

LLM 实际看到的工具列表(内置 + 两个 MCP 服务器):

来源 LLM 看到的工具名
内置 bashreadeditglob、...
MCP fs fs_read_filefs_write_filefs_list_directory、...
MCP my-github my_github_create_issuemy_github_list_prs、...

LLM 无法区分哪些是内置工具、哪些是 MCP 工具,它只看到一张扁平工具列表。

LLM 实际收到的请求体(Anthropic Claude 格式):

json 复制代码
"tools": [
  {
    "name": "bash",
    "description": "Run a bash command",
    "input_schema": { "type": "object", "properties": { "command": { "type": "string" } } }
  },
  {
    "name": "fs_list_directory",
    "description": "List directory contents",
    "input_schema": { "type": "object", "properties": { "path": { "type": "string" } } }
  },
  {
    "name": "fs_read_file",
    "description": "Read file contents",
    "input_schema": { "type": "object", "properties": { "path": { "type": "string" } } }
  },
  {
    "name": "my_github_list_prs",
    "description": "List pull requests",
    "input_schema": { "type": "object", "properties": { "repo": { "type": "string" } } }
  }
]

示例 2:一次完整的工具调用

场景: 用户问"列出 /tmp 目录下的文件"

lua 复制代码
用户消息
  "列出 /tmp 目录下的文件"
        │
        ▼
发给 LLM(携带完整工具列表)
  tools: [bash, read, edit, fs_read_file, fs_list_directory, ...]
        │
        ▼
LLM 决策:选择 fs_list_directory
  调用参数:{ "path": "/tmp" }
        │
        ▼
opencode 拦截执行
  1. 触发插件钩子 tool.execute.before
  2. 弹出权限确认(或自动通过)
  3. 转发给 MCP filesystem 服务器执行
  4. 服务器返回:
       content: [{ type: "text", text: "a.txt\nb.txt\nc.log" }]
  5. 触发插件钩子 tool.execute.after
  6. 写入对话历史(part.type="tool", state.output="a.txt\nb.txt\nc.log")
        │
        ▼
再次发给 LLM(携带工具结果)
        │
        ▼
LLM 最终回复
  "/tmp 目录下有 3 个文件:a.txt、b.txt、c.log"

示例 3:多工具协作

场景: 用户问"查 GitHub 上最新的 PR,把标题写入 /tmp/prs.txt"

swift 复制代码
LLM 第一轮:调用 my_github_list_prs
  → MCP github 服务器返回 PR 列表
  → 结果追加到对话历史

LLM 第二轮:调用 fs_write_file
  参数:{ "path": "/tmp/prs.txt", "content": "PR #123: Fix bug\nPR #124: Add feature" }
  → MCP filesystem 服务器写入文件
  → 结果追加到对话历史

LLM 第三轮:生成最终回复
  "已将 2 条 PR 标题写入 /tmp/prs.txt"

每一轮的工具结果都会附在下次发给 LLM 的对话历史里,LLM 可以跨工具、跨轮次串联信息。


工具返回结果类型

MCP 服务器返回的内容分三种类型,opencode 均支持:

返回类型 说明 LLM 如何使用
text 纯文本 直接作为工具输出读取
image base64 图片 以图片附件形式附加到消息
resource 文件/二进制资源 文本部分直接读取,二进制以附件形式附加

工具列表热更新

MCP 服务器可以在运行中主动推送 tools/list_changed 通知。opencode 收到后立即重新拉取工具列表,下一次 LLM 调用自动使用新列表,无需重启。


相关源码位置

文件 说明
packages/opencode/src/config/mcp.ts Local / Remote / OAuth 类型定义
packages/opencode/src/mcp/index.ts MCP 服务:连接、工具注册、OAuth 流程
packages/opencode/src/mcp/auth.ts OAuth Token 持久化存储
packages/opencode/src/mcp/oauth-provider.ts OAuth Provider 实现
packages/opencode/src/mcp/oauth-callback.ts OAuth 回调服务器(本地 HTTP)
packages/opencode/src/cli/cmd/mcp.ts CLI 命令:opencode mcp add/list/auth/logout/debug
相关推荐
MATLAB代码顾问2 小时前
MATLAB实现灰狼算法优化PID参数
算法·机器学习·matlab
承渊政道3 小时前
【动态规划算法】(完全背包问题从状态定义到空间优化)
数据结构·c++·学习·算法·leetcode·动态规划·哈希算法
超级大福宝3 小时前
【力扣48. 旋转图像】超好记忆版 + 口诀
c++·算法·leetcode
爱写代码的倒霉蛋3 小时前
2023年天梯赛L1-8
数据结构·算法
apollowing3 小时前
启发式算法WebApp实验室:从搜索策略到群体智能的能力进阶(上)
算法·启发式算法·web app
生物信息与育种3 小时前
黄三文院士领衔植物星球计划(PLANeT)发表Cell
人工智能·深度学习·算法·面试·transformer
aini_lovee4 小时前
WSN 四大经典无需测距定位算法
算法
人道领域4 小时前
【LeetCode刷题日记】掌握二叉树遍历:栈实现的三种绝妙方法
算法·leetcode·职场和发展