Skip to main content

Module mcp_seed

Module mcp_seed 

Source
Expand description

Starter MCP Servers catalog seed: preloads a small set of curated global, credential-free MCP servers (db_mcp_servers, the v1 standalone catalog) on fresh install.

Mirrors skill_seed.rs exactly, for the same reasons documented there: the actual “run exactly once, ever” gating lives in migrations::m0016_seed_starter_mcp_servers, tracked in the channel’s db_migrations table — NOT in this module, and NOT gated on “is the catalog currently empty” (that gate can’t distinguish “never seeded” from “seeded then the user deleted every starter server on purpose”, which would silently resurrect the defaults on the next restart after a full deletion — see m0015_seed_starter_skills.rs’s history, reagent P2 on PR #2141 round 2, for why this shape was chosen over a simpler one). This module exposes only the pure insert logic; the migration owns invocation.

Only credential-free, fully local servers belong in this manifest — see docs/specs/SPEC_ARMORY_MCP_SERVER_DEFAULT_SEED_CATALOG_2026_07_13.md §2: every is_global MCP server is auto-injected into every agent’s .mcp.json at launch with no per-agent opt-in, so a seeded row needing an API key or OAuth token would break every agent’s launch by default. The Filesystem reference server is deliberately NOT included despite being credential-free — it requires an allowlisted directory as a CLI arg with no environment-agnostic default (spec §9 open question 3); it can be added once that’s resolved, either by computing a per-agent default at config-build time or shipping it with an explicit prereq the user fills in via the existing catalog-picker mechanism instead.

Ids are deterministic, not randomly minted — same reasoning as skill_seed.rs::starter_skill_id, mirrored here for MCP servers via entry.name (there is no separate slug field for a server the way a skill has trigger; name already plays that role — it’s the catalog key mcp_server_upsert_unique_global enforces uniqueness on). See Phase 1 of SPEC_DURABLE_BINDINGS_2026_09_10.md.

Structs§

StarterMcpServer 🔒
One entry in the embedded starter-mcp-servers manifest. config is a raw JSON object here (command/args/env) and gets re-serialized to a string to match McpServer.config’s storage shape.

Constants§

STARTER_MCP_SERVERS_JSON 🔒
The embedded starter-mcp-servers manifest JSON. Content is authored externally and must not be edited here — see crates/srv/src/config/starter-mcp-servers.json.

Functions§

any_starter_mcp_server_name_exists 🔒
True if any global MCP server whose name matches a starter entry’s name already exists — i.e. this channel already effectively has the starter set (or a name collision with it). The caller (migrations::m0016_seed_starter_mcp_servers) uses this to skip seeding entirely rather than attempting an insert that would collide on mcp_server_upsert_unique_global’s name-uniqueness check and permanently fail the migration on every subsequent boot — same self-heal skill_seed.rs::any_starter_skill_name_exists provides (reagent P1, PR #2144).
reject_duplicate_names 🔒
Guard against a manifest-authoring mistake: two entries sharing a name. Mirrors skill_seed::reject_duplicate_triggers exactly — see its doc comment for the full failure mode this closes (reagent P2, PR #3175). name here plays the role trigger plays for skills: it is both the stable key starter_mcp_server_id derives from AND the field mcp_server_upsert_unique_global’s own duplicate check is keyed on, which is exactly the combination that turned “id collision” into “duplicate-check bypass” for skills.
seed_starter_mcp_servers 🔒
Parse the embedded manifest and insert every entry as a global MCP server via the validated mcp_server_upsert_unique_global path. Does NOT check whether the catalog is already populated — the caller (migrations::m0016_seed_starter_mcp_servers) owns run-once gating via db_migrations tracking, not catalog contents. Exposed at pub(crate) so the migration and tests can call it directly.
starter_mcp_server_id 🔒
Deterministic row id for a starter MCP server, derived from its name. See skill_seed::starter_skill_id’s doc comment for the full reasoning — this is the identical derivation keyed on the server’s catalog name instead of a skill’s trigger, in its own, distinct namespace so a skill and an MCP server that happened to share a stable-key string could never collide on id.