# PROP-027 — `mcp` packages: the agent-server kind and its delivery {#root}

@status:impl/done

[p01] @fact:milestone-line **Milestone:** M1.26 candidate («MCP sovereignty» —
[MCP-SOVEREIGNTY-PLAN-v0.1](../../../legacy-spec/terraforms/MCP-SOVEREIGNTY-PLAN-v0.1.md)). @status:impl/done

[p02] @fact:status-line **Status:** IMPLEMENTED — the kind and the manifest laws (§2.1–§2.3)
shipped with the plan's Wave 1; the servers themselves (Waves 3–4:
`mcp:org.vibevm.ai-native/rust-ai-native-mcp`, `…/typescript-ai-native-mcp`, both
live-chained vibe-free); the registration lifecycle (§2.4–§2.5) with
Wave 5 (`vibe mcp install/uninstall/status` speak package servers; the
pin-server fixture e2e pins the walk). §2.7's composition rows inherit
the kind-agnostic feature suites — no feature branches on `kind`, and
the mcp e2e exercises code-bearing + binaries + the pin end to end. Units typed at REQ grain; the code carries the matching
`scope!` / `#[spec(implements)]` / `#[verifies]` edges. @status:impl/done

[p03] @fact:related **Related:** [PROP-015](PROP-015-mcp-integration.xml) (the product MCP
server + the agent-integration command family this PROP extends),
[PROP-025](../vibe-workspace/PROP-025-binary-delivery.xml) (the binary
delivery an `[[mcp_server]]` rides), [PROP-024](../../common/PROP-024-code-bearing-packages.xml)
(code-bearing packages; §2.4 is why mcp packages vendor),
[`VIBEVM-SPEC.md` §4.1](../../../VIBEVM-SPEC.md) (the kind register,
amended under owner sanction 2026-07-07). @status:spec/done

## 1. Motivation {#motivation}

- [p04] @fact:motivation-gap The discipline stacks ship engines, gates, CLIs, and type oracles —
  everything an agent-facing toolchain needs EXCEPT the transport. @status:impl/done
- @fact:prototype-cycle The
  prototype topology served them through vibevm's own MCP
  (`vibe mcp serve` + the `tcg_*` adapters), which put the whole vibevm
  product into every consumer's runtime path and closed an operational
  cycle over vibevm itself (the tool served its own development). @status:impl/done
- @fact:OWNER-RESOLUTION The
  owner's resolution (2026-07-07): agent-server delivery is a first-class
  package concern — a KIND, not a bolt-on surface — and vibe's job there
  is install-time wiring, never serving. @status:impl/done

## 2. Decisions {#decisions}

### 2.1 The `mcp` kind {#kind}

[p05] @fact:req-kind `req r1` @status:impl/done

[p06] @fact:MCP-KIND-DEF An **`mcp` package** is one whose primary deliverable is one or more
Model Context Protocol servers. @status:impl/done

- [p07] @fact:KIND-REGISTER `kind = "mcp"` joins the installable
  register (VIBEVM-SPEC §4.1); slots materialise under
  `vibedeps/<group>.<name>/<version>/` like every other kind (the identity slot — PROP-022 §2.1, owner ruling 2026-08-13; the path carried a kind prefix before that ruling). @status:impl/done
- @fact:TABLE-ONLY-IN-KIND The
  `[[mcp_server]]` table (§2.2) is **legal only in this kind** — the kind
  IS the taxonomy, enforced by `Manifest::validate`, not advisory. @status:impl/done
- @fact:KIND-PROMISES-SERVER An
  `mcp`-kind manifest that declares NO `[[mcp_server]]` is refused: the
  kind promises a server. @status:impl/done

### 2.2 The `[[mcp_server]]` declaration {#manifest}

[p08] @fact:req-manifest `req r1` @status:impl/done

[p09]
```toml
[[mcp_server]]
name = "rust-ai-native"           # agent-visible server name = the family (PROP-028 §2.4)
binary = "rust-ai-native-mcp"     # must match a [[binary]] in this manifest
description = "AI-Native Rust discipline + type oracle over MCP"
args = ["--path", "{project_root}"]
```

- [p10] @fact:SERVER-IS-BINARY The server IS a [PROP-025](../vibe-workspace/PROP-025-binary-delivery.xml)
  binary: delivery, consent, staleness, and slot residence come from that
  machinery wholesale — `binary` must resolve to a `[[binary]]` declared
  in the same manifest. @status:impl/done
- @fact:SERVER-NAME `name` is what an MCP host shows as the tool
  namespace; names are unique within the package. @status:impl/done
- @fact:ARGS-CLOSED-SET `args` may carry
  substitution tokens ONLY from the closed set `{project_root}` (the
  absolute, verbatim-free root of the consuming project, resolved at
  registration time); unknown `{…}` tokens are refused at validation. @status:impl/done

