07 · 工具、MCP、LSP 与格式化器
理解 OpenCode 如何连接文件系统、shell、MCP server、LSP 和 formatter。
Coding agent 的质量不只取决于模型,也取决于它能接触哪些工具。OpenCode 的工具系统把文件系统、shell、MCP server、LSP、formatter 和 custom tools 接到同一个工作流里。
这一篇解决“工具该接到什么程度”的问题。读完以后,你应该能判断:哪些任务只用内置工具就够,什么时候接 MCP,LSP 能帮什么,formatter 应该怎么开,自定义工具什么时候值得写,以及为什么工具越多越要收紧权限。
先给结论:先用内置工具完成读文件、搜代码、改文件、跑测试;只有需要外部系统时再接 MCP;只有项目语言服务可用时再依赖 LSP;formatter 不要掩盖逻辑 diff;custom tool 只封装重复、可验证、边界清楚的项目动作。
工具扩展地图
OpenCode 工具不是平铺清单,而是一组逐步扩大行动范围的能力。
flowchart TB
Builtin["内置工具<br/>read / grep / edit / bash"] --> LSP["LSP<br/>诊断 / 定义 / 引用"]
Builtin --> Formatter["Formatter<br/>机械格式化"]
Builtin --> Custom["Custom Tools<br/>项目专有动作"]
Custom --> MCP["MCP Servers<br/>外部系统上下文"]
MCP --> Plugin["Plugins<br/>运行时扩展"]
Permission["Permission<br/>allow / ask / deny"] --> Builtin
Permission --> Custom
Permission --> MCP
style Builtin fill:#dbeafe,stroke:#3b82f6,stroke-width:2px
style MCP fill:#fef3c7,stroke:#f59e0b
style Plugin fill:#fee2e2,stroke:#ef4444
style Permission fill:#dcfce7,stroke:#22c55e
判断顺序是:内置工具能解决就不要接 MCP,项目命令能明确封装再做 custom tool,需要运行时事件才考虑 plugin。
1. 工具系统先分层
OpenCode 的工具可以按距离项目核心的远近分层:
内置工具 读写文件、搜索、shell、patch、webfetch
LSP 代码诊断、符号、定义、引用、类型信号
Formatter 文件写入后的机械格式化
Custom Tools 项目专有动作
MCP Servers 外部系统和远程上下文
Plugins 运行时生命周期扩展不要把这些层混成“工具越多越好”。每多接一层,模型可选动作、上下文成本和权限风险都会增加。
2. 内置工具先够用
大多数任务先用内置能力就够:
- 读取文件。
- 搜索文件和内容。
- 修改文件。
- 应用 patch。
- 运行 shell 命令。
- 执行测试和格式化。
- 获取指定网页内容。
- 根据命令输出继续修复。
官方 Tools 文档说明,OpenCode 内置工具包括 bash、edit、write、read、grep、glob、lsp(实验性)、apply_patch、skill、todowrite、webfetch、websearch、question,并且可以通过 permission 控制。其中 websearch 走 Exa AI 的 MCP 服务,OpenCode 直连,不需要你额外配 API key。
常见内置工具可以这样理解:
| 工具 | 用途 | 权限建议 |
|---|---|---|
read / grep / glob | 读文件、搜代码、找路径 | 通常允许 |
edit / write / apply_patch | 修改文件、新建文件、应用补丁 | 默认 ask,审查类 agent deny |
bash | 运行命令、测试、构建、诊断 | 默认 ask,高风险命令 deny |
lsp(实验性) | 跳定义、找引用、查类型、调用层级 | 通常允许(参第 6 节) |
skill | 按需加载 SKILL.md | 内部 skill 默认 ask |
webfetch / websearch | 获取网页或搜索外部信息 | 研究类 allow,隐私敏感项目 ask |
todowrite | 维护多步骤任务的待办清单 | 通常允许 |
question | 执行中向用户提问 | 适合关键决策点 |
文件写入是一组能力:官方文档说明 write、edit、apply_patch 这类文件修改能力受 edit 权限治理。不要只盯着一个工具名,以为禁了 write 就万事大吉。
3. 权限要先于扩展
官方文档说内置工具默认启用;真实项目里,不应该长期依赖默认开放状态。项目级配置可以先收紧:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"read": "allow",
"grep": "allow",
"glob": "allow",
"edit": "ask",
"bash": "ask",
"webfetch": "ask"
}
}如果某个 MCP server 暴露了一组工具,可以用通配符控制:
{
"$schema": "https://opencode.ai/config.json",
"permission": {
"sentry_*": "ask",
"github_*": "ask"
}
}这比在提示词里写“谨慎操作”可靠。提示词是意图,permission 是执行边界。
4. MCP 适合外部上下文
MCP server 适合把外部系统变成 agent 可调用工具。例如:
- GitHub issue / PR。
- 数据库查询。
- 内部 API。
- 文档搜索。
- 设计稿读取。
- 浏览器自动化。
- 项目管理系统。
MCP 的价值是让 agent 获取“项目外部上下文”。如果信息已经在本地文件里,就不一定需要 MCP。
MCP 不是越多越好:官方文档提醒,MCP 工具会增加上下文,工具多了可能很快吃掉上下文窗口。GitHub 这类 MCP 往往工具很多,启用前要确认你真的需要。
5. MCP 本地和远程怎么选
OpenCode 支持本地和远程 MCP。
| 类型 | 适合场景 | 风险点 |
|---|---|---|
| Local MCP | 需要本机 CLI、内网、文件系统、项目环境 | 换机器要重配,命令环境可能不一致 |
| Remote MCP | SaaS、文档搜索、云服务、团队统一入口 | OAuth、API key、远程权限和数据边界 |
最小配置示例:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"context7": {
"type": "remote",
"url": "https://mcp.context7.com/mcp",
"enabled": true
}
}
}本地 MCP 示例:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"my-local-server": {
"type": "local",
"command": ["npx", "-y", "my-mcp-command"],
"enabled": true,
"environment": {
"MY_ENV_VAR": "my_env_var_value"
}
}
}
}先用只读问题验证,再考虑写入型工具。常用检查命令:
opencode mcp list
opencode mcp auth context76. LSP 的价值
LSP 给 agent 提供更接近 IDE 的代码理解能力,包括符号、诊断、跳转和类型信息。对大型代码库来说,这比单纯全文搜索更可靠。
适合依赖 LSP 的任务:
- 找函数定义和引用。
- 判断类型错误。
- 理解跨文件调用关系。
- 修复编译诊断。
- 做局部重命名或接口调整。
官方 LSP 文档说明,OpenCode 内置了多种语言服务器集成。满足文件扩展名和依赖要求时,相关 LSP server 会启动;也可以通过 lsp 配置禁用、定制命令、环境变量和初始化选项。
{
"$schema": "https://opencode.ai/config.json",
"lsp": {
"typescript": {
"initialization": {
"preferences": {
"importModuleSpecifierPreference": "relative"
}
}
}
}
}但 LSP 不是万能。项目依赖没装好、语言服务器没启动、monorepo 配置复杂时,LSP 信息也可能不完整。关键改动仍要靠测试、类型检查和人工 review 验证。
LSP 信号要和测试结合:LSP 适合告诉 agent “哪里有诊断、定义在哪里、引用有哪些”,但不能替代真实构建和测试。
7. Formatter 只做机械格式化
Formatter 适合做机械格式化,不适合掩盖逻辑问题。官方文档说明,formatter 默认是禁用的,需要在配置里启用。
启用所有内置 formatter:
{
"$schema": "https://opencode.ai/config.json",
"formatter": true
}禁用或覆盖某个 formatter:
{
"$schema": "https://opencode.ai/config.json",
"formatter": {
"prettier": {
"disabled": true
}
}
}推荐改动流程:
1. 让 agent 完成最小代码改动
2. 跑测试或类型检查
3. 再运行 formatter
4. 检查 diff 是否只包含预期范围不要一开始就全仓库格式化。大范围格式化会淹没真实逻辑 diff,也增加回滚风险。
8. Custom Tools 什么时候需要
当一个 shell 命令反复使用,并且输出需要被 agent 稳定解释时,可以封装成 custom tool。
适合封装的例子:
- 查询内部服务状态。
- 运行项目专用诊断。
- 读取结构化配置。
- 生成固定格式报告。
- 调用公司内部 API。
官方 Custom Tools 文档说明,工具定义用 TypeScript / JavaScript 文件,放在 .opencode/tools/ 或 ~/.config/opencode/tools/。工具定义可以调用其他语言脚本。
最小只读工具示例:
import { tool } from "@opencode-ai/plugin";
export default tool({
description: "Return current project directory information",
args: {},
async execute(args, context) {
return `directory=${context.directory}\nworktree=${context.worktree}`;
},
});不要把危险操作封装成“一键执行”的工具,例如删除数据、发布生产、重置数据库。即使封装,也必须加确认、dry-run、参数校验和权限边界。
9. 怎么决定用哪一层
可以按这个顺序判断:
| 需求 | 优先方案 |
|---|---|
| 读文件、搜代码、跑测试 | 内置工具 |
| 需要代码诊断、定义、引用 | LSP |
| 需要保持风格一致 | Formatter |
| 需要调用项目专有动作 | Custom Tool |
| 需要外部系统上下文 | MCP |
| 需要改变 OpenCode 生命周期 | Plugin |
不要用 MCP 解决本地 grep 能解决的问题,也不要用 custom tool 包装一次性命令。工具进入 OpenCode 后,就会变成模型可能调用的能力,需要长期维护。
10. 工具治理原则
接工具时,按风险逐步推进:
本地只读工具
本地可写工具
项目测试/检查工具
MCP 只读外部工具
MCP 可写外部工具
发布/生产工具每往后一层,权限和审计要求都要更严格。
建议默认规则:
- 只读工具可以更开放。
- 写文件和 bash 默认
ask。 - 外部写入 MCP 默认
ask或deny。 - 生产、发布、删除、数据库写入不要自动允许。
- 全局工具少放,项目工具先验证。
- 工具输出要短,避免把日志和敏感信息塞进上下文。
11. 怎么验收
你可以用 6 个问题检查工具体系是否过关:
| # | 问题 | 自检 |
|---|---|---|
| 1 | 内置工具能解决的问题,是否没有额外接 MCP? | ☐ |
| 2 | 写文件、bash、外部系统写入是否有 permission 边界? | ☐ |
| 3 | MCP 是否只启用了真正高频的 1-3 个? | ☐ |
| 4 | LSP 诊断是否通过测试或类型检查验证过? | ☐ |
| 5 | Formatter 是否没有扩大无关 diff? | ☐ |
| 6 | Custom tool 是否只读起步,参数和输出都可控? | ☐ |
过关标准:你能解释每个工具为什么存在、谁能调用、是否会写入外部系统,以及出问题时如何关闭它。
接下来去哪
工具总览
查看内置工具、permission、apply_patch、web 工具和 custom tool 的官方边界。
连接 MCP
需要外部系统上下文时,再按只读、少数、按 agent 开放的原则接入 MCP。
LSP 与格式化器
把诊断信号和机械格式化分开,不让 formatter 掩盖逻辑 diff。
安全、分享与团队使用
工具接入后,继续收紧权限、密钥、分享和团队 review 边界。
官方资料
- Tools:https://opencode.ai/docs/tools
- MCP servers:https://opencode.ai/docs/mcp-servers
- LSP Servers:https://opencode.ai/docs/lsp
- Custom Tools:https://opencode.ai/docs/custom-tools
- Formatters:https://opencode.ai/docs/formatters