-
Notifications
You must be signed in to change notification settings - Fork 135
Add Virtual MCP Server routing interfaces and domain model #2333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR establishes the foundational interfaces and domain model for the Virtual MCP Server, enabling parallel development of the vMCP implementation. It provides a platform-agnostic architecture following Domain-Driven Design principles that works seamlessly for both CLI (Docker/Podman) and Kubernetes deployments.
Key Changes:
- Defines comprehensive domain types and error handling for Virtual MCP Server
- Establishes routing, aggregation, authentication, composition, caching, and configuration interfaces
- Creates a clear bounded context architecture with proper separation of concerns
Reviewed Changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pkg/vmcp/types.go | Core domain types including BackendTarget, Tool, Resource, Prompt, and routing table structures |
| pkg/vmcp/errors.go | Common domain errors following DDD principles for use across vmcp subpackages |
| pkg/vmcp/doc.go | Comprehensive package documentation with architecture overview and usage examples |
| pkg/vmcp/router/router.go | Request routing interfaces for directing MCP protocol requests to backend workloads |
| pkg/vmcp/aggregator/aggregator.go | Capability aggregation interfaces for discovering and merging backend capabilities |
| pkg/vmcp/auth/auth.go | Authentication interfaces for both incoming (client→vMCP) and outgoing (vMCP→backends) boundaries |
| pkg/vmcp/composer/composer.go | Workflow engine interfaces for executing multi-step composite tools with elicitation support |
| pkg/vmcp/config/config.go | Platform-agnostic configuration model compatible with both CLI YAML and Kubernetes CRDs |
| pkg/vmcp/cache/cache.go | Token caching interfaces with pluggable backend support (memory, Redis) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2333 +/- ##
==========================================
- Coverage 54.28% 54.26% -0.02%
==========================================
Files 240 241 +1
Lines 23594 23598 +4
==========================================
- Hits 12808 12806 -2
- Misses 9577 9582 +5
- Partials 1209 1210 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
cdebf63 to
6167d8a
Compare
|
@claude please review this. |
|
Claude finished @JAORMX's task —— View job Code Review CompleteI've completed a thorough review of the Virtual MCP Server routing interfaces and domain model PR. Overall, this is an excellent foundation for the vMCP implementation with strong architectural decisions and well-designed interfaces. Below is my detailed feedback. SummaryThis PR establishes solid foundational interfaces following Domain-Driven Design principles. The code demonstrates strong architectural thinking with clear separation of concerns, platform independence, and extensibility. There are a few areas for improvement around documentation clarity, error handling consistency, and interface design details. Verdict: Approve with minor suggestions ✅ Strengths1. Excellent DDD Architecture
2. Platform Independence
3. Interface Segregation
4. Comprehensive Documentation
Issues & Suggestions1. Critical: Documentation Clarification (pkg/vmcp/aggregator/aggregator.go:161)Issue: The comment on
Current Code: // ToolFilter filters tools from a backend based on configuration.
// This reuses ToolHive's existing mcp.WithToolsFilter() middleware.
type ToolFilter interface {
// FilterTools returns only the tools that should be included.
FilterTools(ctx context.Context, tools []vmcp.Tool) ([]vmcp.Tool, error)
}Issue Analysis: After reviewing
Recommendation: This comment is misleading. The interfaces serve different purposes:
Suggested Fix (pkg/vmcp/aggregator/aggregator.go:160-165): // ToolFilter filters tools from a backend based on configuration.
// Implementations apply filtering logic similar to ToolHive's existing
// mcp.WithToolsFilter() middleware, but operate on in-memory tool lists
// during aggregation rather than HTTP request/response streams.
type ToolFilter interface {
// FilterTools returns only the tools that should be included based on
// the configured filter list. Returns a filtered copy of the input.
FilterTools(ctx context.Context, tools []vmcp.Tool) ([]vmcp.Tool, error)
}Same Issue Applies to (pkg/vmcp/aggregator/aggregator.go:167-172): // ToolOverride applies renames and description updates to tools.
// Implementations apply override logic similar to ToolHive's existing
// mcp.WithToolsOverride() middleware, but operate on in-memory tool lists
// during aggregation rather than HTTP request/response streams.
type ToolOverride interface {
// ApplyOverrides modifies tool names and descriptions according to
// the configured overrides. Modifies tools in place or returns a new slice.
ApplyOverrides(ctx context.Context, tools []vmcp.Tool) ([]vmcp.Tool, error)
}This addresses the Copilot review comment and clarifies the relationship between these interfaces. 2. Error Handling Consistency (pkg/vmcp/router/router.go:62-77)Issue: Router package defines its own specific errors ( Current Code: // pkg/vmcp/router/router.go
var (
ErrToolNotFound = fmt.Errorf("tool not found")
ErrResourceNotFound = fmt.Errorf("resource not found")
ErrPromptNotFound = fmt.Errorf("prompt not found")
// ...
)Recommendation: Consider whether these should wrap var (
// ErrToolNotFound indicates the requested tool doesn't exist.
ErrToolNotFound = fmt.Errorf("%w: tool", vmcp.ErrNotFound)
// ErrResourceNotFound indicates the requested resource doesn't exist.
ErrResourceNotFound = fmt.Errorf("%w: resource", vmcp.ErrNotFound)
// ErrPromptNotFound indicates the requested prompt doesn't exist.
ErrPromptNotFound = fmt.Errorf("%w: prompt", vmcp.ErrNotFound)
)Rationale: This allows callers to use Same pattern could apply to: 3. Interface Design: HealthChecker Context (pkg/vmcp/types.go:185-189)Issue:
Current Code: type HealthChecker interface {
// CheckHealth checks if a backend is healthy and responding.
// Returns the current health status and any error encountered.
CheckHealth(ctx context.Context, target *BackendTarget) (BackendHealthStatus, error)
}Recommendation: Clarify the contract in documentation: type HealthChecker interface {
// CheckHealth checks if a backend is healthy and responding.
// Returns the current health status and any error encountered.
//
// Contract:
// - If error is non-nil, the status indicates the failure reason
// (typically BackendUnhealthy or BackendUnknown)
// - If error is nil, the status reflects the actual backend health
// - Never returns (BackendHealthy, non-nil error)
CheckHealth(ctx context.Context, target *BackendTarget) (BackendHealthStatus, error)
}4. Type Safety: BackendTarget.AuthMetadata (pkg/vmcp/types.go:33)Issue: Current Code: type BackendTarget struct {
// ...
AuthMetadata map[string]any
}Recommendation: This is acceptable for v1 given the extensible strategy pattern, but consider documenting expected shapes: // AuthMetadata contains strategy-specific authentication metadata.
// This is opaque to the router and interpreted by the authenticator.
//
// Expected structure by strategy:
// - "token_exchange": {"token_endpoint": string, "audience": string, ...}
// - "client_credentials": {"client_id": string, "client_secret": string, ...}
// - "header_injection": {"headers": map[string]string}
//
// See pkg/vmcp/auth package documentation for complete schema per strategy.
AuthMetadata map[string]anyAlternative: Define strategy-specific config types in 5. Minor: Missing Context on CapabilityList (pkg/vmcp/types.go:213-229)Issue: Suggestion: Add brief documentation: type CapabilityList struct {
// Tools available on this backend.
Tools []Tool
// Resources available on this backend.
Resources []Resource
// Prompts available on this backend.
Prompts []Prompt
// SupportsLogging indicates if the backend supports MCP logging protocol.
// When true, the backend can receive logging/setLevel requests.
SupportsLogging bool
// SupportsSampling indicates if the backend supports MCP sampling protocol.
// When true, the backend can receive sampling/createMessage requests.
SupportsSampling bool
}6. Interface Completeness: TokenCache (pkg/vmcp/cache/cache.go:18-34)Issue: The Observation: type TokenCache interface {
Get(ctx context.Context, key string) (*CachedToken, error)
Set(ctx context.Context, key string, token *CachedToken) error
Delete(ctx context.Context, key string) error
Clear(ctx context.Context) error
Close() error
}
// StatsProvider is defined separately
type StatsProvider interface {
Stats(ctx context.Context) (*Stats, error)
}Recommendation: This is intentional separation (not all caches need stats), but consider documenting: // TokenCache provides caching for exchanged authentication tokens.
// This reduces the number of token exchanges and improves performance.
//
// Cache key format: {backend}:{hash(subject_token)}:{audience}
// This ensures proper token isolation per (user, backend) pair.
//
// Implementations may optionally implement StatsProvider for observability.
type TokenCache interface {
// ... methods
}7. Workflow Engine: Template Expansion Security (pkg/vmcp/composer/composer.go:308-315)Issue: Concern: Template injection vulnerabilities if user-controlled data flows into templates without proper escaping. Recommendation: Add security note: // TemplateExpander handles template expansion for workflow arguments.
//
// Security: Implementations must ensure proper escaping/sanitization of
// user-provided data to prevent template injection attacks. Consider using
// html/template for HTML contexts or implementing custom escape functions.
type TemplateExpander interface {
// Expand evaluates templates in the given data using the workflow context.
// Template syntax follows Go text/template with access to workflow context.
Expand(ctx context.Context, data map[string]any, workflowCtx *WorkflowContext) (map[string]any, error)
// EvaluateCondition evaluates a condition template to a boolean.
EvaluateCondition(ctx context.Context, condition string, workflowCtx *WorkflowContext) (bool, error)
}8. Config Validation: Missing Required Fields (pkg/vmcp/config/config.go)Issue: The Recommendation: Add struct tags or documentation: type Config struct {
// Name is the virtual MCP server name (required).
Name string
// GroupRef references the ToolHive group containing backend workloads (required).
GroupRef string
// IncomingAuth configures how clients authenticate to the virtual MCP server.
// If nil, defaults to anonymous authentication.
IncomingAuth *IncomingAuthConfig
// OutgoingAuth configures how the virtual MCP server authenticates to backends.
// If nil, defaults to pass-through authentication.
OutgoingAuth *OutgoingAuthConfig
// ... rest with similar documentation
}9. Consistency: BackendTarget vs Backend (pkg/vmcp/types.go:8-88)Observation: Both Analysis: After review, this appears intentional:
Recommendation: Document the distinction clearly: // Backend represents a discovered backend MCP server workload.
// This is the output of the discovery phase and input to capability querying.
// After aggregation, backends are converted to BackendTargets for routing.
type Backend struct {
// ... fields
}
// BackendTarget identifies a specific backend workload and provides
// the information needed to forward requests to it.
// This is the output of aggregation and input to the routing phase.
type BackendTarget struct {
// ... fields
}10. Minor: Code Coverage (Codecov Report)Observation: Codecov reports 0% coverage on 4 lines in Analysis: These are the helper methods Recommendation: Tests will be added in implementation PRs. Consider adding basic tests for the helper methods to document expected behavior: // Test in future implementation PR
func TestCachedToken_IsExpired(t *testing.T) {
token := &CachedToken{ExpiresAt: time.Now().Add(-1 * time.Hour)}
assert.True(t, token.IsExpired())
}Consistency with ToolHive Patterns✅ Follows ToolHive Conventions
✅ Platform Abstraction
✅ Integration Points
Architecture Review Checklist
Final RecommendationsBefore Merge
Future PRs
SummaryThis is an excellent foundation for the Virtual MCP Server implementation. The interfaces are well-designed, the architecture follows solid DDD principles, and the code demonstrates thoughtful consideration of extensibility and platform independence. The main issue to address before merge is clarifying the relationship between the new Great work on this foundational piece! 🎉 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a minor comment
Implement foundational domain interfaces for Virtual MCP Server (vMCP) following Domain-Driven Design principles. This enables parallel implementation of vMCP features across multiple teams. Package structure: - pkg/vmcp/types.go: Shared domain types (BackendTarget, Tool, etc.) - pkg/vmcp/errors.go: Common domain errors - pkg/vmcp/router/: Request routing interfaces - pkg/vmcp/aggregator/: Capability aggregation interfaces - pkg/vmcp/auth/: Authentication interfaces (incoming & outgoing) - pkg/vmcp/composer/: Workflow engine interfaces - pkg/vmcp/config/: Platform-agnostic configuration model - pkg/vmcp/cache/: Token caching interfaces Key design decisions: - Shared types in root package avoid circular dependencies - Extensible authentication via Strategy interface - BackendDiscoverer abstraction enables CLI and K8s implementations - RoutingTable maps capabilities to backends (composite tools excluded) - Configuration model matches proposal YAML structure Related: #2106 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Changes: - Use ConflictResolutionStrategy enum instead of string in ResolvedTool - Remove specific auth strategy examples from OutgoingAuthenticator docs until design decisions are finalized Addresses feedback from: - yrobla: Use typed enum for conflict resolution strategy - jhrozek: Defer auth strategy details until design is complete 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
6167d8a to
fe78c46
Compare
Summary
Implements the routing interfaces and domain model for Virtual MCP Server as defined in the proposal. This PR provides the foundational interfaces needed to enable parallel development of the vMCP implementation.
What does this PR do?
Adds comprehensive interfaces and domain types for the Virtual MCP Server routing layer:
Key Design Decisions
Architecture
Following Domain-Driven Design principles with bounded contexts:
Benefits
Testing
This PR contains interface definitions only. Implementations and tests will follow in subsequent PRs as outlined in the implementation plan.
Related Documentation
🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com