-
Notifications
You must be signed in to change notification settings - Fork 97
Description
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:
- Capability definitions come from runtime sources (configuration entities, database records, external services) rather than compile-time discovery
- Parameters are passed as associative arrays from the MCP protocol, not as positional method arguments suitable for reflection
- 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 viasupportsTool(), and executes viaexecuteTool() - DynamicPromptProviderInterface: Provides prompts at runtime via
getPrompts(), checks support viasupportsPrompt(), and retrieves viagetPrompt() - DynamicResourceProviderInterface: Provides resources at runtime via
getResources(), checks support viasupportsResource(), and reads viareadResource() - DynamicResourceTemplateProviderInterface: Provides resources at runtime via
getResourceTemplates(), checks support viasupportsResourceRemplate(), and reads viareadResourceTemplate()
The Registry and request handlers should be extended to:
- Accept registration of dynamic providers
- Query dynamic providers during capability listing operations
- Delegate execution to dynamic providers when they claim support for a capability
Architectural Opportunities
This pattern opens several valuable architectural doors:
-
Clean Separation of Concerns: Metadata discovery (
getTools()), routing (supportsTool()), and execution (executeTool()) become explicit interface methods rather than implicit conventions -
Decorator-Based Cross-Cutting Concerns: Authorization, logging, rate limiting, and caching can be implemented as provider decorators without modifying core execution logic
-
Framework-Agnostic Integration Points: Any framework (Drupal, Symfony, Laravel) can implement these interfaces to bridge their native plugin/service systems with MCP
-
Lazy Loading: Capabilities don't need to be fully instantiated at registration time; providers can defer expensive operations until actual invocation
-
Multi-Tenancy Support: Providers can filter capabilities based on session context, enabling per-tenant or per-user capability sets
-
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
-
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.
-
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.