这次不是模型效果问题。
Agent 页面能正常对话,流式输出也没问题。出问题是在接 MCP 工具之后:Git 工具能看到仓库名,但读 diff 报 permission denied;Playwright 工具容器启动慢,偶尔卡在依赖下载;数据库工具能连上,但权限太大;最后日志散在 Agent 应用、MCP Server 和浏览器容器里,排起来很别扭。
我一开始也想继续看 Agent 的 prompt。后来发现方向不对:接上 MCP 后,它已经不是一个"会回答的服务",而是一组会读文件、访问网络、跑浏览器、连数据库的工具进程。
所以这次我按运行边界重新排了一遍。
这类 Agent 为什么值得接工具
如果 Agent 只是回答问题,它的价值很容易停在"更聪明的问答入口"。接上工具以后,它才开始像一个能嵌进研发流程的执行单元。
我这边比较明确的场景有几个:
- 代码仓库巡检:读 diff、看构建脚本、整理影响范围。
- PR 辅助:生成变更摘要、补测试建议、标出可能遗漏的配置项。
- Web 巡检:用浏览器工具打开测试环境,跑基础路径,收集截图和错误日志。
- 数据排查:用只读账号查异常指标,把 SQL、结果和解释整理到一份报告。
- 运维 runbook:按固定步骤查容器状态、服务日志、最近发布记录。
- 内部知识库:把文档、工单和代码上下文合在一起回答团队问题。
这些场景共同点是:人不是不会做,而是动作分散、上下文多、重复整理耗时间。Agent 适合把这些步骤串起来。问题是,它一旦能串工具,就必须先把环境边界排清楚。
先把"服务没起来"和"权限不对"分开
最容易混在一起的是服务启动问题和权限问题。
MCP 工具服务来源很分散:GitHub MCP Server、浏览器运行时、数据库和缓存可能来自不同制品源。直接 docker compose up -d,失败时只能看到一串服务异常,不容易判断到底是哪一步卡了。
我先把关键依赖拆开:
bash
docker pull ghcr.1ms.run/github/github-mcp-server
docker pull mcr.1ms.run/playwright/mcp
docker pull docker.1ms.run/postgres:16-alpine
docker pull docker.1ms.run/redis:7-alpine
这一步只解决一件事:先确认关键工具依赖能进入环境。启动层过了,后面看到的 permission denied 才更像真实权限问题。
这一步不要写成万能方案。它只是把排查链路的第一层先清掉。
Compose 里我最先改的是挂载目录
原来的 compose 配置很省事,Agent 应用能看到很多宿主机目录。Demo 阶段方便,上线前就不合适。
我把它改成两个目录:
yaml
services:
agent-api:
image: docker.1ms.run/python:3.12-slim
working_dir: /app
command: ["python", "server.py"]
env_file:
- .env.agent
volumes:
- ./app:/app:ro
- ./workspace:/workspace
depends_on:
- mcp-github
- mcp-browser
- redis
/app 只读,Agent 能看应用代码,但不能改。
/workspace 可写,用来放任务输出、中间文件和报告。
这个边界很朴素,但比"挂整个项目根目录进去"清楚得多。
MCP 工具服务单独跑
接下来把工具拆开,不和 Agent 应用混在一个容器里:
yaml
mcp-github:
image: ghcr.1ms.run/github/github-mcp-server
env_file:
- .env.github.readonly
read_only: true
cap_drop:
- ALL
mcp-browser:
image: mcr.1ms.run/playwright/mcp
shm_size: "1gb"
cap_drop:
- ALL
redis:
image: docker.1ms.run/redis:7-alpine
这里的重点不是 YAML 写法本身,而是把能力拆开:
- GitHub MCP 用只读 token。
- Browser MCP 单独限制资源。
- Agent 应用不直接拿所有工具的凭证。
- 工具容器能独立重启,出问题不影响主应用。
我也明确不挂 /var/run/docker.sock。Agent 如果能控制宿主机 Docker,很多容器层的限制就失效了。
验证不只看 up -d
启动以后,我没有只看容器是不是 running,而是补了几条很笨但有效的检查:
bash
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=120 mcp-github mcp-browser
docker exec agent-api test -w /workspace
docker exec agent-api test ! -w /app
这几条能回答几个关键问题:
关键依赖是不是已经就绪。
MCP Server 日志是不是独立可看。
Agent 能不能写工作区。
Agent 会不会误写应用目录。
如果这些都没确认,后面再谈工具调用链路其实很虚。
我最后留下的上线前清单
这次排完,我把检查项收敛成这几条:
- MCP 工具依赖先单独预检。
- Agent 应用和工具服务拆开跑。
- 应用目录只读,工作区单独挂载。
- Git、数据库、浏览器工具按最小权限配置。
- 不给 Agent 挂 Docker socket。
- Secret 按工具拆分。
- 工具调用日志能追到会话和结果。
- MCP Server 可以独立回滚。
复盘
AI Agent 接上 MCP 后,价值也更清楚了:它能把代码、测试、数据、运维和知识库这些分散动作串成流程。难点也跟着变了,不再只是模型调优。模型负责规划,工具负责执行;一旦能执行,工程侧就要处理工具依赖、目录、权限、Secret、网络和日志。
我现在更愿意先问:这个 Agent 的动作边界在哪里?工具失败时能不能复盘?MCP Server 能不能单独回滚?
这些问题答清楚,Agent 才像一个能进团队环境的工程系统。