3030 - [ Prompts] ( #prompts )
3131 - [ Images] ( #images )
3232 - [ Context] ( #context )
33+ - [ Completions] ( #completions )
34+ - [ Elicitation] ( #elicitation )
35+ - [ Authentication] ( #authentication )
3336 - [ Running Your Server] ( #running-your-server )
3437 - [ Development Mode] ( #development-mode )
3538 - [ Claude Desktop Integration] ( #claude-desktop-integration )
@@ -73,7 +76,7 @@ The Model Context Protocol allows applications to provide context for LLMs in a
7376
7477### Adding MCP to your python project
7578
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.
7780
7881If you haven't created a uv-managed project yet, create one:
7982
@@ -209,13 +212,13 @@ from mcp.server.fastmcp import FastMCP
209212mcp = FastMCP(" My App" )
210213
211214
212- @mcp.resource (" config://app" )
215+ @mcp.resource (" config://app" , title = " Application Configuration " )
213216def get_config () -> str :
214217 """ Static configuration data"""
215218 return " App configuration here"
216219
217220
218- @mcp.resource (" users://{user_id} /profile" )
221+ @mcp.resource (" users://{user_id} /profile" , title = " User Profile " )
219222def get_user_profile (user_id : str ) -> str :
220223 """ Dynamic user data"""
221224 return f " Profile data for user { user_id} "
@@ -232,13 +235,13 @@ from mcp.server.fastmcp import FastMCP
232235mcp = FastMCP(" My App" )
233236
234237
235- @mcp.tool ()
238+ @mcp.tool (title = " BMI Calculator " )
236239def calculate_bmi (weight_kg : float , height_m : float ) -> float :
237240 """ Calculate BMI given weight in kg and height in meters"""
238241 return weight_kg / (height_m** 2 )
239242
240243
241- @mcp.tool ()
244+ @mcp.tool (title = " Weather Fetcher " )
242245async def fetch_weather (city : str ) -> str :
243246 """ Fetch current weather for a city"""
244247 async with httpx.AsyncClient() as client:
@@ -257,12 +260,12 @@ from mcp.server.fastmcp.prompts import base
257260mcp = FastMCP(" My App" )
258261
259262
260- @mcp.prompt ()
263+ @mcp.prompt (title = " Code Review " )
261264def review_code (code : str ) -> str :
262265 return f " Please review this code: \n\n { code} "
263266
264267
265- @mcp.prompt ()
268+ @mcp.prompt (title = " Debug Assistant " )
266269def debug_error (error : str ) -> list[base.Message]:
267270 return [
268271 base.UserMessage(" I'm seeing this error:" ),
@@ -310,6 +313,112 @@ async def long_task(files: list[str], ctx: Context) -> str:
310313 return " Processing complete"
311314```
312315
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+
313422### Authentication
314423
315424Authentication can be used by servers that want to expose tools accessing protected resources.
@@ -809,6 +918,42 @@ async def main():
809918 tool_result = await session.call_tool(" echo" , {" message" : " hello" })
810919```
811920
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+
812957### OAuth Authentication for Clients
813958
814959The SDK includes [ authorization support] ( https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization ) for connecting to protected MCP servers:
0 commit comments