@@ -160,7 +160,7 @@ from dataclasses import dataclass
160160
161161from fake_database import Database # Replace with your actual DB type
162162
163- from mcp.server.fastmcp import Context, FastMCP
163+ from mcp.server.fastmcp import FastMCP
164164
165165# Create a named server
166166mcp = FastMCP(" My App" )
@@ -192,9 +192,10 @@ mcp = FastMCP("My App", lifespan=app_lifespan)
192192
193193# Access type-safe lifespan context in tools
194194@mcp.tool ()
195- def query_db (ctx : Context ) -> str :
195+ def query_db () -> str :
196196 """ Tool that uses initialized resources"""
197- db = ctx.request_context.lifespan_context.db
197+ ctx = mcp.get_context()
198+ db = ctx.request_context.lifespan_context[" db" ]
198199 return db.query()
199200```
200201
@@ -631,7 +632,7 @@ server = Server("example-server", lifespan=server_lifespan)
631632# Access lifespan context in handlers
632633@server.call_tool ()
633634async def query_db (name : str , arguments : dict ) -> list :
634- ctx = server.get_context()
635+ ctx = server.request_context
635636 db = ctx.lifespan_context[" db" ]
636637 return await db.query(arguments[" query" ])
637638```
@@ -796,6 +797,60 @@ async def main():
796797 tool_result = await session.call_tool(" echo" , {" message" : " hello" })
797798```
798799
800+ ### OAuth Authentication for Clients
801+
802+ The SDK includes [ authorization support] ( https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization ) for connecting to protected MCP servers:
803+
804+ ``` python
805+ from mcp.client.auth import OAuthClientProvider, TokenStorage
806+ from mcp.client.session import ClientSession
807+ from mcp.client.streamable_http import streamablehttp_client
808+ from mcp.shared.auth import OAuthClientInformationFull, OAuthClientMetadata, OAuthToken
809+
810+
811+ class CustomTokenStorage (TokenStorage ):
812+ """ Simple in-memory token storage implementation."""
813+
814+ async def get_tokens (self ) -> OAuthToken | None :
815+ pass
816+
817+ async def set_tokens (self , tokens : OAuthToken) -> None :
818+ pass
819+
820+ async def get_client_info (self ) -> OAuthClientInformationFull | None :
821+ pass
822+
823+ async def set_client_info (self , client_info : OAuthClientInformationFull) -> None :
824+ pass
825+
826+
827+ async def main ():
828+ # Set up OAuth authentication
829+ oauth_auth = OAuthClientProvider(
830+ server_url = " https://api.example.com" ,
831+ client_metadata = OAuthClientMetadata(
832+ client_name = " My Client" ,
833+ redirect_uris = [" http://localhost:3000/callback" ],
834+ grant_types = [" authorization_code" , " refresh_token" ],
835+ response_types = [" code" ],
836+ ),
837+ storage = CustomTokenStorage(),
838+ redirect_handler = lambda url : print (f " Visit: { url} " ),
839+ callback_handler = lambda : (" auth_code" , None ),
840+ )
841+
842+ # Use with streamable HTTP client
843+ async with streamablehttp_client(
844+ " https://api.example.com/mcp" , auth = oauth_auth
845+ ) as (read, write, _):
846+ async with ClientSession(read, write) as session:
847+ await session.initialize()
848+ # Authenticated session ready
849+ ```
850+
851+ For a complete working example, see [ ` examples/clients/simple-auth-client/ ` ] ( examples/clients/simple-auth-client/ ) .
852+
853+
799854### MCP Primitives
800855
801856The MCP protocol defines three core primitives that servers can implement:
0 commit comments