Skip to content

Define VMCP core interface and Config contract#5450

Merged
tgrunnagle merged 2 commits into
mainfrom
vmcp-core-p1-1_issue_5434
Jun 3, 2026
Merged

Define VMCP core interface and Config contract#5450
tgrunnagle merged 2 commits into
mainfrom
vmcp-core-p1-1_issue_5434

Conversation

@tgrunnagle
Copy link
Copy Markdown
Contributor

Summary

RFC THV-0076 extracts a small, identity-parameterized domain object from today's vMCP transport god-object (server.New), so that aggregation, routing, and composite workflows live behind a single explicit contract instead of being entangled with HTTP/session concerns. Before any of that machinery can be built, the domain boundary itself has to exist and be agreed on — that is what this PR delivers.

This is the contract-only first PR of Phase 1. It declares:

  • The identity-parameterized VMCP domain interface (ListTools/CallTool, ListResources/ReadResource, ListPrompts/GetPrompt, the Lookup* resolution methods, and Close), with its full behavioral contract encoded in the doc comment.
  • The core Config struct of collaborators as typed field declarations.

There is no implementation: New(cfg) (VMCP, error) and the concrete coreVMCP bodies land in #5437. The deliverable here is the durable contract that #5437 implements and that Serve and the decorators downstream consume.

Closes #5434

Type of change

  • Refactoring (no behavior change)

Test plan

  • Unit tests (task test)
  • Linting (task lint-fix)

This is a contract-only change, so compile-time conformance is the guarantee per the issue's testing strategy — there is no behavior to exercise until New is implemented (#5437). Verification performed:

  • task build green — proves the package compiles with no import cycle.
  • task test green (exit 0, no races) — full suite unchanged; server.New is untouched.
  • The new package lints clean. The one task lint finding is a pre-existing gosec G115 in cmd/thv/app/upgrade.go, unrelated to this PR and not in this diff.

Changes

File Change
pkg/vmcp/core/core.go New file (156 lines): the VMCP interface with its full contract doc comment, and the typed Config collaborator struct.

Does this introduce a user-facing change?

No.

Special notes for reviewers

Package location differs from the issue text (user-approved). The issue specified placing the interface and Config in the root pkg/vmcp package (pkg/vmcp/vmcp.go). However, Config references the aggregator, router, composer, health, and authz collaborators, and all of those transitively import the root pkg/vmcp package — verified empirically with go list -deps. A root-package Config would therefore create an import cycle. After confirming this, the interface and Config were placed in a new pkg/vmcp/core subpackage instead. This also resolves the same latent cycle that #5437's New/coreVMCP would otherwise hit. The issue text and #5437/#5430 likely need a follow-up note to reflect this package location.

Two other user-approved deviations from the issue's literal spec:

  • The Config.Elicitation ElicitationRequester field is omitted here because its domain type is owned by P1.3 Domain-typed ElicitationRequester (bounded rewrite) #5436 and is out of scope for this PR. A doc comment marks where it will be added.
  • meta is on CallTool only, not GetPrompt. This matches the authoritative interface signature, the Caller prior art, and vmcp.BackendClient.GetPrompt (which has no meta parameter — there is no client _meta to forward on the prompts/get path). AC#2's prose mentioning GetPrompt is a wording discrepancy in the issue.

Context: Parent story #5430; this PR blocks #5437.

Establish the contract-only first step of the vMCP New/Serve split: the
identity-parameterized VMCP domain interface and the core Config struct
of collaborators. This is the domain boundary that New(cfg) -> VMCP and
the decorators will consume; no implementation yet.

Implements issue #5434:
- Add pkg/vmcp/core with the VMCP interface (ListTools/CallTool/List+
  Read/List+GetPrompt/Lookup{Tool,Resource,Prompt}/Close), identity an
  explicit *auth.Identity on every data method, never read from context.
- Encode the full behavioral contract in the interface doc comment
  (anonymous nil identity, decorators subtract-only, read-only args/meta,
  nil ResourceReadResult.Meta).
