Skip to content

MCP Server Hub #80

@sdelamo

Description

@sdelamo

Feature description

Description

Add support for configuring a Micronaut MCP application as a "hub" that aggregates primitives (tools, prompts, resources) from multiple remote MCP servers and exposes them through a single unified MCP server interface.

Motivation

Currently, when working with multiple MCP servers, clients need to connect to each server individually. This proposal would allow a Micronaut application to act as a central hub that:

  • Connects to multiple remote MCP servers as a client
  • Aggregates all primitives (tools, prompts, resources) from those servers
  • Exposes them through a single unified MCP server interface
  • Provides a single point of entry for MCP clients

This simplifies the client-side architecture and enables centralized management of multiple MCP servers.

Proposed Solution

Configuration

Enable hub mode through configuration:

micronaut:
  mcp:
    server:
      hub: true  # Enable hub mode
      transport: HTTP
      info:
        name: 'mcp-hub'
        version: '1.0.0'
    client:
      http:
        server-a:
          url: 'https://servera.com/mcp'
        server-b:
          url: 'https://serverb.com/modelcontextprotocol'
        server-c:
          url: 'https://serverc.com/mcp'

Behavior

When micronaut.mcp.server.hub=true:

  1. The application will initialize MCP clients for all configured remote servers
  2. During startup, fetch all primitives from each remote server:
    • Tools (via tools/list and handle tools/call requests)
    • Prompts (via prompts/list and handle prompts/get requests)
    • Resources (via resources/list and handle resources/read requests)
    • Resource templates (from resources/templates)
  3. Expose all aggregated primitives through the hub's MCP server interface
  4. Route incoming requests to the appropriate remote server

Name Collision Handling

When multiple servers expose primitives with the same name, we need a strategy. Proposed options (to be discussed):

Option 1: Prefix with server name

  • Tool: server-a:fenEvaluation, server-b:fenEvaluation
  • Resource: server-a://resource-uri, server-b://resource-uri
  • Prompt: server-a:chess-statistics, server-b:chess-statistics

Option 2: Configuration-based priority

micronaut:
  mcp:
    server:
      hub:
        enabled: true
        conflict-resolution: FIRST_WINS  # or LAST_WINS, PREFIX, ERROR

Option 3: Metadata enrichment

  • Keep original names but add server information in descriptions/metadata
  • Allow clients to see which server provides each primitive

Security Configuration

Document how to configure security for remote MCP clients using BeanCreatedEventListener:

@Singleton
class McpClientSecurityConfiguration implements BeanCreatedEventListener<McpClient> {
    
    @Override
    public McpClient onCreated(BeanCreatedEvent<McpClient> event) {
        McpClient client = event.getBean();
         // Configure authentication for server-a
         // e.g., add headers, tokens, etc.
        
        return client;
    }
}

Request Routing

The hub should:

  • Maintain a mapping of primitives to their source servers
  • Forward tools/call, prompts/get, resources/read requests to the appropriate remote server
  • Handle errors gracefully (e.g., when a remote server is unavailable)

Server Capabilities

The hub's ServerCapabilities should reflect the aggregated capabilities of all connected servers:

  • Tools: Union of all remote tools
  • Prompts: Union of all remote prompts (considering listChanged settings)
  • Resources: Union of all remote resources (considering subscribe and listChanged settings)

Implementation Considerations

  1. Startup Performance: Fetching primitives from multiple servers during startup could be slow

    • Consider async initialization
    • Provide configuration for timeout settings
    • Support lazy loading of primitives
  2. Dynamic Updates: How to handle when remote servers add/remove primitives

    • Support for MCP notification protocol (notifications/tools/list_changed, etc.)
    • Periodic polling as fallback
    • Configuration for refresh intervals
  3. Error Handling: What happens when a remote server is unavailable

    • Continue serving primitives from available servers
    • Cache last-known primitives
    • Report degraded status through health endpoints
  4. Transport Compatibility:

    • Initial implementation should support HTTP transport
    • Future: Consider STDIO transport support (though less common for remote servers)
  5. Testing: Provide utilities for testing hub configurations

    • Mock remote MCP servers
    • Integration tests with embedded servers

Documentation Updates

The documentation should include:

  1. New section on "MCP Hub" functionality
  2. Configuration examples for hub mode
  3. Security configuration examples
  4. Name collision handling strategies
  5. Performance considerations and best practices
  6. Examples of common hub architectures

Open Questions

  1. Should the hub support filtering which primitives to expose from each server?
  2. How should the hub handle versioning differences between remote servers?
  3. Should the hub support primitive transformation/adaptation (e.g., modifying tool schemas)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions