Skip to content

[Server] Dynamic provider interfaces to support runtime capability registration #177

@e0ipso

Description

@e0ipso

Is your feature request related to a problem? Please describe.

The current MCP SDK architecture requires tools, prompts, and resources to be registered at build time with handlers that can be invoked via reflection-based parameter mapping. This poses significant challenges for framework integrations where:

  1. Capability definitions come from runtime sources (configuration entities, database records, external services) rather than compile-time discovery
  2. Parameters are passed as associative arrays from the MCP protocol, not as positional method arguments suitable for reflection
  3. Per-capability authorization requirements cannot be evaluated until the capability is invoked with a specific context

Integrators are forced to implement workarounds:

  • Custom request handlers that intercept calls and bypass the SDK's parameter matching
  • Dummy/no-op handlers registered purely for metadata discovery during capability listing
  • Custom loaders that construct schema objects manually to avoid reflection-based argument discovery

These workarounds are fragile, increase maintenance burden, and work against the SDK's intended extension points.

Describe the solution you'd like

Introduce three new interfaces that enable runtime capability registration and execution:

  • DynamicToolProviderInterface: Provides tools at runtime via getTools(), checks support via supportsTool(), and executes via executeTool()
  • DynamicPromptProviderInterface: Provides prompts at runtime via getPrompts(), checks support via supportsPrompt(), and retrieves via getPrompt()
  • DynamicResourceProviderInterface: Provides resources at runtime via getResources(), checks support via supportsResource(), and reads via readResource()
  • DynamicResourceTemplateProviderInterface: Provides resources at runtime via getResourceTemplates(), checks support via supportsResourceRemplate(), and reads via readResourceTemplate()

The Registry and request handlers should be extended to:

  1. Accept registration of dynamic providers
  2. Query dynamic providers during capability listing operations
  3. Delegate execution to dynamic providers when they claim support for a capability

Architectural Opportunities

This pattern opens several valuable architectural doors:

  1. Clean Separation of Concerns: Metadata discovery (getTools()), routing (supportsTool()), and execution (executeTool()) become explicit interface methods rather than implicit conventions

  2. Decorator-Based Cross-Cutting Concerns: Authorization, logging, rate limiting, and caching can be implemented as provider decorators without modifying core execution logic

  3. Framework-Agnostic Integration Points: Any framework (Drupal, Symfony, Laravel) can implement these interfaces to bridge their native plugin/service systems with MCP

  4. Lazy Loading: Capabilities don't need to be fully instantiated at registration time; providers can defer expensive operations until actual invocation

  5. Multi-Tenancy Support: Providers can filter capabilities based on session context, enabling per-tenant or per-user capability sets

  6. Hybrid Registration: Static and dynamic providers can coexist, allowing simple tools to use traditional registration while complex integrations use dynamic providers

Describe alternatives you've considered

  1. Custom Request Handlers: Intercept requests at the handler level and bypass SDK routing entirely. This works but duplicates error handling, logging, and result formatting logic.

  2. Build-Time Code Generation: Generate static registrations from runtime sources during a compilation phase. This adds complexity and feels very brittle.

Additional context

The dynamic provider pattern aligns with how modern frameworks handle extensibility:

  • Drupal uses plugin managers with runtime discovery
  • Symfony uses ...
  • Laravel uses ...

Providing first-class SDK support for this pattern may reduce friction for framework integrations and establish a clear architectural contract for capability providers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions