Skip to content

Phase 1: VMCP interface, core constructor, admission + elicitation seams #5430

Description

@tgrunnagle

Description

Deliver the foundation of the vMCP domain/transport split: a public,
identity-parameterized VMCP domain interface and core Config in the root
pkg/vmcp package, a New(cfg) -> VMCP constructor that relocates (does not
rewrite) server.New's domain wiring, and the two deliberate bounded rewrites
— the Cedar-backed admission seam (R1) and the domain-typed ElicitationRequester
(R4). This story maps to RFC Phase 1 and moves the domain seam (aggregation,
routing, admission, elicitation) out from behind the transport god-object — while
server.New stays completely untouched.

Context

See RFC THV-0076: vMCP Core Interface
for full design details. Part of the vMCP interface refactor (epic #5419).

This is the first story and the entry point for the whole refactor: it
establishes the VMCP contract that Serve (Phase 2) and the server.New
wrapper reduction (Phase 3) build on. Per architecture.md ("PR-Sized
Decomposition Guidance → Phase 1"), the new core is constructed by relocating the
collaborator wiring that lives in server.New today — aggregator, router, backend
registry, backend client, composer, the per-session
sessionComposerFactory/NewSessionRouter pattern, and workflow validation —
plus an injected health.StatusProvider so the core runs filterHealthyBackends
internally (core filters, Serve caches). Identity is an explicit *auth.Identity
on every method and is never read from context (anti-pattern #1); no mcp-go types
cross the VMCP boundary (anti-pattern #5).

Crucially, this story carries the two highest-risk items in the entire epic
the two bounded rewrites that re-platform existing behavior rather than merely
relocating it:

  • Admission seam (P1.5 Core admission seam (bounded rewrite) #5438, R1) — HIGHEST regression risk. Moves the
    authorization decision from the HTTP AuthzMiddleware into a core Admission
    seam that wraps the existing Cedar authorizers.Authorizer (no new policy
    model). It must produce the same decision in List* (filter) and
    Call/Read/Get (deny), re-inject the explicit identity into ctx for Cedar's
    AuthorizeWithJWTClaims, source Tool.Annotations directly from the core
    (replacing AnnotationEnrichmentMiddleware), and be a no-op/allow-all when
    authz is unconfigured.
  • Domain-typed ElicitationRequester (P1.3 Domain-typed ElicitationRequester (bounded rewrite) #5436, R4) — high risk. Replaces
    composer.SDKElicitationRequester (which leaks mcp.ElicitationRequest/Result)
    with a domain-typed requester, confining mcp-go translation to
    sdk_elicitation_adapter.go. A one-to-one type mirror only — no elicitation
    semantics are redesigned.

Both rewrites get dedicated parity/security tests (see their child tasks).

RFC Phase(s): Phase 1
Dependencies: None (first story)

Scope

In scope

Out of scope

Child Tasks

PR-sized tasks under this story (each ≤ 400 LOC, ≤ 10 files changed excluding
tests/docs/generated, one logical change):

Acceptance Criteria

  • All child tasks complete and merged
  • server.New signature and observable behavior unchanged
  • The new core is NOT yet wired into server.New in Phase 1 — the core
    exists as additive public API (VMCP/New) but the server.New body is
    untouched; the live authz HTTP middleware still runs in the shipped path
  • VMCP interface and New(cfg) -> VMCP exist as additive public API in the
    root pkg/vmcp package, with identity as an explicit *auth.Identity and no
    mcp-go types crossing the boundary
  • Tool/Resource/Prompt.BackendID is pinned non-empty on every advertised
    capability across all conflict strategies (P1.2 Pin BackendID through the advertising filter (tests) #5435)
  • Bounded rewrite R4 (elicitation): the domain ElicitationRequester carries
    no mcp-go types and its dedicated parity tests pass (accept/decline/cancel/
    timeout; security validation still fires)
  • Bounded rewrite R1 (admission): list-omit and call-deny enforce the same
    Cedar decision, no-op/allow-all when unconfigured, passThroughTools exempt,
    identity never logged — dedicated R1 security parity tests pass
  • Existing thv vmcp serve E2E suite passes unchanged

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactorvmcpVirtual MCP Server related issues

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions