Skip to content

Conversation

@chughtapan
Copy link
Contributor

@chughtapan chughtapan commented Aug 2, 2025

Reference implementation: for the SEP: Namespaces using URIs
Key Changes:

  1. Added uri fields to Tools and Prompts.
  2. Added capability to filter by URI prefixes for all list methods (list_resources, tools, etc.)

Motivation and Context

modelcontextprotocol/modelcontextprotocol#993 proposed namespaces as a new capability to offer hierarchical aggregation of MCP servers. However, was rejected in modelcontextprotocol/modelcontextprotocol#1061 with the motivation URIs are the preferred approach for handling hierarchies.

How Has This Been Tested?

All existing and new unit tests pass

Breaking Changes

Low-level code and SDKs might require changes, but this is non-breaking for clients & applications.

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

There are several open questions:

  • What should be the reserved URI prefix for tools and prompts? I propose mcp://tools/ and mcp://prompts/ and recommend that we should reserve the entire mcp:// prefix for future.
  • What should be the semantics around filters? I'm currently using path prefix matching for now but open to other alternatives as well

Tapan Chugh and others added 10 commits July 31, 2025 17:27
Add ToolResource and PromptResource base classes that extend the Resource
base class. Tool now inherits from ToolResource and Prompt inherits from
PromptResource, establishing a proper inheritance hierarchy.

