feat(core): implement dynamic tool management with filtering and cursor pagination #747
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Implement ToolsRepository for Dynamic Tool Management & Cursor-based Pagination
Closes #746
Summary
This PR introduces the
ToolsRepositoryinterface and its default implementation (InMemoryToolsRepository) to enable dynamic, context-aware tool management inMcpAsyncServer.Motivation
Currently,
McpAsyncServeronly supports static tool registration during initialization. This limits flexibility for scenarios like:Changes
New Files
ToolsRepository.javaInMemoryToolsRepository.javaConcurrentHashMapToolsListResult.javaModified Files
McpAsyncServer.javaToolsRepositoryMcpServerFeatures.javatoolsRepositoryfield to builderMcpServer.java.toolsRepository()methodTechnical Considerations
Cursor-based Pagination: The implementation uses cursor tokens (following the MCP spec). The cursor is opaque to clients; while the examples below use a simple numeric offset for demonstration, production implementations can choose stable tokens (e.g., signed/encoded/timestamp-based) to ensure data stability.
ToolsListResult Encapsulation: Response is encapsulated in
ToolsListResultto cleanly separate the list of tools from the metadata (cursor), matching the MCPtools/liststructure.Separation of Concerns:
listToolshandles visibility ("What tools exist?"), whileresolveToolForCallhandles executability ("Can I run this?").Important
Security Note: Hiding a tool in
listToolsis NOT sufficient for security. Implementations should also verify permissions inresolveToolForCall..tools()API continues to work unchanged. If no custom repository is provided,InMemoryToolsRepositoryis automatically used.InMemoryToolsRepositoryusesConcurrentHashMapfor safe concurrent access.ToolsRepositoryinterface.API Usage
Existing Code (No Changes Required)
Custom Repository
Example: Filtering by Client Context and Pagination
Example code
Verification Results
The implementation was verified using a sample Spring Boot application to confirm that filtering and pagination work as intended in different role-based scenarios.
Scenario 1: Standard User Access (Filtering & Pagination)
X-Role: USERheader.nextCursor.page1returned 2 public tools.nextCursoris "2", pointing to the next available tool.Scenario 2: Administrator Access (Full Visibility)
X-Role: ADMINheader.Types of changes
Checklist
spring-javaformat:apply)Additional context
ToolsRepositorywas introduced to decouple tool storage from the core engine, enabling pluggable and dynamic tool management.Important
Security Note: Hiding a tool in
listToolsis NOT sufficient for security. Implementation developers SHOULD also verify permissions inresolveToolForCallto prevent unauthorized execution.