Skip to content

feat: support dynamic MCP primitive repositories#953

Open
ultramancode wants to merge 2 commits into
modelcontextprotocol:mainfrom
ultramancode:feat/dynamic-mcp-primitives
Open

feat: support dynamic MCP primitive repositories#953
ultramancode wants to merge 2 commits into
modelcontextprotocol:mainfrom
ultramancode:feat/dynamic-mcp-primitives

Conversation

@ultramancode
Copy link
Copy Markdown

@ultramancode ultramancode commented May 11, 2026

Adds request-aware, pluggable repository APIs for dynamic MCP server primitives: tools, resources, prompts, and completions.

This allows server implementations to resolve visible primitives from request/session context, while preserving the existing static in-memory registration behavior by default.

Fixes #578

Motivation and Context

Some MCP servers need to expose different tools, resources, prompts, or completion handlers depending on the authenticated user, tenant, token, or request context.

This change makes primitive discovery and resolution request-aware:

  • */list responses can be scoped per request context
  • follow-up operations such as tools/call, resources/read, prompts/get, and completion/complete resolve through the same request-aware repositories
  • custom implementations can choose their own pagination and cursor handling
  • existing static registration methods continue to work through default in-memory repositories

How Has This Been Tested?

Added unit and in-process server tests for the new repository path, including request-context based tool/resource/prompt visibility, completion capability wiring, cursor forwarding, runtime add/remove behavior, repository/static registration conflict validation, and stateful list-changed notifications for supported runtime mutations.

I tested the change locally end-to-end with a small servlet server and a Postman collection.

The test server returns different tools, resources, prompts, and completions based on the X-User request header, so I could verify that listing and resolution both go through the repository layer. I also checked runtime add/remove behavior and stateful list-changed notifications.


dynamic_mcp_test

Files used for the local test:

DynamicRepositoryDemoServlet.java

dynamic-repository-demo.postman_collection.json

I attached the servlet and Postman collection so the same checks can be reproduced locally.

Breaking Changes

None intended.

Existing static registrations continue to work. When no custom repository is provided, registrations are loaded into default in-memory repositories.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Design notes:

  • Static registrations and custom repositories cannot be mixed for the same primitive family. This avoids implicit SDK-level merge semantics.
  • Repository list methods receive McpSchema.PaginatedRequest, so custom implementations can choose whether and how to apply pagination and cursor handling.

@ultramancode ultramancode force-pushed the feat/dynamic-mcp-primitives branch from 0e34129 to c021fbc Compare May 12, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Primitive repository APIs (ResourceRepository, ToolsRepository, ... )

1 participant