- Declare Config with typed collaborator fields; no construction logic.
- No mcp-go types cross the boundary (anti-pattern #5).

The core lives in pkg/vmcp/core rather than root pkg/vmcp because Config
references aggregator/router/composer/health/authz, all of which import
pkg/vmcp; a root-package Config would create an import cycle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the size/S Small PR: 100-299 lines changed label Jun 3, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 68.85%. Comparing base (a785995) to head (b9638f9).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5450      +/-   ##
==========================================
- Coverage   68.85%   68.85%   -0.01%     
==========================================
  Files         634      634              
  Lines       64437    64437              
==========================================
- Hits        44371    44370       -1     
- Misses      16789    16790       +1     
  Partials     3277     3277              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor Author

@tgrunnagle tgrunnagle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review summary

Clean, well-scoped contract-only PR: a single 156-line new file (pkg/vmcp/core/core.go) declaring the identity-parameterized VMCP interface and a typed Config collaborator struct, with no implementation. All ten acceptance-criteria methods are present, identity is an explicit *auth.Identity on every data method (anti-pattern #1), and zero mcp-go types cross the boundary (anti-pattern #5). The interface is a faithful non-session-scoped generalization of the prior-art Caller interface.

Verified against the codebase:

  • The package-location deviation (pkg/vmcp/core instead of the issue's root pkg/vmcp) is justifiedaggregator, router, composer, and health all import root pkg/vmcp, so a root-package Config referencing them would create an import cycle. Confirmed empirically.
  • All referenced types resolve (vmcp.Tool/Resource/Prompt, the result wrappers, BackendRegistry, BackendClient, and every Config collaborator type).
  • meta-on-CallTool-only (not GetPrompt) matches both the Caller prior art and BackendClient.GetPrompt (which has no meta param). The approved deviation from AC#2's wording is sound.
  • Omitting the Elicitation field is correct — no domain ElicitationRequester type exists yet, and the field is purely additive on a struct with zero consumers.

Three minor doc nits (all non-blocking, see inline comments).

# Severity Finding Raised by
1 LOW Doc comment hard-codes types.go:556-561 line numbers that will rot 3 reviewers
2 LOW godoc link [pkg/vmcp/session/types.ShouldAllowAnonymous] won't render (package not imported) 1 reviewer

Doc reconciliation (no code change): Issue #5434's acceptance-criteria checkboxes reference pkg/vmcp/vmcp.go; since the canonical location is now core.VMCP, the issue and downstream PRs #5437/#5439 should be annotated so the core package is recognized as the single front door.

Notes for downstream PRs (contract claims this PR cannot enforce — flag during implementation review):

  • #5437 must actually copy args/meta before mutating (the read-only guarantee is doc-only here), and List*/Lookup* must share a single admission filter so a denied capability is invisible to both paths.
  • #5438's admission decorator constructor should take only an inner VMCP (no backend-reaching collaborators) to keep the "decorators may only subtract reachability" invariant structurally true.
  • Confirm the composer collaborator is constructed internally by New from WorkflowDefs rather than injected; if injected, add the field now to avoid a later Config shape change.

Recommendation: APPROVE — no blocking issues; the inline items are optional polish.

🤖 Generated with Claude Code

Comment thread pkg/vmcp/core/core.go
Comment thread pkg/vmcp/core/core.go
Addresses #5450 review comments:
- LOW pkg/vmcp/core/core.go (3351574912): replace the unresolvable
  [pkg/vmcp/session/types.ShouldAllowAnonymous] godoc link (package not
  imported) with plain prose so it no longer renders as literal brackets.
- LOW pkg/vmcp/core/core.go (3351574935): drop the rot-prone types.go:556-561
  line citation in favor of the self-maintaining [vmcp.ResourceReadResult].Meta
  doc link.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tgrunnagle tgrunnagle marked this pull request as ready for review June 3, 2026 20:18
@github-actions github-actions Bot added size/S Small PR: 100-299 lines changed and removed size/S Small PR: 100-299 lines changed labels Jun 3, 2026
@tgrunnagle tgrunnagle merged commit 255686a into main Jun 3, 2026
45 checks passed
@tgrunnagle tgrunnagle deleted the vmcp-core-p1-1_issue_5434 branch June 3, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/S Small PR: 100-299 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P1.1 Define VMCP interface + core Config

2 participants