Skip to content

Commit 906ceea

Browse files
fix: Expose completions capability (#865)
1 parent 3d67e72 commit 906ceea

File tree

4 files changed

+41
-7
lines changed

4 files changed

+41
-7
lines changed

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,13 +1327,13 @@ The MCP protocol defines three core primitives that servers can implement:
13271327

13281328
MCP servers declare capabilities during initialization:
13291329

1330-
| Capability | Feature Flag | Description |
1331-
|-------------|------------------------------|------------------------------------|
1332-
| `prompts` | `listChanged` | Prompt template management |
1333-
| `resources` | `subscribe`<br/>`listChanged`| Resource exposure and updates |
1334-
| `tools` | `listChanged` | Tool discovery and execution |
1335-
| `logging` | - | Server logging configuration |
1336-
| `completion`| - | Argument completion suggestions |
1330+
| Capability | Feature Flag | Description |
1331+
|--------------|------------------------------|------------------------------------|
1332+
| `prompts` | `listChanged` | Prompt template management |
1333+
| `resources` | `subscribe`<br/>`listChanged`| Resource exposure and updates |
1334+
| `tools` | `listChanged` | Tool discovery and execution |
1335+
| `logging` | - | Server logging configuration |
1336+
| `completions`| - | Argument completion suggestions |
13371337

13381338
## Documentation
13391339

src/mcp/server/lowlevel/server.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ def get_capabilities(
190190
resources_capability = None
191191
tools_capability = None
192192
logging_capability = None
193+
completions_capability = None
193194

194195
# Set prompt capabilities if handler exists
195196
if types.ListPromptsRequest in self.request_handlers:
@@ -209,12 +210,17 @@ def get_capabilities(
209210
if types.SetLevelRequest in self.request_handlers:
210211
logging_capability = types.LoggingCapability()
211212

213+
# Set completions capabilities if handler exists
214+
if types.CompleteRequest in self.request_handlers:
215+
completions_capability = types.CompletionsCapability()
216+
212217
return types.ServerCapabilities(
213218
prompts=prompts_capability,
214219
resources=resources_capability,
215220
tools=tools_capability,
216221
logging=logging_capability,
217222
experimental=experimental_capabilities,
223+
completions=completions_capability,
218224
)
219225

220226
@property

src/mcp/types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,12 @@ class LoggingCapability(BaseModel):
286286
model_config = ConfigDict(extra="allow")
287287

288288

289+
class CompletionsCapability(BaseModel):
290+
"""Capability for completions operations."""
291+
292+
model_config = ConfigDict(extra="allow")
293+
294+
289295
class ServerCapabilities(BaseModel):
290296
"""Capabilities that a server may support."""
291297

@@ -299,6 +305,8 @@ class ServerCapabilities(BaseModel):
299305
"""Present if the server offers any resources to read."""
300306
tools: ToolsCapability | None = None
301307
"""Present if the server offers any tools to call."""
308+
completions: CompletionsCapability | None = None
309+
"""Present if the server offers autocompletion suggestions for prompts and resources."""
302310
model_config = ConfigDict(extra="allow")
303311

304312

tests/server/test_session.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@
1111
from mcp.shared.session import RequestResponder
1212
from mcp.types import (
1313
ClientNotification,
14+
Completion,
15+
CompletionArgument,
16+
CompletionsCapability,
1417
InitializedNotification,
18+
PromptReference,
1519
PromptsCapability,
20+
ResourceReference,
1621
ResourcesCapability,
1722
ServerCapabilities,
1823
)
@@ -80,6 +85,7 @@ async def test_server_capabilities():
8085
caps = server.get_capabilities(notification_options, experimental_capabilities)
8186
assert caps.prompts is None
8287
assert caps.resources is None
88+
assert caps.completions is None
8389

8490
# Add a prompts handler
8591
@server.list_prompts()
@@ -89,6 +95,7 @@ async def list_prompts():
8995
caps = server.get_capabilities(notification_options, experimental_capabilities)
9096
assert caps.prompts == PromptsCapability(listChanged=False)
9197
assert caps.resources is None
98+
assert caps.completions is None
9299

93100
# Add a resources handler
94101
@server.list_resources()
@@ -98,6 +105,19 @@ async def list_resources():
98105
caps = server.get_capabilities(notification_options, experimental_capabilities)
99106
assert caps.prompts == PromptsCapability(listChanged=False)
100107
assert caps.resources == ResourcesCapability(subscribe=False, listChanged=False)
108+
assert caps.completions is None
109+
110+
# Add a complete handler
111+
@server.completion()
112+
async def complete(ref: PromptReference | ResourceReference, argument: CompletionArgument):
113+
return Completion(
114+
values=["completion1", "completion2"],
115+
)
116+
117+
caps = server.get_capabilities(notification_options, experimental_capabilities)
118+
assert caps.prompts == PromptsCapability(listChanged=False)
119+
assert caps.resources == ResourcesCapability(subscribe=False, listChanged=False)
120+
assert caps.completions == CompletionsCapability()
101121

102122

103123
@pytest.mark.anyio

0 commit comments

Comments
 (0)