feat(agent-config): AOI-2 MCP env-merge + forge-identity guardrail #763

Merged
charles merged 1 commit from code-lead/731 into main 2026-05-02 18:51:34 +00:00
Collaborator

Closes #731

Instance-scope mcp_server rows whose name matches an inherited row now merge their env map into the parent record per-key (instance overrides parent, absent keys inherit). The other fields (command/args/transport/url) come from the parent — divergent values are rejected by the route validator.

Forge MCP auth env (FORGE_TOKEN / FORGE_TOKENS) is bound to the agent's type identity by construction. The lock list lives in config/mcp-builtin-locks.json so FM-3 can extend it for github / gitlab without code changes.

Test plan

  • resolver: instance row partial env merges with parent env
  • resolver: locked keys stripped from non-builtin env
  • route: PUT with locked env key rejected at any scope
  • route: instance PUT with divergent transport / command rejected
  • render: locked-key MCPs receive type-derived auth env at render time
  • render: stale locked-key DB value overwritten by type identity
  • CI green
Closes #731 Instance-scope `mcp_server` rows whose `name` matches an inherited row now merge their `env` map into the parent record per-key (instance overrides parent, absent keys inherit). The other fields (`command`/`args`/`transport`/`url`) come from the parent — divergent values are rejected by the route validator. Forge MCP auth env (`FORGE_TOKEN` / `FORGE_TOKENS`) is bound to the agent's type identity by construction. The lock list lives in `config/mcp-builtin-locks.json` so FM-3 can extend it for `github` / `gitlab` without code changes. ## Test plan - [ ] resolver: instance row partial env merges with parent env - [ ] resolver: locked keys stripped from non-builtin env - [ ] route: PUT with locked env key rejected at any scope - [ ] route: instance PUT with divergent transport / command rejected - [ ] render: locked-key MCPs receive type-derived auth env at render time - [ ] render: stale locked-key DB value overwritten by type identity - [ ] CI green
feat(agent-config): AOI-2 MCP env-merge + forge-identity guardrail
All checks were successful
qa / dockerfile (pull_request) Successful in 5s
qa / qa (pull_request) Successful in 2m32s
832590acc4
Closes #731

- Resolver merges instance-scope mcp_server.env into the inherited row
  per-key instead of replacing the record. command/args/transport/url
  come from the parent.
- New config/mcp-builtin-locks.json registers per-MCP env keys bound to
  the agent's type identity (forge → FORGE_TOKEN / FORGE_TOKENS).
  Resolver strips locked keys from non-builtin layers; render-for-instance
  injects them from ResolvedAgent.tokens / token at write-to-disk time.
- agent-config PUT/fork/restore reject env writes that touch a locked
  key and instance-scope writes whose command/args/transport/url
  diverge from the parent.
reviewer approved these changes 2026-05-02 18:32:23 +00:00
reviewer left a comment

CI green. All AOI-2 ACs met: env-merge, forge-identity guardrail, locked-key validation, and render-time injection all correct and tested.

Nit (non-blocking): no test for divergent args rejection in the route validator — trivial gap given args overrides are rare in practice.

CI green. All AOI-2 ACs met: env-merge, forge-identity guardrail, locked-key validation, and render-time injection all correct and tested. Nit (non-blocking): no test for divergent `args` rejection in the route validator — trivial gap given args overrides are rare in practice.
charles deleted branch code-lead/731 2026-05-02 18:51:34 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks!763
No description provided.