### 2.3 The exact-pin law {#exact-pin}

[p11] @fact:req-exact-pin `req r1` @status:impl/done

- [p12] @fact:VENDORING-WHY Cargo path-deps cannot cross package slots (PROP-024 §2.4), so an mcp
  package VENDORS the crates of the toolchain it serves. @status:impl/done
- @fact:SKEW-REOPENED Vendoring
  re-opens the version skew the in-slot prototype excluded by
  construction: a server built from engine copy X enriching against a
  consumer whose gates run engine copy Y. @status:impl/done
- @fact:EXACT-PIN-LAW The pin closes it: **every
  `[requires.packages]` entry of an `mcp`-kind package MUST be an exact
  `=X.Y.Z` requirement** — the resolver holds the served engines and the
  consumer's gates to ONE version set; no runtime handshake exists or is
  needed. @status:impl/done
- @fact:PIN-VALIDATION `Manifest::validate` refuses any other requirement shape
  (caret, bare, partial `=X.Y`, compound ranges). @status:impl/done
- @fact:PIN-SOURCES Git-source deps pin by
  rev inherently; path-source deps are local-dev surfaces outside this
  law. @status:impl/done
- @fact:PIN-LOCKSTEP The operational consequence is accepted and priced by the plan:
  the mcp package bumps in lockstep with the package it serves. @status:impl/done

### 2.4 Registration: `vibe mcp install` learns packages {#registration}

[p13] @fact:req-registration `req r1` @status:impl/done

[p14] @fact:REG-TODAY `vibe mcp install` today writes vibevm's own server into agent configs
(PROP-015). @status:impl/done

[p15] @fact:REG-PACKAGE-DISCOVERY It grows package discovery: every installed package of kind
`mcp` contributes its `[[mcp_server]]` entries, written into the target
agents' configs with @status:impl/done

- [p16] @fact:REG-COMMAND-PATH `command` = the absolute, **verbatim-free** path to the slot-resident
  built artifact (a real executable — no shim, no `cmd /c` wrapper
  class), `args` with the closed-set substitutions resolved; @status:impl/done
- @fact:REG-MANAGED-SIDECAR a **managed sidecar**: a top-level `"vibevm": { "managed": [...] }`
  object in the JSON config names the entries vibevm owns (never a key
  INSIDE a server entry — hosts validate entry shapes), so re-installs
  rewrite ONLY vibevm-managed entries and operator-owned servers are
  never touched — the `<vibevm>` block convention of the boot files,
  applied to agent configs. @status:impl/done
- @fact:REG-PROJECT-SCOPE Registration is PROJECT-scope only (the
  `{project_root}` substitution demands a project, and a project's
  servers belong in its committed config), and every project-scope
  agent config is JSON — so no TOML sidecar form exists; @status:impl/done
- @fact:REG-REFRESH lifecycle: `vibe mcp install` re-run refreshes paths after a slot
  move; @status:impl/done
- @fact:REG-STATUS `vibe mcp status` reports each declared server's artifact state
  (an unbuilt artifact registers fine and fails at agent launch — the
  recipe names `vibe bin build <name>`); @status:impl/done
- @fact:REG-UNINSTALL `vibe mcp uninstall` removes
  managed entries plus the emptied sidecar, and nothing else. @status:impl/done

### 2.5 Consent: registration is the same trust act as building {#consent}

[p17] @fact:req-consent `req r1` @status:impl/done

- [p18] @fact:CONSENT-TRUST-ACT Registering a server schedules package code execution at agent-session
  start; building its binary compiles package code. @status:impl/done
- @fact:CONSENT-GATE-INHERITED One trust model, two
  verbs: registration inherits PROP-025's consent gate verbatim —
  `org.vibevm` packages are allow-listed; any other origin requires the
  explicit `--assume-yes` (or is refused with the recipe naming that
  exact flag). @status:impl/done
- @fact:CONSENT-WRITE-SCOPE Registration writes touch ONLY the target agent's config
  files and only managed entries; server processes receive the project
  root as cwd and NO secrets from vibe. @status:impl/done

### 2.6 Serving is vibe-free {#vibe-free}

[p19] @fact:req-vibe-free `req r1` @status:impl/done

- [p20] @fact:VIBE-FREE-SERVING An mcp package's servers run without vibe: the artifact is launched by
  the agent host directly from the slot path, links its vendored engines,
  and speaks stdio MCP. @status:impl/done
- @fact:VIBE-ROLE `vibe` is required only to install, build, and
  register. @status:impl/done
- @fact:VIBE-FREE-ACCEPTANCE The acceptance form of this requirement: the server's live
  chain passes with `vibe` absent from `PATH` and no vibevm process
  running. @status:impl/done

### 2.7 Composition: an mcp package is a full package {#composition}

[p21] @fact:req-composition `req r1` @status:impl/done

