30
30
- [ Prompts] ( #prompts )
31
31
- [ Images] ( #images )
32
32
- [ Context] ( #context )
33
+ - [ Completions] ( #completions )
34
+ - [ Elicitation] ( #elicitation )
35
+ - [ Authentication] ( #authentication )
33
36
- [ Running Your Server] ( #running-your-server )
34
37
- [ Development Mode] ( #development-mode )
35
38
- [ Claude Desktop Integration] ( #claude-desktop-integration )
@@ -73,7 +76,7 @@ The Model Context Protocol allows applications to provide context for LLMs in a
73
76
74
77
### Adding MCP to your python project
75
78
76
- We recommend using [ uv] ( https://docs.astral.sh/uv/ ) to manage your Python projects.
79
+ We recommend using [ uv] ( https://docs.astral.sh/uv/ ) to manage your Python projects.
77
80
78
81
If you haven't created a uv-managed project yet, create one:
79
82
@@ -209,13 +212,13 @@ from mcp.server.fastmcp import FastMCP
209
212
mcp = FastMCP(" My App" )
210
213
211
214
212
- @mcp.resource (" config://app" )
215
+ @mcp.resource (" config://app" , title = " Application Configuration " )
213
216
def get_config () -> str :
214
217
""" Static configuration data"""
215
218
return " App configuration here"
216
219
217
220
218
- @mcp.resource (" users://{user_id} /profile" )
221
+ @mcp.resource (" users://{user_id} /profile" , title = " User Profile " )
219
222
def get_user_profile (user_id : str ) -> str :
220
223
""" Dynamic user data"""
221
224
return f " Profile data for user { user_id} "
@@ -232,13 +235,13 @@ from mcp.server.fastmcp import FastMCP
232
235
mcp = FastMCP(" My App" )
233
236
234
237
235
- @mcp.tool ()
238
+ @mcp.tool (title = " BMI Calculator " )
236
239
def calculate_bmi (weight_kg : float , height_m : float ) -> float :
237
240
""" Calculate BMI given weight in kg and height in meters"""
238
241
return weight_kg / (height_m** 2 )
239
242
240
243
241
- @mcp.tool ()
244
+ @mcp.tool (title = " Weather Fetcher " )
242
245
async def fetch_weather (city : str ) -> str :
243
246
""" Fetch current weather for a city"""
244
247
async with httpx.AsyncClient() as client:
@@ -257,12 +260,12 @@ from mcp.server.fastmcp.prompts import base
257
260
mcp = FastMCP(" My App" )
258
261
259
262
260
- @mcp.prompt ()
263
+ @mcp.prompt (title = " Code Review " )
261
264
def review_code (code : str ) -> str :
262
265
return f " Please review this code: \n\n { code} "
263
266
264
267
265
- @mcp.prompt ()
268
+ @mcp.prompt (title = " Debug Assistant " )
266
269
def debug_error (error : str ) -> list[base.Message]:
267
270
return [
268
271
base.UserMessage(" I'm seeing this error:" ),
@@ -310,6 +313,112 @@ async def long_task(files: list[str], ctx: Context) -> str:
310
313
return " Processing complete"
311
314
```
312
315
316
+ ### Completions
317
+
318
+ MCP supports providing completion suggestions for prompt arguments and resource template parameters. With the context parameter, servers can provide completions based on previously resolved values:
319
+
320
+ Client usage:
321
+ ``` python
322
+ from mcp.client.session import ClientSession
323
+ from mcp.types import ResourceTemplateReference
324
+
325
+
326
+ async def use_completion (session : ClientSession):
327
+ # Complete without context
328
+ result = await session.complete(
329
+ ref = ResourceTemplateReference(
330
+ type = " ref/resource" , uri = " github://repos/{owner} /{repo} "
331
+ ),
332
+ argument = {" name" : " owner" , " value" : " model" },
333
+ )
334
+
335
+ # Complete with context - repo suggestions based on owner
336
+ result = await session.complete(
337
+ ref = ResourceTemplateReference(
338
+ type = " ref/resource" , uri = " github://repos/{owner} /{repo} "
339
+ ),
340
+ argument = {" name" : " repo" , " value" : " test" },
341
+ context_arguments = {" owner" : " modelcontextprotocol" },
342
+ )
343
+ ```
344
+
345
+ Server implementation:
346
+ ``` python
347
+ from mcp.server import Server
348
+ from mcp.types import (
349
+ Completion,
350
+ CompletionArgument,
351
+ CompletionContext,
352
+ PromptReference,
353
+ ResourceTemplateReference,
354
+ )
355
+
356
+ server = Server(" example-server" )
357
+
358
+
359
+ @server.completion ()
360
+ async def handle_completion (
361
+ ref : PromptReference | ResourceTemplateReference,
362
+ argument : CompletionArgument,
363
+ context : CompletionContext | None ,
364
+ ) -> Completion | None :
365
+ if isinstance (ref, ResourceTemplateReference):
366
+ if ref.uri == " github://repos/{owner} /{repo} " and argument.name == " repo" :
367
+ # Use context to provide owner-specific repos
368
+ if context and context.arguments:
369
+ owner = context.arguments.get(" owner" )
370
+ if owner == " modelcontextprotocol" :
371
+ repos = [" python-sdk" , " typescript-sdk" , " specification" ]
372
+ # Filter based on partial input
373
+ filtered = [r for r in repos if r.startswith(argument.value)]
374
+ return Completion(values = filtered)
375
+ return None
376
+ ```
377
+ ### Elicitation
378
+
379
+ Request additional information from users during tool execution:
380
+
381
+ ``` python
382
+ from mcp.server.fastmcp import FastMCP, Context
383
+ from mcp.server.elicitation import (
384
+ AcceptedElicitation,
385
+ DeclinedElicitation,
386
+ CancelledElicitation,
387
+ )
388
+ from pydantic import BaseModel, Field
389
+
390
+ mcp = FastMCP(" Booking System" )
391
+
392
+
393
+ @mcp.tool ()
394
+ async def book_table (date : str , party_size : int , ctx : Context) -> str :
395
+ """ Book a table with confirmation"""
396
+
397
+ # Schema must only contain primitive types (str, int, float, bool)
398
+ class ConfirmBooking (BaseModel ):
399
+ confirm: bool = Field(description = " Confirm booking?" )
400
+ notes: str = Field(default = " " , description = " Special requests" )
401
+
402
+ result = await ctx.elicit(
403
+ message = f " Confirm booking for { party_size} on { date} ? " , schema = ConfirmBooking
404
+ )
405
+
406
+ match result:
407
+ case AcceptedElicitation(data = data):
408
+ if data.confirm:
409
+ return f " Booked! Notes: { data.notes or ' None' } "
410
+ return " Booking cancelled"
411
+ case DeclinedElicitation():
412
+ return " Booking declined"
413
+ case CancelledElicitation():
414
+ return " Booking cancelled"
415
+ ```
416
+
417
+ The ` elicit() ` method returns an ` ElicitationResult ` with:
418
+ - ` action ` : "accept", "decline", or "cancel"
419
+ - ` data ` : The validated response (only when accepted)
420
+ - ` validation_error ` : Any validation error message
421
+
313
422
### Authentication
314
423
315
424
Authentication can be used by servers that want to expose tools accessing protected resources.
@@ -809,6 +918,42 @@ async def main():
809
918
tool_result = await session.call_tool(" echo" , {" message" : " hello" })
810
919
```
811
920
921
+ ### Client Display Utilities
922
+
923
+ When building MCP clients, the SDK provides utilities to help display human-readable names for tools, resources, and prompts:
924
+
925
+ ``` python
926
+ from mcp.shared.metadata_utils import get_display_name
927
+ from mcp.client.session import ClientSession
928
+
929
+
930
+ async def display_tools (session : ClientSession):
931
+ """ Display available tools with human-readable names"""
932
+ tools_response = await session.list_tools()
933
+
934
+ for tool in tools_response.tools:
935
+ # get_display_name() returns the title if available, otherwise the name
936
+ display_name = get_display_name(tool)
937
+ print (f " Tool: { display_name} " )
938
+ if tool.description:
939
+ print (f " { tool.description} " )
940
+
941
+
942
+ async def display_resources (session : ClientSession):
943
+ """ Display available resources with human-readable names"""
944
+ resources_response = await session.list_resources()
945
+
946
+ for resource in resources_response.resources:
947
+ display_name = get_display_name(resource)
948
+ print (f " Resource: { display_name} ( { resource.uri} ) " )
949
+ ```
950
+
951
+ The ` get_display_name() ` function implements the proper precedence rules for displaying names:
952
+ - For tools: ` title ` > ` annotations.title ` > ` name `
953
+ - For other objects: ` title ` > ` name `
954
+
955
+ This ensures your client UI shows the most user-friendly names that servers provide.
956
+
812
957
### OAuth Authentication for Clients
813
958
814
959
The SDK includes [ authorization support] ( https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization ) for connecting to protected MCP servers:
0 commit comments