你从一个 MCP 服务器开始。文件访问,让你的 Claude Code 智能体能够读写项目。合理的选择。
然后添加了网页搜索。然后是 GitHub。然后是数据库工具,让智能体能直接查询你的 schema。然后是 Slack,因为智能体需要查看需求讨论帖。然后是内部 Wiki 的文档工具。
六个 MCP 服务器。每一个都在智能体的上下文中注册工具 schema。每一个都扩大了智能体可能做的事情的范围,这意味着更多 token 花在工具描述上,智能体偏离任务的机会也更多。
你的智能体仍然在写好代码。但写得更慢了,输出变得不那么可预测。你没有在想象。上下文窗口是瓶颈,而你正在用管道把它填满。
累积问题
MCP 服务器很强大。Model Context Protocol 让 Claude Code 能访问外部系统,每个集成确实解决了一个问题。文件访问让智能体读取代码库。网页搜索让它查找文档。GitHub 集成让它检查 PR 状态。
问题始于你用增加另一个 MCP 来解决智能体的每一个需求。
智能体需要检查数据库 schema?添加 Postgres MCP。智能体需要读 Confluence 页面?添加 Confluence MCP。智能体需要发 Slack 消息?添加 Slack MCP。每个单独来看都是合理的。合在一起,它们创造了一个在输出质量下降之前很难注意到的问题。
每个 MCP 服务器在对话上下文中注册自己的工具。文件访问 MCP 可能注册 5-10 个工具。数据库 MCP 再注册几个。GitHub MCP 添加更多。当你有六个 MCP 服务器时,智能体在读你的第一行代码之前,就已经在上下文窗口中携带了数十个工具定义。
这些工具定义不是免费的。它们消耗 token。更重要的是,它们争夺智能体的注意力。当智能体有 40 个可用工具时,每个决策点都变成分支问题:该用文件工具、搜索工具、数据库工具还是 GitHub 工具?智能体把认知预算花在决定如何获取信息上,而不是使用信息来解决你的问题。
上下文有限。注意力更稀缺。
Claude Code 的上下文窗口很大。这制造了一种危险的错觉:你可以不断添加信息而不产生后果。
实际上,智能体性能在上下文窗口填满之前就已经开始下降。问题不是容量。是信噪比。一个拥有 200K token 上下文窗口的智能体,使用 50K token 的专注相关信息比使用 150K token(相关部分散布在工具 schema、API 响应和无关文件内容之间)表现更好。
这和人类面对太多浏览器标签时的问题一样。信息在技术上是可用的。找到它花的时间比应该的要长。你最终重新阅读已经看过的东西,因为相关上下文被噪声从工作记忆中挤出去了。
对于智能体,这表现为:
兔子洞。 智能体有数据库工具,所以查询 schema。Schema 很有趣,所以查询数据。数据揭示了意外的东西,所以深入调查。二十分钟后,你有了数据库内容的详尽分析,但你要求的功能进展为零。
工具混淆。 有了很多可用工具,智能体偶尔会选错。用网页搜索去找已经在本地文件中的文档。在答案就在任务描述中时查询数据库。每次错误的工具选择都浪费 token 并引入噪声。
稀释的专注。 智能体的"注意力"是每次生成中的有限资源。当上下文包含文件访问、网页搜索、数据库查询、GitHub 操作、Slack 消息和 Wiki 查询的工具 schema 时,智能体在处理你的实际请求之前先处理了所有这些。任务与工具在认知优先级上竞争。
有界上下文:工具膨胀的替代方案
对"我的智能体需要信息 X"的条件反射是给智能体一个获取 X 的工具。但还有另一种方法:把 X 放进任务里。
这就是有界上下文模式。不是给智能体访问一切的权限然后期望它找到相关的,而是给每个智能体一个包含完成工作所需一切的任务。智能体不搜索上下文。上下文被交付。
差异是结构性的。有 MCP 膨胀时,智能体的工作流程是:
- 读取任务
- 弄清缺少什么信息
- 使用各种工具收集信息
- 综合信息
- 做实际工作
有界上下文下是:
- 读取任务(包含所有必要上下文)
- 做实际工作
第一个工作流程中的步骤 2-4 不仅仅是开销。那正是出问题的地方。智能体收集了太多信息,或者错误的信息,或者被有趣但无关的数据分散了注意力。每次工具调用都是潜在的弯路。
有界上下文不意味着智能体不能使用工具。文件访问对于读写代码仍然是必要的。但它意味着信息性上下文(构建什么、为什么、哪些文件、验收标准是什么)存在于任务中,而不是智能体需要查询的工具中。
将任务构造为上下文容器
作为上下文容器的任务与典型的 Jira 票据或 GitHub Issue 不同。它是自包含的。阅读它的智能体应该拥有开始工作所需的一切,而不需要查询外部系统获取背景信息。
实践中是这样的:
Title: Add rate limiting to /api/search endpoint
Description:
The /api/search endpoint currently has no rate limiting.
Add a token bucket rate limiter at 100 requests/minute per IP.
Files to modify:
- server/middleware/rate-limit.ts (create new)
- server/routes/search.ts (apply middleware)
- server/config.ts (add RATE_LIMIT_RPM env var)
Acceptance criteria:
- Requests beyond 100/min from same IP return 429
- Rate limit resets after 60 seconds
- Config value overridable via environment variable
- Existing tests still pass
Context:
- We use Express middleware pattern (see server/middleware/auth.ts for example)
- The config module uses dotenv (see server/config.ts lines 1-15)
- No Redis available; use in-memory store. This is a single-instance app.
Dependencies: None. This can run independently.
注意任务中嵌入了什么。智能体知道要修改哪些文件、遵循什么模式、存在什么约束(没有 Redis),以及"完成"具体是什么样子。不需要数据库 MCP 来检查 schema。不需要 Wiki 工具来找中间件模式。不需要搜索代码库来理解配置方法。一切都在任务中。
这样写任务需要更多前期投入。典型的票据可能只说"给搜索端点添加速率限制"然后让智能体自己弄清楚。但那个弄清楚的过程正是 MCP 膨胀的来源:智能体需要信息,所以你给它工具,工具消耗上下文。
CLAUDE.md 作为上下文边界
任务告诉智能体构建什么。CLAUDE.md 文件告诉它生活在什么世界里。
如果你正在运行多个 Claude Code 智能体,每个都应该有一个定义其范围的 CLAUDE.md,而不仅仅是指令。把它想象成上下文围栏:围栏内的一切是智能体的责任,围栏外的一切是别人的事。
## Identity
Frontend engineer for ProjectX. You own components/, hooks/,
and app/pages/. You write React components with TypeScript.
## What you do NOT own
- server/ (backend engineer handles this)
- database/ (DBA handles schema changes)
- infrastructure/ (ops handles deployment configs)
## How to get information you need
- API contracts are in docs/api-spec.md
- Design specs are linked in the task description
- If you need backend changes, create a task for the backend agent
这个 CLAUDE.md 消除了整个类别的 MCP 需求。前端智能体不需要数据库 MCP,因为它不碰数据库。不需要部署工具,因为它不管理基础设施。它的上下文窗口保持干净,因为范围很窄。
"how to get information" 部分至关重要。不是给智能体一个搜索 API 契约的工具,而是告诉它契约在哪里。不是给它 Slack 权限去问后端团队问题,而是告诉它创建一个任务。信息流是显式的,不是涌现的。
这和管理 Claude Code 智能体任务是同一个原则:智能体在有清晰边界时比有无限访问权时工作得更好。你定义的每一个边界就是一个不需要的 MCP 服务器。
什么时候仍然需要 MCP
有界上下文并不完全消除 MCP。有些工具是真正必要的:
文件系统访问不可商量。智能体需要读写代码。这不是膨胀,是基础。
版本控制工具(git 操作)是智能体核心工作流程的一部分。提交、分支和 diff 是实现动作,不是信息收集的弯路。
语言服务器和 linter 提供无法预加载到任务描述中的实时反馈。智能体需要知道代码是否编译通过和类型检查是否通过。
区分在于实现工具(智能体用来做工作的东西)和信息收集工具(智能体用来弄清工作是什么的东西)。实现工具属于智能体的 MCP 配置。信息收集工具是你的任务描述需要更多上下文的信号。
如果你发现自己因为"智能体需要查找 X"而添加 MCP,问问 X 是否可以放在任务中。如果可以,放进去。如果不行(因为 X 经常变化、太大、或需要实时数据),那 MCP 是合理的。但这个问题每次都值得问。
Beads:作为有界上下文的任务
这是我们用来在单一代码库上协调 13 个 Claude Code 智能体的模式。每个智能体得到一个包含完整范围的任务和一个定义边界的 CLAUDE.md。这种组合意味着智能体很少需要文件访问和 git 之外的工具。
使这成为可能的 issue tracker 是 beads,一个开源的本地优先 CLI。每个 "bead" 是一个自包含的工作单元:标题、描述、验收标准和一个智能体发布计划和完成报告的评论帖。
创建带有嵌入上下文的任务:
bd create --title "Add rate limiting to /api/search" \
--description "Token bucket at 100 req/min per IP. \
Files: server/middleware/rate-limit.ts (new), \
server/routes/search.ts, server/config.ts. \
Pattern: see server/middleware/auth.ts. \
Constraint: in-memory store, no Redis." \
--priority p2
智能体认领任务并阅读:
bd update bb-r3k2 --claim --actor eng1
bd show bb-r3k2
智能体需要的一切都在 bead 中。描述包含文件、模式和约束。智能体不需要 Wiki MCP 来找中间件模式,因为任务说了 "see server/middleware/auth.ts"。不需要数据库 MCP,因为任务说了 "no Redis, use in-memory store"。
写代码前,智能体发布实现计划:
bd comments add bb-r3k2 --author eng1 "PLAN:
1. Create server/middleware/rate-limit.ts with token bucket
2. Wire into search route in server/routes/search.ts
3. Add RATE_LIMIT_RPM to server/config.ts with default 100
4. Add tests for 429 response and reset behavior"
实现后,智能体发布做了什么和如何验证:
bd comments add bb-r3k2 --author eng1 "DONE: Rate limiting added.
Commit: abc123
Verification:
- curl /api/search 101 times in 60s, 101st returns 429
- Set RATE_LIMIT_RPM=5, verify limit changes
- pnpm test passes (3 new tests added)"
从任务创建到实现再到验证的整个生命周期存在于一个地方。没有上下文因为在工具间跳转而丢失。没有 token 花在查询外部系统获取本可以写入任务的信息上。
在整个舰队中看到上下文边界
当你运行多个具有有界上下文的智能体时,新的问题出现了:谁的任务引用谁的文件?上下文边界在哪里重叠?哪个智能体在处理 API 层,我能安全地并行分配前端工作吗?
这是 CLI 本身变得有限的地方。bd list 显示任务和状态。它不显示任务之间的关系,也不能让你发现两个智能体的范围已经漂移到了同一片领地。
Beadbox 是一个实时仪表板,可视化这些边界。它显示依赖树(哪些任务阻塞哪些)、史诗进度(一个功能在所有子任务中进展到哪里)和智能体所有权(谁在做什么)。你看到全貌,无需在终端窗口间切换并在脑中拼凑。
Beta 期间免费,完全在你的机器上运行。无需账户,无云同步,不对你的项目数据做遥测。
如果你正在构建这样的工作流程,请在 GitHub 上给 Beadbox 点个 star。
Like what you read?
Beadbox is a real-time dashboard for AI agent coordination. Free during the beta.