[p22] @fact:COMPOSITION-LAW Every package-role feature applies to `mcp` packages exactly as to the
other kinds; no feature branches on `kind`, so each row inherits its
feature's own kind-agnostic suite (the mcp-kind e2e adds the
code-bearing + binaries + exact-pin composition end to end): @status:impl/done

[p23]
| Feature | Spec | Composition rule |
| --- | --- | --- |
| @fact:ROW-CODE-BEARING Code-bearing layout @status:impl/done | @fact:ROW-CODE-BEARING-SPEC PROP-024 @status:impl/done | @fact:ROW-CODE-BEARING-COMPOSITION-RULE the package IS code-bearing by definition; `spec/` for prompt content, crates at root @status:impl/done |
| @fact:ROW-BINARIES Binaries @status:impl/done | @fact:ROW-BINARIES-SPEC PROP-025 @status:impl/done | @fact:ROW-BINARIES-COMPOSITION-RULE `[[mcp_server]].binary` references them; `vibe bin list/build/exec` see them like any other @status:impl/done |
| @fact:ROW-SKILLS Skills @status:impl/done | @fact:ROW-SKILLS-SPEC PROP-015 §2.8, PROP-018 §2.4 @status:impl/done | @fact:ROW-SKILLS-COMPOSITION-RULE `[[skill]]` legal; a server may ship its teaching skill @status:impl/done |
| @fact:ROW-BOOT-SNIPPET Boot snippet @status:impl/done | @fact:ROW-BOOT-SNIPPET-SPEC PROP-009 @status:impl/done | @fact:ROW-BOOT-SNIPPET-COMPOSITION-RULE legal but not required; agents learn servers via registration, not boot text @status:impl/done |
| @fact:ROW-HOOKS Hooks @status:impl/done | @fact:ROW-HOOKS-SPEC PROP-020 @status:impl/done | @fact:ROW-HOOKS-COMPOSITION-RULE pre/post-install hooks run in the slot as usual @status:impl/done |
| @fact:ROW-MATERIALIZATION Materialization modes @status:impl/done | @fact:ROW-MATERIALIZATION-SPEC PROP-022 @status:impl/done | @fact:ROW-MATERIALIZATION-COMPOSITION-RULE snapshot/in-place per the standard rules @status:impl/done |
| @fact:ROW-BRIDGES Bridges / submodules @status:impl/done | @fact:ROW-BRIDGES-SPEC PROP-023 / PROP-021 @status:impl/done | @fact:ROW-BRIDGES-COMPOSITION-RULE no special-casing @status:impl/done |
| @fact:ROW-PUBLISH Publish @status:impl/done | @fact:ROW-PUBLISH-SPEC PROP-002 §2.10 @status:impl/done | @fact:ROW-PUBLISH-COMPOSITION-RULE standard registry publish; the exact-pin law travels in the manifest @status:impl/done |
| @fact:ROW-MUTABILITY In-workspace mutability @status:impl/done | @fact:ROW-MUTABILITY-SPEC PROP-011 §2.6 @status:impl/done | @fact:ROW-MUTABILITY-COMPOSITION-RULE dev-loop re-materialisation applies @status:impl/done |

## 3. Rejected alternatives {#rejected}

- [p24] @fact:REJ-ANY-KIND **`[[mcp_server]]` as an any-kind surface** (the plan's original
  draft): rejected by the owner — the taxonomy should say what a
  package IS; embedded servers would blur the register and hide the
  vendoring/pinning obligations §2.3 makes explicit. @status:spec/done
- @fact:REJ-CROSS-SLOT **Cross-slot path-deps or manifest rewriting** instead of vendoring:
  PROP-025 v2 territory, specified-only; the reproducible-hash model
  (PROP-024 §2.2) forbids post-materialise rewriting today. @status:spec/done
- @fact:REJ-HANDSHAKE **A runtime version handshake** instead of the exact pin: weaker (it
  detects skew instead of preventing it) and needs a wire surface;
  the resolver already enforces equality for free. @status:spec/done
- @fact:REJ-VIBE-LAUNCHER **vibe as the server launcher** (`vibe mcp exec <name>` in agent
  configs): would keep vibe in the runtime path — the exact property
  this PROP removes. @status:spec/done

## 4. Open questions {#open}

1. [p25] @fact:OPEN-MULTI-SERVER Multi-server packages (legal today) — does `vibe mcp install` offer
   per-server opt-out? v1: all-or-nothing per package. @status:spec/work
2. @fact:OPEN-APP-KIND The `app` kind (anticipated, VIBEVM-SPEC §4.1) — whether it reuses
   §2.4's managed-entry machinery for desktop-integration surfaces. @status:spec/work
3. @fact:OPEN-STABLE-PATHS Stable artifact paths (PROP-025 v2 shims) would make managed entries
   survive version bumps without a re-install; deferred with it. @status:spec/work

