Summary
The MCP install helper (#310) needs to add and update [mcp.servers.<name>] entries in a user's config.toml "without destroying unrelated settings" (epic acceptance criteria). Today the agent config is read-only: aura-config only parses, and the format-preserving toml_edit machinery in aura-cli/src/config.rs is scoped to the CLI's own cli.toml.
This issue adds the reusable building block: a writer in aura-config that upserts a single MCP server entry into an existing config file.
Scope
aura_config::writer::upsert_mcp_server(path, name, &McpServerConfig) plus a string-level variant for testability.
- Format-preserving via
toml_edit: unrelated tables, sibling servers, comments, and value decor survive the edit.
- Atomic write (temp file + rename in the same directory), matching the existing
cli.toml save path.
{{ env.VAR }} placeholder strings pass through verbatim, so callers can keep secrets out of the TOML.
- Creates
[mcp] / [mcp.servers] as explicit tables when missing; replaces an existing server table wholesale on name collision.
- Errors (rather than clobbering) on malformed TOML or a missing config file.
- Written output must round-trip through the normal loader back into an equal
McpServerConfig for all three transports (stdio, http_streamable, sse).
Non-goals
Summary
The MCP install helper (#310) needs to add and update
[mcp.servers.<name>]entries in a user'sconfig.toml"without destroying unrelated settings" (epic acceptance criteria). Today the agent config is read-only:aura-configonly parses, and the format-preservingtoml_editmachinery inaura-cli/src/config.rsis scoped to the CLI's owncli.toml.This issue adds the reusable building block: a writer in
aura-configthat upserts a single MCP server entry into an existing config file.Scope
aura_config::writer::upsert_mcp_server(path, name, &McpServerConfig)plus a string-level variant for testability.toml_edit: unrelated tables, sibling servers, comments, and value decor survive the edit.cli.tomlsave path.{{ env.VAR }}placeholder strings pass through verbatim, so callers can keep secrets out of the TOML.[mcp]/[mcp.servers]as explicit tables when missing; replaces an existing server table wholesale on name collision.McpServerConfigfor all three transports (stdio,http_streamable,sse).Non-goals
/mcpflow builds on this separately).mcp_filtersemantics ([FEATURE]: Empty worker mcp_filter grants access to all MCP tools #378).