An inherited-layer mutation (global config or persona definition) could
silently push an existing buzz-agent over the 15-server effective cap,
breaking it at next spawn. Add pre-save cross-checks at both save
paths so the save is rejected atomically with the offending agent named.
F1: Effective-merge MCP cap check at agent create/update save time.
validate_effective_mcp_cap calls effective_buzz_agent_mcp_servers
(the same resolver used at spawn) and rejects when the three-layer
merge (global < definition < agent) exceeds MAX_USER_MCP_SERVERS.
Prevents a per-layer-valid record from silently breaking at spawn or
emptying the WYSIWYG surface. Editor now shows a destructive error
whenever effective count exceeds the cap (fires on rename too).
4 Rust unit tests: 15-global+1-local → Err, at-cap → Ok,
rename-unmask → Err, non-buzz-agent skip.
F2: Complete the client-side Rust mirror — validateMcpServerRow now
checks command NUL + ≤32KB; new validateMcpServerArg checks arg
NUL + ≤32KB with inline subrow errors; new validateMcpServerListPayload
checks aggregate total payload ≤256KB (name+command+args+env bytes
across all servers) with editor-level error. Adds MAX_ENV_TOTAL_BYTES
constant. 9 unit tests: command NUL/oversize/at-limit, arg NUL/oversize
/valid, payload under/over/at-limit.
check-file-sizes.mjs: agent_models.rs override bumped 1079→1082
(+3 lines for the effective-cap block).
Add buzz_agent_mcp_servers to RuntimeConfigSurface, populated by
resolve_config_surface via the existing effective_buzz_agent_mcp_servers
merge (global < definition < agent, enabled-only) for the buzz-agent
runtime only. Every other runtime keeps the field empty and continues
to surface its servers via extensions.
This is the WYSIWYG read path the PR3 UI's read-only buzzAgentSlot will
consume — the effective list is now reachable from the config-bridge
surface the frontend already reads, matching what actually runs at
spawn (spawn_hash.rs, runtime.rs) rather than just the agent's own
record layer.
Also bumps two pre-existing file-size overrides (agent_config.rs,
readiness.rs) to their gate's own split-count, matching this diff and
a prior unaccounted +1 line already on the branch.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Borrow the disabled mask for validation before moving it into the merge assertion, avoiding an unnecessary clone.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
New snapshot construction sites added after the original MCP change require empty local-only MCP configuration. Raise the discovery fixture-file exception by the two required fields.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
F1: Extend env_secrets_from_request in backend.rs to harvest
mcp_servers[*].env[*].value alongside env_vars, so provider errors
that echo MCP env values are redacted from desktop-visible last_error.
Add two regression tests: one verifying harvest coverage, one verifying
end-to-end redaction.
F2: Extend validate_mcp_servers in types/mcp_servers.rs to mirror the
buzz-agent name grammar (1-128 bytes, ASCII alnum/_/-, no __) and
reserve the built-in buzz-dev-mcp name. Both checks fire at every IPC
save boundary, so names that would fail at spawn are rejected at edit
time. Add tests covering invalid chars, double-underscore, reserved
name, valid grammar.
F3: Restructure build_mcp_servers in buzz-acp/src/lib.rs so the
built-in server push is conditional on mcp_command being non-empty, but
configured_mcp_servers are always appended. Previously the early-return
on empty mcp_command silently discarded user-configured servers even
though they don't depend on the built-in slot. Update the test that
pinned the old drop behavior; add a complementary empty-with-no-servers
test.
F4: Add an enabled-server count check to validate_mcp_servers: a layer
with more than MAX_USER_MCP_SERVERS enabled servers is rejected at save
time rather than only at merge/spawn. Add boundary tests (15 passes,
16 fails).
MINOR: Add mcp_servers to the MUST NEVER list in agent_events.rs so
future edits don't miss the local-only invariant.
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
Add local-only MCP server layering (global < definition < agent) for
buzz-agent. Other runtimes manage their own MCP config and are unchanged.
- McpServerConfig/McpServerTransport types with validate/merge/replace helpers
- BUZZ_ACP_MCP_SERVERS reserved env key; desktop injects transport JSON only
for buzz-agent children, explicitly removes it for all others
- spawn_config_hash includes effective MCP layer so config drift triggers restart
- build_deploy_payload forwards resolved Mcp transport to providers
- agent_snapshot excludes mcp_servers (credentials in env vars)
- GlobalAgentConfig.mcp_servers: inherits to every buzz-agent instance
- AgentDefinition.mcp_servers: definition layer (not copied into record on mint)
- ManagedAgentRecord.mcp_servers: per-agent override layer
- buzz-acp: ConfiguredMcpServer deserialized from BUZZ_ACP_MCP_SERVERS; appended
after built-in buzz-dev-mcp in build_mcp_servers
- Max 15 user-defined servers (slot 16 is reserved for buzz-dev-mcp)
- IPC validation at every save boundary: empty name, duplicate names, enabled
with empty command, NUL bytes, per-field length cap, total payload cap,
reserved env key guard
Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>