Tools and prompts automatically generate URIs with their respective schemes
(tool://name and prompt://name) when created. This allows them to be accessed
through the ResourceManager using their URIs while maintaining full backward
compatibility with existing code.

The ResourceManager's list_resources() method filters out tool and prompt
URIs by default to preserve the existing API behavior. Tools and prompts
can still be accessed directly by their URIs when needed.

Comprehensive tests verify the inheritance model works correctly and that
all existing functionality remains intact.
Apply automated formatting from ruff to ensure consistent code style
across the combined features.
- Add uri field to FastMCP Tool and Prompt classes with automatic generation
- Change ToolManager and PromptManager to use URIs as primary keys
- Implement backward compatibility with automatic name-to-URI conversion
- Update server to use stored URIs instead of generating them
- Fix tests to handle URI-based warning messages

This aligns tools and prompts with the resource storage pattern, where URIs
are the primary identifiers. Names are automatically converted to URIs
(e.g., 'my_tool' -> 'tool://my_tool') for backward compatibility.
…ions

- Rename PaginatedRequestParams to ListRequestParams and add prefix field
- Rename PaginatedRequest to ListRequest for semantic clarity
- Rename PaginatedResult to ListResult for consistency
- Remove redundant ListResourcesRequestParams and ListResourceTemplatesRequestParams
- Add prefix filtering to tools and prompts list operations
- Ensure all prefixes are treated as path prefixes ending with /
- Update lowlevel server handlers to accept full request objects
- Update FastMCP server to extract prefix from request params

This unifies the list operation API across resources, templates, tools, and
prompts. All list methods now support optional prefix filtering using URI
path prefixes (e.g., 'tool://category/' to match only tools under that path).
…storage

- Add prefix parameter to PromptManager.list_prompts() with path prefix behavior
- Add _normalize_to_uri() method to convert names to prompt:// URIs
- Update add_prompt() to use URIs as keys for consistent storage
- Update get_prompt() to accept both names and URIs
- Update FastMCP server to pass request object to lowlevel handlers
- Fix test expectation for new path prefix behavior in list_templates

This completes the implementation of consistent prefix-based filtering
across all list operations (resources, templates, tools, and prompts).
This commit fixes all test failures that occurred after implementing
consistent prefix-based filtering across tools, prompts, and resources.

Changes:
- Add required URI fields to all Tool instances in tests
- Update all list_tools handlers to accept request parameter
- Fix client session to use ListRequestParams for all list methods
- Update test handlers in streamable_http, SSE, and WS tests

The tests were failing because:
1. Tool objects now require a URI field
2. Low-level server list_tools handlers expect a request parameter
3. Client session was using old RequestParams class names

All tests now pass except for one unrelated connection error.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Add TOOL_SCHEME and PROMPT_SCHEME constants in mcp/types.py
- Create common URI utilities in uri_utils.py for normalization and prefix filtering
- Update Tool and Prompt classes to auto-generate URIs when not provided
- Replace hardcoded URI schemes throughout codebase with constants
- Fix prefix filtering to handle partial matches correctly
- Update example files to match expected function signatures
- Replace unused request parameters with _ in handler functions
- Remove explicit URI additions where auto-generation suffices
- Remove unused TOOL_SCHEME and other imports
- Keep only changes essential for prefix filtering functionality

This reduces noise in tests and examples while maintaining the core
functionality of URI-based storage and prefix filtering.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
- Change URI schemes from tool:// and prompt:// to mcp://tools and mcp://prompts
- Add MCP_SCHEME constant and use it for URL validation
- Add model validators to ensure URIs start with correct prefixes
- Improve filter_by_prefix to accept AnyUrl | str, removing need for str() casts
- Make Prompt description field optional (matching main branch)
- Update all tests to use scheme constants instead of hardcoded values

This provides a more standard URI format where 'mcp' is the scheme and
'tools'/'prompts' are path segments, while also simplifying the API.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
…resources

- Changed Tool and Prompt URI fields from optional to required (auto-generated)
- Updated Resource validator to block any URI using the MCP scheme (mcp://)
- Removed unnecessary None checks in URI validators since fields are now required
- Updated tests to match new error message

This provides stronger type safety and clearer API contracts while maintaining
backward compatibility through auto-generation.
@lironsher
Copy link

Can you add some examples for URIs?

Tapan Chugh added 3 commits August 3, 2025 00:52
- Change Tool and Prompt classes to use AnyUrl for uri field
- Update all manager get/call methods to accept AnyUrl | str
- Add method overloads for better type hints
- Update tests to use AnyUrl objects
- Update filter_by_uri_paths to use Sequence for covariance
@chughtapan chughtapan force-pushed the combined_resource_prefix branch from 9a7c125 to 2dcdfae Compare August 4, 2025 01:13
@chughtapan chughtapan force-pushed the combined_resource_prefix branch from 2dcdfae to d4ead25 Compare August 4, 2025 01:24
@chughtapan
Copy link
Contributor Author

chughtapan commented Aug 4, 2025

@lironsher I have added an end-to-end example in hierarchical_organization.py
The eventual goal is that the spec can converge around a set of "well-known" resource endpoints which can provide more information about the uri space organization. The current choice of mcp://group/ based on ideas from @patwhite and @cliffhall

Screenshot 2025-08-03 at 6 21 57 PM

Copy link
Contributor

@felixweinberger felixweinberger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @chughtapan thank you for this contribution! Apologies for the time it took to get back to this PR.

SEP-993 has been closed and is now superseded by SEP-1300

Would you want to take a look at the new SEP modelcontextprotocol/modelcontextprotocol#1300 and potentially weigh in on whether it would also address your use case? There's significant discussion around several potential ways this could be achieved.

Going to mark this as "Pending SEP approval" as I believe your implementation here seems to implement the "groups" concept.

@felixweinberger felixweinberger added pending SEP approval When a PR is attached as an implementation detail to a SEP, we mark it as such for triage. enhancement New feature or request needs more eyes Needs alignment among maintainers whether this is something we want to add and removed needs more eyes Needs alignment among maintainers whether this is something we want to add labels Sep 17, 2025
@chughtapan chughtapan closed this Sep 17, 2025
@scottslewis
Copy link

A comment: Although I strongly agree with the general desire for having namespace support for tools MCPToolGroups in particular...and perhaps for other MCP-exposed capabilities (prompts, etc), I would say it may be a little premature to standardize a uri...i.e. protocol...at this point. Only because getting a new uri protocol established could be a long proocess wrt w3c, browser integration or integration in general.

In the immediate term, it might be easier to standardize just the namespace for tools/prompts/etc within the MCP Server process (analogous to 'path' segment of uri). The MCPToolGroups project defines a simple, common, well-understood, hierarchical namespace for tool groups (e.g. my.org.mcp.toolgroups.MyToolGroup) that can be used to guarantee in-process uniqueness. The 'dot' notation is already established for hierarchical namespaces in most languages for class naming...among other things.

This approach for tool groups namespace could then be easily extended by adding on the mcp protocol and host/port/authority parts of the uri.

Again I'm not critical of the namespaces with uris idea, I just think that an incremental approach might be more pragmatic and maybe quicker wrt supporting further MCP Server development.

@chughtapan
Copy link
Contributor Author

Thanks @scottslewis -- appreciate the feedback here. I think the idea of using "." based namespaces was proposed earlier in the original namespaces proposal and rejected in the favor of a more path based scheme
I had written up
modelcontextprotocol/modelcontextprotocol#1292 earlier, but
modelcontextprotocol/modelcontextprotocol#1300 is probably where the action has been recently. Hope we can finally converge on a solution here.

@scottslewis
Copy link

Thanks @scottslewis -- appreciate the feedback here. I think the idea of using "." based namespaces was proposed earlier in the original namespaces proposal and rejected in the favor of a more path based scheme I had written up modelcontextprotocol/modelcontextprotocol#1292 earlier, but modelcontextprotocol/modelcontextprotocol#1300 is probably where the action has been recently.

It seems by the last comment from cliffhall on modelcontextprotocol/modelcontextprotocol#1300 that he/others are preparing a new 'hierarchical groups only' proposal (without filtering, search, etc).

Although I understand the use of path...as it's already there in uri syntax spec, I do hope that the dot syntax is considered again for group names. Making every name look like a filesystem/path doesn't seem like a great idea to me...because the '/' as delimiter is so overused and...due to URL visibility in browsers...will make (e.g.) tool names look like resource names. Plus the fact that most programming langs these days use dot syntax...and not slash...for (e.g.) class naming....and programmers will be the ones defining these names...which implies to me re-using conventions for modules/classes (dot syntax with reverse domain name) if possible.

Hope we can finally converge on a solution here.

Yeah agreed.

@chughtapan
Copy link
Contributor Author

chughtapan commented Sep 19, 2025

Although I understand the use of path...as it's already there in uri syntax spec, I do hope that the dot syntax is considered again for group names. Making every name look like a filesystem/path doesn't seem like a great idea to me...because the '/' as delimiter is so overused and...due to URL visibility in browsers...will make (e.g.) tool names look like resource names. Plus the fact that most programming langs these days use dot syntax...and not slash...for (e.g.) class naming....and programmers will be the ones defining these names...which implies to me re-using conventions for modules/classes (dot syntax with reverse domain name) if possible.

IIUC the scenarios where having too many tool is a problem (currently) are mostly driven by API-to-MCP conversion flows, where the "/" based paths are already present. But, yeah, I understand the point about "." being present in most languages, and that makes sense too. Maybe we need multiple naming schemes in MCP :)

@scottslewis
Copy link

scottslewis commented Sep 19, 2025 via email

@cliffhall
Copy link
Member

It seems by the last comment from cliffhall on modelcontextprotocol/modelcontextprotocol#1300 that he/others are preparing a new 'hierarchical groups only' proposal (without filtering, search, etc).

We haven't decided on whether to propose hierarchical groups. We got a bunch of pushback on our previous Namespaces proposal mainly that hierarchies can be encapsulated in tool names themselves. And whether models could reliably navigate hierarchies, etc. Our focus will be to take Groups as proposed in 1300 and make it a separate proposal, probably without hierarchy at first just because of the resistance we've seen thus far on that topic.

@scottslewis
Copy link

It seems by the last comment from cliffhall on modelcontextprotocol/modelcontextprotocol#1300 that he/others are preparing a new 'hierarchical groups only' proposal (without filtering, search, etc).

We haven't decided on whether to propose hierarchical groups.

We got a bunch of pushback on our previous Namespaces proposal mainly that hierarchies can be encapsulated in tool names themselves.

That is indeed true...and is exactly what the MCPToolGroups work does (adds a hierarchical ToolGroupName...aka namespace essentially) using dot notation. Then when constructing the tool specification, it essentially uses the (optional) ToolGroupName.getFQName() as the prefix to the String tool name. e.g.

my.package.or.module.name.MyToolGroup.my-tool-name

Here's the ToolGroupName class. And here's the ToolGroup (abstract superclass).

One advantage to such an approach (no matter what the delimiter is) is that it requires no changes to the protocol. It also has what I think is another crucial advantage: The fully qualified name is left up to convention (i.e. the dev community declaring and implementing tool groups) rather than specification. This is crucial, IMHO, as I expect that tools implementers will want to have make/create hierarchical names for tool groups and tools to avoid name collisions on MCP servers...that may be using proxies to other servers to implement toolgroups and tools. There also the issues of security and trust that would make it very limiting (IMHO) to start with no hierarchy wrt tool groups.

This approach has the downside, however, of the tool name now being a String like my.package.or.module.name.MyToolGroup.my-tool-name for adding/removing to a ToolManager (or the McpSyncServer instance in the mcp-java-sdk).

It my view, it would be much better (IMHO) if the concept of a 'ToolGroup' was introduced to the mcp protocol, so that mcp clients and servers could avoid having to parse/reparse and send/resend a fully qualified tool group name.

so...in json:

ToolGroupName (or ToolGroupNamespace if you like)

{
"fullyQualifiedGroupName": String
}

ToolGroup:

{
"name": ToolGroupName,
"description": "any description associated with the ToolGroup for use by llm"
}

The advantage of introducing ToolGroupName (over having a String for the ToolGroup.name field), would be that the ToolGroupName fields could be added/migrate to provide better filtering and searching, as well as other meta-data (e.g. name segment/folder descriptions?), without having to introduce a new type to the spec.

And whether models could reliably navigate hierarchies, etc. Our focus will be to take Groups as proposed in 1300 and make it a separate proposal, probably without hierarchy at first just because of the resistance we've seen thus far on that topic.

FWIW, I do feel that hierarchy will be important almost immediately from the ToolGroup developer and implementer (and tools builders) point of view. Because in addition to ToolGroup uniqueness, there is/will be probably an immediate need for toolgroups in client UI (for organization) as well as server admin (in addition to searching and filtering).

IMHO introducing a simple naming convention for toolgroups specifically would be a relatively easy 'sell' to the developer world, as packages (java, other languages), modules (python, etc), and uniquely named classes/interfaces (as 'sets of tools') are very familiar to most developers. The MCPToolGroups examples show using a java class to create a tooldescription, and simply using the fully qualified classname (package/module name plus class name) as the prefix to the tool name. The use of a class as a 'ToolGroup' also could easily allow annotations/decorators to specify the ToolGroup description for LLM/model usage.

So in any event, I'm of the view that full uris are probably too much (in terms of Namespaces)...at least at this time...and having only a single level of tool group (no hierarchy) is probably too little, as it doesn't alleviate many of the problems of (e.g.) scaling to a large number of tools/groups of tools for many independent developers and organizations.

@cliffhall I would be interested in reading any arguments/discussions among the original 1300 authors and the reviewers, specifically against supporting hierarchy for groups (in the naming/as conventions or how tool groups are constructed by tools). Was it a matter of 'lets start simple', or something more specific than that? Thanksinadvance.

@cliffhall
Copy link
Member

@cliffhall I would be interested in reading any arguments/discussions among the original 1300 authors and the reviewers, specifically against supporting hierarchy for groups (in the naming/as conventions or how tool groups are constructed by tools). Was it a matter of 'lets start simple', or something more specific than that?

It was a combination of "let's start simple" and the fact that the previous namespaces SEP was turned down because it was turned down on the basis of hierarchical namespacing being achievable via tool name. We didn't want any crosstalk on that point, so we punted hierarchical groups to future discussion.

@scottslewis
Copy link

@cliffhall I would be interested in reading any arguments/discussions among the original 1300 authors and the reviewers, specifically against supporting hierarchy for groups (in the naming/as conventions or how tool groups are constructed by tools). Was it a matter of 'lets start simple', or something more specific than that?

It was a combination of "let's start simple" and the fact that the previous namespaces SEP was turned down because it was turned down on the basis of hierarchical namespacing being achievable via tool name.

This is what I don't understand. Why isn't hierarchical namespacing considered to be achievable via a tool name? (i.e. single String). In most programming languages, classes need a unique name. e.g. io.modelcontextprotocol.server.McpSyncServer. It seems to me, from the tool group designer/implementer this is exactly the same situation as a tool group. Why not define a naming convention of naming ToolGroups with a similar hierarchical group name (for uniqueness, and tool group implementer flexibility)? Then at tool add and remove time (on server), each tool's 'name' can resolve to io.modelcontextprotocol.server.McpSyncServer.my-tool-name....i.e. the tool's 'fully-qualified' name. This is precisely what I do with the existing mcp-java-sdk + mcp-annotations projects here:

https://github.com/ECF/MCPToolGroups/blob/main/com.composent.ai.mcp.toolgroup/src/main/java/com/composent/ai/mcp/toolgroup/ToolGroup.java

There is nothing at all that is java-specific here...it could easily implemented in any language.

A good thing about having a hierarchical toolgroup naming convention (instead of in the protocol spec), is that you are leaving most of the choices up to the programmers who will be actually creating toolgroups and tools, and allowing them flexibility in naming. It also possible that in the future a convention could be formalized/standardized into having (e.g.) a full URI (i.e. protocol, host/domain toolgroup/tool name> without destroying backward compatibility (i.e. requiring new servers and clients).

My own opinion is that hierarchical names for ToolGroups is needed immediately, because it's pretty much the only way to handle a large number of tools (or classes, or components, or modules, or apps, or ....). As well, hierarchy provides semantic info/relevant context...therefore the 'description' in ToolGroup class above for the LLM/model consumption.

We didn't want any crosstalk on that point, so we punted hierarchical groups to future discussion.

I agree that the notion of a full filesystem-like structure (both files and folders at every level) implies much more work and agreement for a protocol. But as per above, I think that if the problem is simplified in a very programmer-familiar way (unique hierarchical name for ToolGroups, rather then nested ToolGroups) that it would only require a small amount of protocol changes, leave open the possibility of future generalization (e.g. to URI), and still provide a well-known programmer-defined name (e.g. classes) that can scale to large numbers of tools while supporting organization for searching as well as LLM interpretation (ToolGroup descriptions).

@scottslewis
Copy link

To show what I'm talking about, I implemented in Java 'hierarchical toolgroup naming' as a fully-backward compatible addition of toolgroups to the mcp java sdk. It's on my fork of the mcp-java-sdk, and is on the toolgroup_naming branch.

Here's the package with the ToolGroup, ToolGroupName and subclasses (AsyncToolGroup, SyncToolGroup, etc for the various types of servers in the java sdk)

And to get this to all work...by resolving the hierarchical tool group name at server 'addTool' and 'removeTool' execution time dynamically, I've added this AbstractAsyncMcpServer class with addToolGroup(AsyncToolGroup, and removeToolGroup(AsyncToolGroup) methods + implementations that use the existing addTool(toolSpecification) and removeTool(String) methods in this class...which now inherits from AbstractAsyncMcpServer to in backward compatible way introduce addToolGroup and removeToolGroup.

Existing clients and servers would be able to show these fully qualified toolgroup names without new protocol or UI changes. Yes, 'old/existing' uis will want to show these group names hierarchically eventually, but that's not at all difficult once the new version of the appropriate sdk (with AsyncToolGroup, ToolGroup, ToolGroupName classes) is present.

@chughtapan
Copy link
Contributor Author

@scottslewis thanks for sharing your thoughts. I'm very much in the favor of using naming schemes to handle hierarchies? One feedback that I got from one of the core maintainers was that MCP tools now have a title field: so we could technically use the name field to mean the fully qualified name and leave the title field to be what is used for the models. I'm also okay with considering other delimiters and feel that hierarchies are gonna be critical for whatever notion of groups we end up with.
One question which my PR didn't address properly here was the notion of group discovery: how do clients understand what groups a server exposes, what do they mean, etc.? I'm didn't read through the code carefully yet, but I'm curious to understand more what your proposal to that problem is.

@scottslewis
Copy link

@scottslewis thanks for sharing your thoughts. I'm very much in the favor of using naming schemes to handle hierarchies? One feedback that I got from one of the core maintainers was that MCP tools now have a title field: so we could technically use the name field to mean the fully qualified name and leave the title field to be what is used for the models.

Yes, that's true (use tool.name() for the fully qualified name and use title for a 'human readable' name for the tool. The code that I link to above does exactly this (fully qualified name as the String tool name()), but even though the fully qualified toolgroup name could just be added as a prefix to the tool.name(), I think that it would make more sense to have a new ToolGroup type in the schema and protocol that includes more than just the fully qualified name.

In my opinion, one should ask: which clients will use the tool group?...and. for what use cases? If you are talking about models/LLMs as the client of the tool then I think that the String description for a toolgroup as the more direct answer to your question about what the tool group 'means' to the LLM. The title and name could also be considered useful information to the LLM, but I suspect that the title and name will be more useful in a user interface for accessing a tool...be it a UI directly via the client (e.g. inspector), or UI presented by the LLM/model.

As an example below is an Arithmetic tool group...using the current metadata protocol and schema-supported metadata (descriptions and titles as provided by programmer via McpTool and McpToolParam annotations/decorators):

public interface ArithmeticToolGroup {

	@McpTool(description = "computes the sum of the two double precision input arguments a and b")
	double add(@McpToolParam(description = "x is the first argument") double x,
			@McpToolParam(description = "y is the second argument") double y);

	@McpTool(description = "return the product of the two given double precision arguments named a and b")
	double multiply(@McpToolParam(description = "x is the first argument") double x,
			@McpToolParam(description = "y is the second argument") double y);

	@McpTool(description = "return asynchronously the sum of the two double precision input arguments a and b")
	Mono<Double> asyncAdd(@McpToolParam(description = "x is the first argument") double x,
			@McpToolParam(description = "y is the second argument") double y);

	@McpTool(description = "return asynchronously the product of the two given double precision arguments named a and b")
	Mono<Double> asyncMultiply(@McpToolParam(description = "x is the first argument") double x,
			@McpToolParam(description = "y is the second argument") double y);
}
For ToolGroups I would envision a new annotation/that could be used as follows:

```java
@McpToolGroup(title="Arithmetic Tools", description="tools for doing basic arithmetic operations")
public interface ArithmeticToolGroup {
...
}

The default name could be something like: com.composent.ai.mcp.toolgroups.ArithmeticToolGroup (the fully qualified name of the interface), while the title and the description would be as shown in the McpToolGroup annotation above. The values of all three (name, title, description, eventually 'tags'?) would be available for the LLM/model for 'meaning'.

But...to get a ToolGroup description and title the protocol must be enhanced...even if the name can be squeezed into the tool name() field (as per my code), a protocol enhancement is required for the tool group 'description' and 'title' meta-data to be somehow passed from server to any clients. Even if the hierarchical namespace and toolgroup were packed as a prefix to the tool name (as my example does) without a protocol enhancement, there's no way to get a toolgroup description or title to the client.

That's why I think that it would be cleaner if the schema/spec and protocol had a new ToolGroup type with String name, String description, String title meta-data.

I'm didn't read through the code carefully yet, but I'm curious to understand more what your proposal to that problem is.

Yes, I did want to demonstrate that a hierarchical namespace for toolgroups could just be added to the a Tool as its fully qualified name (single String). But I don't think that's optimal, as it doesn't provide for any toolgroup metadata (description, title, etc).

So I think a new schema entity for a ToolGroup, with it's own name, description, title, and (possibly) meta would be best...e.g.

type ToolGroup { "name": String, "description": String, "title": String } would make most sense so that the client can have and use the ToolGroup metadata (for LLM/model and/or user or dev UI). Then when a server communicates a Tool to a client (e.g. via listTools()), each Tool could have a ToolGroup typed 'group' field as part of the updated Tool schema.

@scottslewis
Copy link

To take this a little further toward specification concreteness, I've added to the mcp-java-sdk's McpSchema class here.

The McpSchema class is where the mcp-java-sdk has all the specification-defined types.

I've added the ToolGroupName and ToolGroup types.

I've also added a 'group' property (of type ToolGroup) to the Tool type.

@scottslewis
Copy link

To take this a little further toward specification concreteness, I've added to the mcp-java-sdk's McpSchema class here.

The McpSchema class is where the mcp-java-sdk has all the specification-defined types.

I've added the ToolGroupName and ToolGroup types.

I've also added a 'group' property (of type ToolGroup) to the Tool type.

I wanted to comment on this specifically to @cliffhall and @chughtapan. I can see now that all of the existing work at MCPToolGroups was really leading to the realization expressed by:

Yes, I did want to demonstrate that a hierarchical namespace for toolgroups could just be added to the a Tool as its fully qualified name (single String). But I don't think that's optimal, as it doesn't provide for any toolgroup metadata (description, title, etc).

What I'm really proposing is these changes to the spec in the form of two new types in the json schema (I'm not as facile with json schema language as I am Python or Java, so that's why I'm expressing these types as Java). But java types is 1-1 with the specified schema.

First type: ToolGroup. Fields/properties: name (required), title (optional), description (optional). There could be others fields in the future (e.g. 'searchtags') one nice thing is that new fields don't break backward compatibility (old servers and clients can just ignore the new fields...because they don't know about them).

Second Type: ToolGroupName. Fields/properties: parent (optional), segmentName (required). This type essentially represents a tool namespace (it could be called a ToolGroupNamespace I suppose). This type defines a hierarchical namespace with '.' as the name separator. It would be accepting of all of examples:

550e8400-e29b-41d4-a716-446655440000 (a uuid)

fa7b07d1-3377-4248-ad76-4eb267705a16.mygroup

com.composent.ai.mcp.toolgroups.ArithmeticToolGroup

MY.SHOUTINGGROUP

mcp://myserver.org/com.composent.ai.mcp.toolgroups.ArithmeticToolGroup

$%^deDIU

Are just a few examples. The reason this flexibility is a good thing is that all of the above are/will be established by convention...and if things to a particular way, they can all be accommodated without changing the spec and protocol....OR by enhancing the ToolGroupName type in the future by adding optional fields (which old servers/clients can still use if they ignore unknown fields in parser).

And then, the part that (optionally) connects a tool to a tool group is in the Tool type...adding the 'group' field/property with type ToolGroup. First, for backward compatibility, this field/property can be optional, which would basically mean 'no toolgroup for this/these tools'. Second, the group can be set by construction of the Tool, which allows the Tool builder the flexibility to define any appropriate ToolGroupName and provide any toolgroup metadata (title, description, others to be added in future) upon ToolGroup instance construction.

Once these two types are in the schema and connected to the Tool construction new servers be able to produce responses to (e.g.) listTools requests with Tools in json, and new clients will be able to use the ToolGroup title and description fields/meta-data to organize/classify/choose (models) or present in UI (tooling).

Note this isn't a formal proposal yet...as there are questions like...for ToolGroup type: Should other/additional meta-data be added? (e.g. searchtags or just tags)? Are the field names good/appropriate? Is having a hierarchical namespace with ToolGroupName a good way to go? (it could be just a String rather than a new schema type, but I think that a type will provide more opportunities for migration/backward compatibility.

@cliffhall : I will be thrilled if any parts of this approach are accepted into the forthcoming proposal. All I'm trying to do is to contribute productively to the community design problems. I don't have any other dogs in fights/am not representing anyone else's interests other than the open source dev/design community and mcp developers in general.

@scottslewis
Copy link

scottslewis commented Sep 24, 2025

@cliffhall @chughtapan

I've generated json schema from the two types (McpSchema.ToolGroup and McpSchema.ToolGroupName). Here's the schema:

{
  "$schema" : "https://json-schema.org/draft/2020-12/schema",
  "$defs" : {
    "ToolGroupName" : {
      "type" : "object",
      "properties" : {
        "parent" : {
          "$ref" : "#/$defs/ToolGroupName"
        },
        "segmentName" : {
          "type" : "string"
        }
      }
    },
  "ToolGroup" : {
   "type" : "object",
   "properties" : {
    "description" : {
      "type" : "string"
     },
     "name" : {
       "$ref" : "#/$defs/ToolGroupName"
     },
     "title" : {
       "type" : "string"
     }
   }
 }
}

The two classes are declared in my fork of the mcp-java-sdk on the 'toolgroup_naming' branch right here

I've also been playing around with this addition with the tooling/annotations support in the my fork, toolgroup_naming branch of the mcp-annotations project. Specifically, adding the McpToolGroup annotation type.

Also I neglected to mention that you could get much/most of the benefit by leaving the out the ToolGroupName type and just using a String type for the ToolGroup.name field. As I've said, I think it would be useful to have a hierarchical namespace support, so that community could decide over time how they want to uniquely define groups, But it could just start out as an opaque string without much loss. Again I think identifying the type ToolGroupName is probably worth it...so that it can be extended (i.e. fields/properties added) in a backward compatible way (without changing types of existing fields/properties like the ToolGroup.name).

@scottslewis
Copy link

@cliffhall @chughtapan

Here's the full Tool schema new 'group' property...of type ToolGroup.

{
  "$schema" : "https://json-schema.org/draft/2020-12/schema",
  "$defs" : {
    "Map(String,Object)" : {
      "type" : "object"
    },
    "ToolGroupName" : {
      "type" : "object",
      "properties" : {
        "parent" : {
          "$ref" : "#/$defs/ToolGroupName"
        },
        "segmentName" : {
          "type" : "string"
        }
      }
    }
  },
  "type" : "object",
  "properties" : {
    "annotations" : {
      "type" : "object",
      "properties" : {
        "destructiveHint" : {
          "type" : "boolean"
        },
        "idempotentHint" : {
          "type" : "boolean"
        },
        "openWorldHint" : {
          "type" : "boolean"
        },
        "readOnlyHint" : {
          "type" : "boolean"
        },
        "returnDirect" : {
          "type" : "boolean"
        },
        "title" : {
          "type" : "string"
        }
      }
    },
    "description" : {
      "type" : "string"
    },
    "group" : {
      "type" : "object",
      "properties" : {
        "description" : {
          "type" : "string"
        },
        "name" : {
          "$ref" : "#/$defs/ToolGroupName"
        },
        "title" : {
          "type" : "string"
        }
      }
    },
    "inputSchema" : {
      "type" : "object",
      "properties" : {
        "additionalProperties" : {
          "type" : "boolean"
        },
        "definitions" : {
          "$ref" : "#/$defs/Map(String,Object)"
        },
        "defs" : {
          "$ref" : "#/$defs/Map(String,Object)"
        },
        "properties" : {
          "$ref" : "#/$defs/Map(String,Object)"
        },
        "required" : {
          "type" : "array",
          "items" : {
            "type" : "string"
          }
        },
        "type" : {
          "type" : "string"
        }
      }
    },
    "meta" : {
      "$ref" : "#/$defs/Map(String,Object)"
    },
    "name" : {
      "type" : "string"
    },
    "outputSchema" : {
      "$ref" : "#/$defs/Map(String,Object)"
    },
    "title" : {
      "type" : "string"
    }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request pending SEP approval When a PR is attached as an implementation detail to a SEP, we mark it as such for triage.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants