44
55import inspect
66import re
7- from collections .abc import AsyncIterator , Awaitable , Callable , Iterable , Sequence
8- from contextlib import (
9- AbstractAsyncContextManager ,
10- asynccontextmanager ,
11- )
7+ from collections .abc import AsyncIterator , Awaitable , Callable , Collection , Iterable , Sequence
8+ from contextlib import AbstractAsyncContextManager , asynccontextmanager
129from typing import Any , Generic , Literal
1310
1411import anyio
2522from starlette .types import Receive , Scope , Send
2623
2724from mcp .server .auth .middleware .auth_context import AuthContextMiddleware
28- from mcp .server .auth .middleware .bearer_auth import (
29- BearerAuthBackend ,
30- RequireAuthMiddleware ,
31- )
25+ from mcp .server .auth .middleware .bearer_auth import BearerAuthBackend , RequireAuthMiddleware
3226from mcp .server .auth .provider import OAuthAuthorizationServerProvider , ProviderTokenVerifier , TokenVerifier
3327from mcp .server .auth .settings import AuthSettings
3428from mcp .server .elicitation import ElicitationResult , ElicitSchemaModelT , elicit_with_validation
4842from mcp .server .streamable_http_manager import StreamableHTTPSessionManager
4943from mcp .server .transport_security import TransportSecuritySettings
5044from mcp .shared .context import LifespanContextT , RequestContext , RequestT
51- from mcp .types import (
52- AnyFunction ,
53- ContentBlock ,
54- GetPromptResult ,
55- ToolAnnotations ,
56- )
45+ from mcp .types import AnyFunction , ContentBlock , GetPromptResult , ToolAnnotations
5746from mcp .types import Prompt as MCPPrompt
5847from mcp .types import PromptArgument as MCPPromptArgument
5948from mcp .types import Resource as MCPResource
@@ -108,7 +97,7 @@ class Settings(BaseSettings, Generic[LifespanResultT]):
10897 description = "List of dependencies to install in the server environment" ,
10998 )
11099
111- lifespan : Callable [[FastMCP ], AbstractAsyncContextManager [LifespanResultT ]] | None = Field (
100+ lifespan : Callable [[FastMCP [ LifespanResultT ] ], AbstractAsyncContextManager [LifespanResultT ]] | None = Field (
112101 None , description = "Lifespan context manager"
113102 )
114103
@@ -119,18 +108,18 @@ class Settings(BaseSettings, Generic[LifespanResultT]):
119108
120109
121110def lifespan_wrapper (
122- app : FastMCP ,
123- lifespan : Callable [[FastMCP ], AbstractAsyncContextManager [LifespanResultT ]],
124- ) -> Callable [[MCPServer [LifespanResultT , Request ]], AbstractAsyncContextManager [object ]]:
111+ app : FastMCP [ LifespanResultT ] ,
112+ lifespan : Callable [[FastMCP [ LifespanResultT ] ], AbstractAsyncContextManager [LifespanResultT ]],
113+ ) -> Callable [[MCPServer [LifespanResultT , Request ]], AbstractAsyncContextManager [LifespanResultT ]]:
125114 @asynccontextmanager
126- async def wrap (s : MCPServer [LifespanResultT , Request ]) -> AsyncIterator [object ]:
115+ async def wrap (_ : MCPServer [LifespanResultT , Request ]) -> AsyncIterator [LifespanResultT ]:
127116 async with lifespan (app ) as context :
128117 yield context
129118
130119 return wrap
131120
132121
133- class FastMCP :
122+ class FastMCP ( Generic [ LifespanResultT ]) :
134123 def __init__ (
135124 self ,
136125 name : str | None = None ,
@@ -140,14 +129,50 @@ def __init__(
140129 event_store : EventStore | None = None ,
141130 * ,
142131 tools : list [Tool ] | None = None ,
143- ** settings : Any ,
132+ debug : bool = False ,
133+ log_level : Literal ["DEBUG" , "INFO" , "WARNING" , "ERROR" , "CRITICAL" ] = "INFO" ,
134+ host : str = "127.0.0.1" ,
135+ port : int = 8000 ,
136+ mount_path : str = "/" ,
137+ sse_path : str = "/sse" ,
138+ message_path : str = "/messages/" ,
139+ streamable_http_path : str = "/mcp" ,
140+ json_response : bool = False ,
141+ stateless_http : bool = False ,
142+ warn_on_duplicate_resources : bool = True ,
143+ warn_on_duplicate_tools : bool = True ,
144+ warn_on_duplicate_prompts : bool = True ,
145+ dependencies : Collection [str ] = (),
146+ lifespan : Callable [[FastMCP [LifespanResultT ]], AbstractAsyncContextManager [LifespanResultT ]] | None = None ,
147+ auth : AuthSettings | None = None ,
148+ transport_security : TransportSecuritySettings | None = None ,
144149 ):
145- self .settings = Settings (** settings )
150+ self .settings = Settings (
151+ debug = debug ,
152+ log_level = log_level ,
153+ host = host ,
154+ port = port ,
155+ mount_path = mount_path ,
156+ sse_path = sse_path ,
157+ message_path = message_path ,
158+ streamable_http_path = streamable_http_path ,
159+ json_response = json_response ,
160+ stateless_http = stateless_http ,
161+ warn_on_duplicate_resources = warn_on_duplicate_resources ,
162+ warn_on_duplicate_tools = warn_on_duplicate_tools ,
163+ warn_on_duplicate_prompts = warn_on_duplicate_prompts ,
164+ dependencies = list (dependencies ),
165+ lifespan = lifespan ,
166+ auth = auth ,
167+ transport_security = transport_security ,
168+ )
146169
147170 self ._mcp_server = MCPServer (
148171 name = name or "FastMCP" ,
149172 instructions = instructions ,
150- lifespan = (lifespan_wrapper (self , self .settings .lifespan ) if self .settings .lifespan else default_lifespan ),
173+ # TODO(Marcelo): It seems there's a type mismatch between the lifespan type from an FastMCP and Server.
174+ # We need to create a Lifespan type that is a generic on the server type, like Starlette does.
175+ lifespan = (lifespan_wrapper (self , self .settings .lifespan ) if self .settings .lifespan else default_lifespan ), # type: ignore
151176 )
152177 self ._tool_manager = ToolManager (tools = tools , warn_on_duplicate_tools = self .settings .warn_on_duplicate_tools )
153178 self ._resource_manager = ResourceManager (warn_on_duplicate_resources = self .settings .warn_on_duplicate_resources )
@@ -257,7 +282,7 @@ async def list_tools(self) -> list[MCPTool]:
257282 for info in tools
258283 ]
259284
260- def get_context (self ) -> Context [ServerSession , object , Request ]:
285+ def get_context (self ) -> Context [ServerSession , LifespanResultT , Request ]:
261286 """
262287 Returns a Context object. Note that the context will only be valid
263288 during a request; outside a request, most methods will error.
0 commit comments