Skip to content

Commit bdea300

Browse files
committed
Ran npm run generate:seps
1 parent e22dc0d commit bdea300

3 files changed

Lines changed: 322 additions & 25 deletions

File tree

Lines changed: 289 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,289 @@
1+
---
2+
title: "SEP-2084: Untitled"
3+
sidebarTitle: "SEP-2084: Untitled"
4+
description: "Untitled"
5+
---
6+
7+
import { Badge } from "/snippets/badge.mdx";
8+
9+
<div className="flex items-center gap-2 mb-4">
10+
<Badge color="gray">Unknown</Badge>
11+
<Badge color="gray">Unknown</Badge>
12+
</div>
13+
14+
| Field | Value |
15+
| ------------- | ------------------------------------------------------------------------ |
16+
| **SEP** | 2084 |
17+
| **Title** | Untitled |
18+
| **Status** | Unknown |
19+
| **Type** | Unknown |
20+
| **Created** | Unknown |
21+
| **Author(s)** | Unknown |
22+
| **Sponsor** | None |
23+
| **PR** | [#2084](https://github.com/modelcontextprotocol/specification/pull/2084) |
24+
25+
---
26+
27+
## Abstract
28+
29+
This SEP proposes Groups, a new server capability and primitive, to organize tools, prompts, resources, tasks, and groups themselves, into named collections.
30+
31+
## Motivation
32+
33+
### What are Groups?
34+
35+
Groups are named collections of MCP primitives: tools, prompts, resources, tasks, and other groups, organized by use cases, functionality, etc.
36+
37+
- A productivity server could organize groups such as Email or Calendar, and present related tools, e.g. Email: ["Draft Email", "Spell Check", "Send Email"], Calendar: ["Add Participants", "Find Open Time", "Create Appointment"]
38+
- A server with many tools could separate them by functionality such as "Pull Requests", "Issues", "Actions".
39+
- A server with various reference programming resources could separate them by language, like "Python", "TypeScript, and "Kotlin".
40+
41+
#### Groups are overlapping sets NOT hierarchies
42+
43+
- Primitives can belong to multiple groups; for instance, if tools are grouped by use case, a `spell_check` tool might appear in both `compose_email` and `compose_document` groups.
44+
- Since groups are a primitive, they may belong to multiple groups, and so the result is **not a hierarchy** but rather, potentially overlapping sets.
45+
- Server developers should take care to avoid cyclic graphs — e.g., a group belonging to itself or to a child.
46+
47+
#### Transitivity
48+
49+
- Primitive A is in group B. Group B is in group C. Is primitive A implicitly in group C also?
50+
- The Transitivity of groups is a matter of client interpretation.
51+
- In the TypeScript reference implementation, the `communications` group contains `email` and `calendar` groups.
52+
- When listing the primitives in the `communications` group, I chose to have it display the contents of both children.
53+
- So `email_thank_contributor` would appear in both `email` and `communications`.
54+
- Some clients might wish to only show direct children of a group.
55+
- If a server contained cyclic graphs, configuring the client to only show the direct children of a group would short circuit the graph traversal, unless the group contains itself as a direct child, which would be an obvious mistake on the server developer's part that would likely never happen in production.
56+
57+
#### Visibility of Groups to LLMs
58+
59+
- Groups are simply an organizational tool available to the server developer.
60+
- It is up to clients to decide how to interpret and make use of them, e.g., for deciding what primitives to expose to LLMs or simply ignoring them.
61+
- Server developers cannot expect that clients will pass any group information to LLMs, although they may.
62+
63+
### Why use Groups?
64+
65+
Organizing a server's primitives by functionality or use case enables richer client workflows, wherein certain operations or settings can be applied to multiple primitives concurrently. Some use cases [identified by the community](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/1772) include:
66+
67+
#### Client-Side & User Organization
68+
69+
- **Client-side Filtering:** Client UIs could display a list of groups and allow users to select/deselect specific groups to interact with or ignore. Primitives from deselected groups would not be presented to the LLM.
70+
71+
- **Library Management:** Enabling users to create and manage organized Prompt and Resource libraries that can be shared or reused across different sessions.
72+
73+
- **Presentation and Search:** Improving how humans and AI models look up and discover tools. Grouping helps organize the interface so that relevant tools are easier to find among hundreds of options.
74+
75+
- **Workflow-Specific Context:** Providing a model with a "set" of tools and tasks specifically curated for a particular workflow, rather than overwhelming it with every available primitive.
76+
77+
#### Server-Side & Architectural Patterns
78+
79+
- **Gateway Facades:** Using a Gateway Server to wrap various backend services (REST APIs, databases, or legacy systems) into a single cohesive facade. For example, a group might dynamically expose a mix of tools from different MCP servers, APIs, REST services, etc.
80+
81+
- **Dynamic Orchestration:** Supporting the ability to add or remove groups and tools without restarting the server, which is essential for high-availability gateway environments.
82+
83+
- **Task Management:** Grouping the new Task primitive alongside tools and prompts to manage long-running workflows, sequencing, and concurrency.
84+
85+
#### Governance & Development Lifecycle
86+
87+
- **Governance and Security:** Providing a standardized mechanism for server-side governance of who can access specific sets of tools and resources.
88+
89+
- **Ecosystem Tooling:** Supporting broader developer workflows such as debugging, automated testing, and documentation by grouping related diagnostic tools together.
90+
91+
## Specification
92+
93+
**Recommendation:** Groups are implemented as new MCP primitive, alongside the existing ones (i.e., tools, resources, prompts, and tasks). The new primitive will have a similar schema, list method, and list changed notification. Additionally, all MCP primitives, including groups, use a new reserved `_meta` key to list the groups to which they belong.
94+
95+
### Capability
96+
97+
Servers that support groups MUST declare the capability during initialization, including whether list change notifications are supported. Group lists can change at runtime, and so support for listChanged notifications for each is included.
98+
99+
```json
100+
{
101+
"capabilities": {
102+
"groups": {
103+
"listChanged": true
104+
}
105+
}
106+
}
107+
```
108+
109+
### Schema
110+
111+
```json
112+
"Group": {
113+
"properties": {
114+
"name": {
115+
"description": "Intended for programmatic or logical use, but used as a display name in past specs or fallback (if title isn't present). Must be unique.",
116+
"type": "string"
117+
},
118+
"title": {
119+
"description": "Intended for UI and end-user contexts — optimized to be human-readable and easily understood.",
120+
"type": "string"
121+
},
122+
"description": {
123+
"description": "A full, human-readable description of the group.",
124+
"type": "string"
125+
},
126+
"_meta": {
127+
"additionalProperties": {},
128+
"description": "See [General fields: `_meta`](/specification/2025-11-25/basic/index#meta) for notes on `_meta` usage.",
129+
"io.modelcontextprotocol/groups": {
130+
"description": "A list of group names containing this group.",
131+
"items": {
132+
"type": "string"
133+
},
134+
"type": "array"
135+
},
136+
"type": "object",
137+
},
138+
"annotations": {
139+
"$ref": "#/$defs/Annotation",
140+
"description": "Optional additional group information.\n\nDisplay name precedence order is: title, annotations.title, then name."
141+
},
142+
"icons": {
143+
"description": "Optional set of sized icons that the client can display in a user interface.\n\nClients that support rendering icons MUST support at least the following MIME types:\n- `image/png` - PNG images (safe, universal compatibility)\n- `image/jpeg` (and `image/jpg`) - JPEG images (safe, universal compatibility)\n\nClients that support rendering icons SHOULD also support:\n- `image/svg+xml` - SVG images (scalable but requires security precautions)\n- `image/webp` - WebP images (modern, efficient format)",
144+
"items": {
145+
"$ref": "#/$defs/Icon"
146+
},
147+
"type": "array"
148+
}
149+
},
150+
"required": [
151+
"name"
152+
],
153+
"type": "object"
154+
}
155+
```
156+
157+
### Reserved `_meta` Property for All Primitives
158+
159+
Grouping of all primitives is handled in the same way, including groups themselves.
160+
161+
For groups, tools, resources, prompts, and tasks, an optional reserved `_meta` key is used to present the list of group names to which the primitive instance belongs.
162+
163+
By listing a primitive's groups in a reserved `_meta` property, we ensure backward compatibility.
164+
165+
```json
166+
"io.modelcontextprotocol/groups": {
167+
"description": "A list of group names containing this [primitive name].",
168+
"items": {
169+
"type": "string"
170+
},
171+
"type": "array"
172+
},
173+
```
174+
175+
### Groups Discovery Method: groups/list
176+
177+
Request:
178+
179+
```json
180+
{
181+
"jsonrpc": "2.0",
182+
"id": 2,
183+
"method": "groups/list"
184+
}
185+
```
186+
187+
Response:
188+
189+
```json
190+
{
191+
"jsonrpc": "2.0",
192+
"id": 2,
193+
"result": {
194+
"groups": [
195+
{
196+
"name": "user",
197+
"title": "User Management Tools",
198+
"description": "Tools used for managing user accounts within the system."
199+
},
200+
{
201+
"name": "mapping",
202+
"title": "Geospatial Mapping Tools",
203+
"description": "Tools used for map rendering, geocoding, and spatial analysis."
204+
}
205+
]
206+
}
207+
}
208+
```
209+
210+
### Changes to Response Formats
211+
212+
As mentioned above, all primitives have a new property that appears in their list result. This includes `tools/list`, `resources/list`, `resources/templates/list`, `prompts/list`, `tasks/list`.
213+
Here is an example tool definition from `tools/list` response with new groups property:
214+
215+
```json
216+
{
217+
"name": "calculator",
218+
"title": "Arithmetic Calculator",
219+
"description": "Perform mathematical calculations on arithmetic expressions",
220+
"inputSchema": {
221+
"type": "object",
222+
"properties": {
223+
"expression": {
224+
"type": "string",
225+
"description": "Expression to evaluate (e.g., '2 + 3 * 4')"
226+
}
227+
},
228+
"required": ["expression"]
229+
},
230+
"_meta": {
231+
"io.modelcontextprotocol/groups": ["arithmetic"]
232+
}
233+
}
234+
```
235+
236+
### Notifications
237+
238+
#### List Changed
239+
240+
When the list of available groups changes, servers that declared the listChanged capability SHOULD send a notification:
241+
242+
```json
243+
{
244+
"jsonrpc": "2.0",
245+
"method": "notifications/groups/list_changed"
246+
}
247+
```
248+
249+
#### Membership Changed
250+
251+
If a primitive is added (or removed) from a group, the server SHOULD send the `list_changed` notification appropriate for that primitive.
252+
253+
## Rationale
254+
255+
This specification proposal was selected for its ease of understanding since it mirrors the other MCP primitives.
256+
257+
### Alternatives Considered
258+
259+
- **Groups as MCP Resources instead of new primitive:** A completely separate proposal where the group metadata is declared in MCP resources with a specific schema and mimeType, referenced by their URIs, e.g., `mcp://groups/{groupId}`. Servers MAY publish the group index at a URI which MUST be defined in the capabilities object during the server initialization. This proposal could reduce spec changes and implementation effort significantly, but it was not considered as intuitive.
260+
261+
- **Primitive's group list passed in a first class `groups` property:** A variation of the proposed specification, but the list of groups to which a primitive instance belongs would be presented by a `groups` property added to the top level of each primitive's schema.
262+
This idea was discarded because it could lead to backward compatibility issues. For instance, if a server returned a tool, resource, etc, with this property to an older client which validated it against a strict schema that did not contain this property, it would most likely cause an error.
263+
Since this proposal spans all primitives, such a compatibility failure would be unacceptable. We could require SDK developers to implement a "feature flag" that suppresses the top-level groups field in all primitives after protocol version negotiation takes place if there is a mismatch. However, that would be more effort and complexity than simply using a reserved metadata key to pass the primitive's group list, which older clients would simply ignore.
264+
265+
- **Primitive's group list as an array of Group instances not names:** A variation of the proposed specification, but the schema would reference the Groups definition instead of declaring a string (group name). This means that full Group instances would appear in the primitive's group list, significantly increasing the token count when passed to an LLM without modification. Also, beacuse groups belong to other groups, every child of a given group would carry a duplicate of the parent instance. There was discussion of mitigating the duplication on the line using libraries that perform a marshalling on send/receive, replacing the parent with a pointer to a single copy of the parent instance. This would put an unnecessary burden on SDK developers for no clear benefit, when a client can easily look up a group by name in its cached `groups/list` result.
266+
More information on this approach can be found in @scottslewis's [proposal](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/1567).
267+
268+
- **No Grouping of Groups** - A variation of the proposed specification, but Groups cannot have a group list. Avoids any worry of graphs — e.g., a group belonging to itself or to a child. Makes groups a flat list.
269+
270+
## Security Implications
271+
272+
No serious implications identified.
273+
274+
We do wish to point out that use of groups for controlling access to a set of primitives, while a stated use case, could have security implications if groups change dynamically.
275+
276+
## Reference Implementation
277+
278+
- **Schema Changes:** [PR #2110](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2110)
279+
- **TypeScript SDK:** [PR #1399](https://github.com/modelcontextprotocol/typescript-sdk/pull/1399) - Fully implemented with unit tests and documented client/server examples.
280+
281+
The reference implementation's example client and server demonstrate how groups, tools, prompts, and resources can be grouped on the server, and the client can filter them by group. It manually demonstrates how an agent using the server could easily reduce the tokens placed into an LLM's context by only including the primitives in one or more groups rather than providing the full list.
282+
283+
Note: Tasks are not included in the example as they are ephemeral, but the SDK changes do support grouping of tasks.
284+
285+
## Acknowledgements
286+
287+
- @cliffhall and @chughtapan thank @patwhite for his earlier work on [SEP-1300](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1300) where a version of this grouping approach was first proposed.
288+
- And thanks to @scottslewis for rounding up [use cases](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/1772) for grouping and providing input on alternative implementations.
289+
- Thanks also to @bdoyle0182, @LucaButBoring, and @SamMorrowDrums for providing feedback and opinions in Discord and meetings.

0 commit comments

Comments
 (0)