@@ -99,12 +99,14 @@ from mcp.server.fastmcp import FastMCP
9999#  Create an MCP server
100100mcp =  FastMCP(" Demo" 
101101
102+ 
102103#  Add an addition tool
103104@mcp.tool ()
104105def  add (a : int , b : int ) -> int :
105106    """ Add two numbers""" 
106107    return  a +  b
107108
109+ 
108110#  Add a dynamic greeting resource
109111@mcp.resource (" greeting://{name} " 
110112def  get_greeting (name : str ) -> str :
@@ -139,34 +141,42 @@ The FastMCP server is your core interface to the MCP protocol. It handles connec
139141
140142``` python 
141143#  Add lifespan support for startup/shutdown with strong typing
144+ from  contextlib import  asynccontextmanager
142145from  dataclasses import  dataclass
143146from  typing import  AsyncIterator
144- from  mcp.server.fastmcp import  FastMCP
147+ 
148+ from  fake_database import  Database  #  Replace with your actual DB type
149+ 
150+ from  mcp.server.fastmcp import  Context, FastMCP
145151
146152#  Create a named server
147153mcp =  FastMCP(" My App" 
148154
149155#  Specify dependencies for deployment and development
150156mcp =  FastMCP(" My App" dependencies = [" pandas" " numpy" 
151157
158+ 
152159@dataclass 
153160class  AppContext :
154-     db: Database  #  Replace with your actual DB type
161+     db: Database
162+ 
155163
156164@asynccontextmanager 
157165async  def  app_lifespan (server : FastMCP) -> AsyncIterator[AppContext]:
158166    """ Manage application lifecycle with type-safe context""" 
167+     #  Initialize on startup
168+     db =  await  Database.connect()
159169    try :
160-         #  Initialize on startup
161-         await  db.connect()
162170        yield  AppContext(db = db)
163171    finally :
164172        #  Cleanup on shutdown
165173        await  db.disconnect()
166174
175+ 
167176#  Pass lifespan to server
168177mcp =  FastMCP(" My App" lifespan = app_lifespan)
169178
179+ 
170180#  Access type-safe lifespan context in tools
171181@mcp.tool ()
172182def  query_db (ctx : Context) -> str :
@@ -180,11 +190,17 @@ def query_db(ctx: Context) -> str:
180190Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects:
181191
182192``` python 
193+ from  mcp.server.fastmcp import  FastMCP
194+ 
195+ mcp =  FastMCP(" My App" 
196+ 
197+ 
183198@mcp.resource (" config://app" 
184199def  get_config () -> str :
185200    """ Static configuration data""" 
186201    return  " App configuration here" 
187202
203+ 
188204@mcp.resource (" users://{user_id} /profile" 
189205def  get_user_profile (user_id : str ) -> str :
190206    """ Dynamic user data""" 
@@ -196,10 +212,17 @@ def get_user_profile(user_id: str) -> str:
196212Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects:
197213
198214``` python 
215+ import  httpx
216+ from  mcp.server.fastmcp import  FastMCP
217+ 
218+ mcp =  FastMCP(" My App" 
219+ 
220+ 
199221@mcp.tool ()
200222def  calculate_bmi (weight_kg : float , height_m : float ) -> float :
201223    """ Calculate BMI given weight in kg and height in meters""" 
202-     return  weight_kg /  (height_m **  2 )
224+     return  weight_kg /  (height_m** 2 )
225+ 
203226
204227@mcp.tool ()
205228async  def  fetch_weather (city : str ) -> str :
@@ -214,16 +237,22 @@ async def fetch_weather(city: str) -> str:
214237Prompts are reusable templates that help LLMs interact with your server effectively:
215238
216239``` python 
240+ from  mcp.server.fastmcp import  FastMCP, types
241+ 
242+ mcp =  FastMCP(" My App" 
243+ 
244+ 
217245@mcp.prompt ()
218246def  review_code (code : str ) -> str :
219247    return  f " Please review this code: \n\n { code} " 
220248
249+ 
221250@mcp.prompt ()
222- def  debug_error (error : str ) -> list[Message]:
251+ def  debug_error (error : str ) -> list[types. Message]:
223252    return  [
224-         UserMessage(" I'm seeing this error:" 
225-         UserMessage(error),
226-         AssistantMessage(" I'll help debug that. What have you tried so far?" 
253+         types. UserMessage(" I'm seeing this error:" 
254+         types. UserMessage(error),
255+         types. AssistantMessage(" I'll help debug that. What have you tried so far?" , 
227256    ]
228257``` 
229258
@@ -235,6 +264,9 @@ FastMCP provides an `Image` class that automatically handles image data:
235264from  mcp.server.fastmcp import  FastMCP, Image
236265from  PIL  import  Image as  PILImage
237266
267+ mcp =  FastMCP(" My App" 
268+ 
269+ 
238270@mcp.tool ()
239271def  create_thumbnail (image_path : str ) -> Image:
240272    """ Create a thumbnail from an image""" 
@@ -250,6 +282,9 @@ The Context object gives your tools and resources access to MCP capabilities:
250282``` python 
251283from  mcp.server.fastmcp import  FastMCP, Context
252284
285+ mcp =  FastMCP(" My App" 
286+ 
287+ 
253288@mcp.tool ()
254289async  def  long_task (files : list[str ], ctx : Context) -> str :
255290    """ Process multiple files with progress tracking""" 
@@ -322,16 +357,19 @@ from mcp.server.fastmcp import FastMCP
322357
323358mcp =  FastMCP(" Echo" 
324359
360+ 
325361@mcp.resource (" echo://{message} " 
326362def  echo_resource (message : str ) -> str :
327363    """ Echo a message as a resource""" 
328364    return  f " Resource echo:  { message} " 
329365
366+ 
330367@mcp.tool ()
331368def  echo_tool (message : str ) -> str :
332369    """ Echo a message as a tool""" 
333370    return  f " Tool echo:  { message} " 
334371
372+ 
335373@mcp.prompt ()
336374def  echo_prompt (message : str ) -> str :
337375    """ Create an echo prompt""" 
@@ -343,20 +381,21 @@ def echo_prompt(message: str) -> str:
343381A more complex example showing database integration:
344382
345383``` python 
346- from  mcp.server.fastmcp import  FastMCP
347384import  sqlite3
348385
386+ from  mcp.server.fastmcp import  FastMCP
387+ 
349388mcp =  FastMCP(" SQLite Explorer" 
350389
390+ 
351391@mcp.resource (" schema://main" 
352392def  get_schema () -> str :
353393    """ Provide the database schema as a resource""" 
354394    conn =  sqlite3.connect(" database.db" 
355-     schema =  conn.execute(
356-         " SELECT sql FROM sqlite_master WHERE type='table'" 
357-     ).fetchall()
395+     schema =  conn.execute(" SELECT sql FROM sqlite_master WHERE type='table'" 
358396    return  " \n " 0 ] for  sql in  schema if  sql[0 ])
359397
398+ 
360399@mcp.tool ()
361400def  query_data (sql : str ) -> str :
362401    """ Execute SQL queries safely""" 
@@ -378,20 +417,27 @@ For more control, you can use the low-level server implementation directly. This
378417from  contextlib import  asynccontextmanager
379418from  typing import  AsyncIterator
380419
420+ from  fake_database import  Database  #  Replace with your actual DB type
421+ 
422+ from  mcp.server import  Server
423+ 
424+ 
381425@asynccontextmanager 
382426async  def  server_lifespan (server : Server) -> AsyncIterator[dict ]:
383427    """ Manage server startup and shutdown lifecycle.""" 
428+     #  Initialize resources on startup
429+     db =  await  Database.connect()
384430    try :
385-         #  Initialize resources on startup
386-         await  db.connect()
387431        yield  {" db" 
388432    finally :
389433        #  Clean up on shutdown
390434        await  db.disconnect()
391435
436+ 
392437#  Pass lifespan to server
393438server =  Server(" example-server" lifespan = server_lifespan)
394439
440+ 
395441#  Access lifespan context in handlers
396442@server.call_tool ()
397443async  def  query_db (name : str , arguments : dict ) -> list :
@@ -406,14 +452,15 @@ The lifespan API provides:
406452-  Type-safe context passing between lifespan and request handlers
407453
408454``` python 
409- from  mcp.server.lowlevel import  Server, NotificationOptions
410- from  mcp.server.models import  InitializationOptions
411455import  mcp.server.stdio
412456import  mcp.types as  types
457+ from  mcp.server.lowlevel import  NotificationOptions, Server
458+ from  mcp.server.models import  InitializationOptions
413459
414460#  Create a server instance
415461server =  Server(" example-server" 
416462
463+ 
417464@server.list_prompts ()
418465async  def  handle_list_prompts () -> list[types.Prompt]:
419466    return  [
@@ -422,18 +469,16 @@ async def handle_list_prompts() -> list[types.Prompt]:
422469            description = " An example prompt template" 
423470            arguments = [
424471                types.PromptArgument(
425-                     name = " arg1" 
426-                     description = " Example argument" 
427-                     required = True 
472+                     name = " arg1" description = " Example argument" required = True 
428473                )
429-             ]
474+             ], 
430475        )
431476    ]
432477
478+ 
433479@server.get_prompt ()
434480async  def  handle_get_prompt (
435-     name : str ,
436-     arguments : dict[str , str ] |  None 
481+     name : str , arguments : dict[str , str ] |  None 
437482) -> types.GetPromptResult:
438483    if  name !=  " example-prompt" 
439484        raise  ValueError (f " Unknown prompt:  { name} " )
@@ -443,14 +488,12 @@ async def handle_get_prompt(
443488        messages = [
444489            types.PromptMessage(
445490                role = " user" 
446-                 content = types.TextContent(
447-                     type = " text" 
448-                     text = " Example prompt text" 
449-                 )
491+                 content = types.TextContent(type = " text" text = " Example prompt text" 
450492            )
451-         ]
493+         ], 
452494    )
453495
496+ 
454497async  def  run ():
455498    async  with  mcp.server.stdio.stdio_server() as  (read_stream, write_stream):
456499        await  server.run(
@@ -462,12 +505,14 @@ async def run():
462505                capabilities = server.get_capabilities(
463506                    notification_options = NotificationOptions(),
464507                    experimental_capabilities = {},
465-                 )
466-             )
508+                 ), 
509+             ), 
467510        )
468511
512+ 
469513if  __name__  ==  " __main__" 
470514    import  asyncio
515+ 
471516    asyncio.run(run())
472517``` 
473518
@@ -476,18 +521,21 @@ if __name__ == "__main__":
476521The SDK provides a high-level client interface for connecting to MCP servers:
477522
478523``` python 
479- from  mcp import  ClientSession, StdioServerParameters
524+ from  mcp import  ClientSession, StdioServerParameters, types 
480525from  mcp.client.stdio import  stdio_client
481526
482527#  Create server parameters for stdio connection
483528server_params =  StdioServerParameters(
484-     command = " python" #  Executable
485-     args = [" example_server.py" #  Optional command line arguments
486-     env = None  #  Optional environment variables
529+     command = " python"   #  Executable
530+     args = [" example_server.py"   #  Optional command line arguments
531+     env = None ,   #  Optional environment variables
487532)
488533
534+ 
489535#  Optional: create a sampling callback
490- async  def  handle_sampling_message (message : types.CreateMessageRequestParams) -> types.CreateMessageResult:
536+ async  def  handle_sampling_message (
537+     message : types.CreateMessageRequestParams,
538+ ) -> types.CreateMessageResult:
491539    return  types.CreateMessageResult(
492540        role = " assistant" 
493541        content = types.TextContent(
@@ -498,17 +546,22 @@ async def handle_sampling_message(message: types.CreateMessageRequestParams) ->
498546        stopReason = " endTurn" 
499547    )
500548
549+ 
501550async  def  run ():
502551    async  with  stdio_client(server_params) as  (read, write):
503-         async  with  ClientSession(read, write, sampling_callback = handle_sampling_message) as  session:
552+         async  with  ClientSession(
553+             read, write, sampling_callback = handle_sampling_message
554+         ) as  session:
504555            #  Initialize the connection
505556            await  session.initialize()
506557
507558            #  List available prompts
508559            prompts =  await  session.list_prompts()
509560
510561            #  Get a prompt
511-             prompt =  await  session.get_prompt(" example-prompt" arguments = {" arg1" " value" 
562+             prompt =  await  session.get_prompt(
563+                 " example-prompt" arguments = {" arg1" " value" 
564+             )
512565
513566            #  List available resources
514567            resources =  await  session.list_resources()
@@ -522,8 +575,10 @@ async def run():
522575            #  Call a tool
523576            result =  await  session.call_tool(" tool-name" arguments = {" arg1" " value" 
524577
578+ 
525579if  __name__  ==  " __main__" 
526580    import  asyncio
581+ 
527582    asyncio.run(run())
528583``` 
529584
0 commit comments