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
1512import pydantic_core
16- from pydantic import BaseModel , Field
13+ from pydantic import BaseModel
1714from pydantic .networks import AnyUrl
1815from pydantic_settings import BaseSettings , SettingsConfigDict
1916from starlette .applications import Starlette
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
@@ -79,58 +68,57 @@ class Settings(BaseSettings, Generic[LifespanResultT]):
7968 )
8069
8170 # Server settings
82- debug : bool = False
83- log_level : Literal ["DEBUG" , "INFO" , "WARNING" , "ERROR" , "CRITICAL" ] = "INFO"
71+ debug : bool
72+ log_level : Literal ["DEBUG" , "INFO" , "WARNING" , "ERROR" , "CRITICAL" ]
8473
8574 # HTTP settings
86- host : str = "127.0.0.1"
87- port : int = 8000
88- mount_path : str = "/" # Mount path (e.g. "/github", defaults to root path)
89- sse_path : str = "/sse"
90- message_path : str = "/messages/"
91- streamable_http_path : str = "/mcp"
75+ host : str
76+ port : int
77+ mount_path : str
78+ sse_path : str
79+ message_path : str
80+ streamable_http_path : str
9281
9382 # StreamableHTTP settings
94- json_response : bool = False
95- stateless_http : bool = False # If True, uses true stateless mode (new transport per request)
83+ json_response : bool
84+ stateless_http : bool
85+ """Define if the server should create a new transport per request."""
9686
9787 # resource settings
98- warn_on_duplicate_resources : bool = True
88+ warn_on_duplicate_resources : bool
9989
10090 # tool settings
101- warn_on_duplicate_tools : bool = True
91+ warn_on_duplicate_tools : bool
10292
10393 # prompt settings
104- warn_on_duplicate_prompts : bool = True
94+ warn_on_duplicate_prompts : bool
10595
106- dependencies : list [str ] = Field (
107- default_factory = list ,
108- description = "List of dependencies to install in the server environment" ,
109- )
96+ # TODO(Marcelo): Investigate if this is used. If it is, it's probably a good idea to remove it.
97+ dependencies : list [str ]
98+ """A list of dependencies to install in the server environment."""
11099
111- lifespan : Callable [[FastMCP ], AbstractAsyncContextManager [LifespanResultT ]] | None = Field (
112- None , description = "Lifespan context manager"
113- )
100+ lifespan : Callable [[FastMCP [LifespanResultT ]], AbstractAsyncContextManager [LifespanResultT ]] | None
101+ """A async context manager that will be called when the server is started."""
114102
115- auth : AuthSettings | None = None
103+ auth : AuthSettings | None
116104
117105 # Transport security settings (DNS rebinding protection)
118- transport_security : TransportSecuritySettings | None = None
106+ transport_security : TransportSecuritySettings | None
119107
120108
121109def lifespan_wrapper (
122- app : FastMCP ,
123- lifespan : Callable [[FastMCP ], AbstractAsyncContextManager [LifespanResultT ]],
124- ) -> Callable [[MCPServer [LifespanResultT , Request ]], AbstractAsyncContextManager [object ]]:
110+ app : FastMCP [ LifespanResultT ] ,
111+ lifespan : Callable [[FastMCP [ LifespanResultT ] ], AbstractAsyncContextManager [LifespanResultT ]],
112+ ) -> Callable [[MCPServer [LifespanResultT , Request ]], AbstractAsyncContextManager [LifespanResultT ]]:
125113 @asynccontextmanager
126- async def wrap (s : MCPServer [LifespanResultT , Request ]) -> AsyncIterator [object ]:
114+ async def wrap (_ : MCPServer [LifespanResultT , Request ]) -> AsyncIterator [LifespanResultT ]:
127115 async with lifespan (app ) as context :
128116 yield context
129117
130118 return wrap
131119
132120
133- class FastMCP :
121+ class FastMCP ( Generic [ LifespanResultT ]) :
134122 def __init__ (
135123 self ,
136124 name : str | None = None ,
@@ -140,14 +128,50 @@ def __init__(
140128 event_store : EventStore | None = None ,
141129 * ,
142130 tools : list [Tool ] | None = None ,
143- ** settings : Any ,
131+ debug : bool = False ,
132+ log_level : Literal ["DEBUG" , "INFO" , "WARNING" , "ERROR" , "CRITICAL" ] = "INFO" ,
133+ host : str = "127.0.0.1" ,
134+ port : int = 8000 ,
135+ mount_path : str = "/" ,
136+ sse_path : str = "/sse" ,
137+ message_path : str = "/messages/" ,
138+ streamable_http_path : str = "/mcp" ,
139+ json_response : bool = False ,
140+ stateless_http : bool = False ,
141+ warn_on_duplicate_resources : bool = True ,
142+ warn_on_duplicate_tools : bool = True ,
143+ warn_on_duplicate_prompts : bool = True ,
144+ dependencies : Collection [str ] = (),
145+ lifespan : Callable [[FastMCP [LifespanResultT ]], AbstractAsyncContextManager [LifespanResultT ]] | None = None ,
146+ auth : AuthSettings | None = None ,
147+ transport_security : TransportSecuritySettings | None = None ,
144148 ):
145- self .settings = Settings (** settings )
149+ self .settings = Settings (
150+ debug = debug ,
151+ log_level = log_level ,
152+ host = host ,
153+ port = port ,
154+ mount_path = mount_path ,
155+ sse_path = sse_path ,
156+ message_path = message_path ,
157+ streamable_http_path = streamable_http_path ,
158+ json_response = json_response ,
159+ stateless_http = stateless_http ,
160+ warn_on_duplicate_resources = warn_on_duplicate_resources ,
161+ warn_on_duplicate_tools = warn_on_duplicate_tools ,
162+ warn_on_duplicate_prompts = warn_on_duplicate_prompts ,
163+ dependencies = list (dependencies ),
164+ lifespan = lifespan ,
165+ auth = auth ,
166+ transport_security = transport_security ,
167+ )
146168
147169 self ._mcp_server = MCPServer (
148170 name = name or "FastMCP" ,
149171 instructions = instructions ,
150- lifespan = (lifespan_wrapper (self , self .settings .lifespan ) if self .settings .lifespan else default_lifespan ),
172+ # TODO(Marcelo): It seems there's a type mismatch between the lifespan type from an FastMCP and Server.
173+ # We need to create a Lifespan type that is a generic on the server type, like Starlette does.
174+ lifespan = (lifespan_wrapper (self , self .settings .lifespan ) if self .settings .lifespan else default_lifespan ), # type: ignore
151175 )
152176 self ._tool_manager = ToolManager (tools = tools , warn_on_duplicate_tools = self .settings .warn_on_duplicate_tools )
153177 self ._resource_manager = ResourceManager (warn_on_duplicate_resources = self .settings .warn_on_duplicate_resources )
@@ -257,7 +281,7 @@ async def list_tools(self) -> list[MCPTool]:
257281 for info in tools
258282 ]
259283
260- def get_context (self ) -> Context [ServerSession , object , Request ]:
284+ def get_context (self ) -> Context [ServerSession , LifespanResultT , Request ]:
261285 """
262286 Returns a Context object. Note that the context will only be valid
263287 during a request; outside a request, most methods will error.
0 commit comments