Skip to content

Preserve tool annotations and output schema through vmcp#4090

Merged
JAORMX merged 1 commit intomainfrom
tool-annotations-propagation
Mar 11, 2026
Merged

Preserve tool annotations and output schema through vmcp#4090
JAORMX merged 1 commit intomainfrom
tool-annotations-propagation

Conversation

@JAORMX
Copy link
Copy Markdown
Collaborator

@JAORMX JAORMX commented Mar 11, 2026

Summary

  • MCP tool annotations (readOnlyHint, destructiveHint, idempotentHint, openWorldHint, Title) were silently dropped during vmcp aggregation, blocking downstream authorization profiles. This adds the ToolAnnotations vmcp domain type and propagates it through the full pipeline.
  • OutputSchema existed on vmcp.Tool but was never populated from backend MCP servers. This populates it using the same JSON round-trip pattern as InputSchema.
  • Both fields now flow end-to-end: backend query → tool adapter → all three conflict resolvers (prefix/priority/manual) → merge → SDK adapter output.

Type of change

  • New feature

Test plan

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

22 new test cases across 4 test files:

  • pkg/vmcp/conversion/content_test.go — conversion functions (15 cases including round-trip)
  • pkg/vmcp/aggregator/tool_adapter_annotations_test.go — preservation through overrides (3 cases)
  • pkg/vmcp/server/adapter/capability_adapter_annotations_test.go — SDK output (4 cases)

Changes

File Change
pkg/vmcp/types.go Add ToolAnnotations struct and Annotations field to Tool
pkg/vmcp/conversion/content.go Add ConvertToolAnnotations, ConvertToolOutputSchema, ToMCPToolAnnotations
pkg/vmcp/client/client.go Populate Annotations + OutputSchema from backend
pkg/vmcp/session/internal/backend/mcp_session.go Same for session-based client path
pkg/vmcp/aggregator/aggregator.go Add fields to ResolvedTool
pkg/vmcp/aggregator/prefix_resolver.go Propagate through prefix resolver
pkg/vmcp/aggregator/priority_resolver.go Propagate through all 3 code paths
pkg/vmcp/aggregator/manual_resolver.go Propagate through manual resolver
pkg/vmcp/aggregator/default_aggregator.go Propagate through fallback + merge
pkg/vmcp/aggregator/tool_adapter.go Preserve through filtering/renaming
pkg/vmcp/server/adapter/capability_adapter.go Emit Annotations and RawOutputSchema to SDK types

Does this introduce a user-facing change?

No direct user-facing change. Backend MCP tool annotations and output schemas are now preserved through vmcp aggregation instead of being silently dropped. This enables downstream consumers (like authorization profiles) to use these fields.

Special notes for reviewers

  • ACL pattern preserved: vmcp.ToolAnnotations is a vmcp-owned type (not mcp.ToolAnnotation directly) to maintain the Anti-Corruption Layer — mcp-go is only used at ingestion and SDK adapter boundaries.
  • PR 2 follow-up: Icons, Execution, Resource Annotations, and Prompt Icons are deferred to a follow-up PR per the split strategy.
  • ConvertToolOutputSchema nil check: Uses schema.Type == "" rather than byte-length check because a zero-valued ToolOutputSchema marshals to {"type":"","properties":{},"required":[]} (non-empty JSON but semantically empty).

Generated with Claude Code

MCP tool annotations (readOnlyHint, destructiveHint, idempotentHint,
openWorldHint) were silently dropped during vmcp aggregation, and
OutputSchema was never populated from backends. This blocks downstream
authorization profiles that need annotation data.

Add ToolAnnotations type to vmcp domain model and propagate both
Annotations and OutputSchema through the full pipeline: backend
query → tool adapter → conflict resolvers → merge → SDK adapter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions github-actions bot added the size/L Large PR: 600-999 lines changed label Mar 11, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 84.94624% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.52%. Comparing base (c598eda) to head (230b788).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
pkg/vmcp/server/adapter/capability_adapter.go 69.23% 4 Missing and 4 partials ⚠️
pkg/vmcp/conversion/content.go 80.64% 3 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4090      +/-   ##
==========================================
+ Coverage   68.50%   68.52%   +0.02%     
==========================================
  Files         447      447              
  Lines       45663    45746      +83     
==========================================
+ Hits        31281    31349      +68     
- Misses      11964    11973       +9     
- Partials     2418     2424       +6     

☔ 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.

@JAORMX JAORMX merged commit 5b4b724 into main Mar 11, 2026
46 of 48 checks passed
@JAORMX JAORMX deleted the tool-annotations-propagation branch March 11, 2026 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/L Large PR: 600-999 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants