zzstoatzz commited on
Commit
d09d7f6
·
1 Parent(s): 5359040

strict typing for `server.py`

Browse files
pyproject.toml CHANGED
@@ -96,6 +96,7 @@ reportMissingTypeStubs = false
96
  useLibraryCodeForTypes = true
97
  venvPath = "."
98
  venv = ".venv"
 
99
 
100
  [tool.ruff.lint]
101
  extend-select = ["I", "UP"]
 
96
  useLibraryCodeForTypes = true
97
  venvPath = "."
98
  venv = ".venv"
99
+ strict = ["src/fastmcp/server/server.py"]
100
 
101
  [tool.ruff.lint]
102
  extend-select = ["I", "UP"]
src/fastmcp/server/http.py CHANGED
@@ -10,9 +10,15 @@ from mcp.server.auth.middleware.bearer_auth import (
10
  BearerAuthBackend,
11
  RequireAuthMiddleware,
12
  )
13
- from mcp.server.auth.provider import OAuthAuthorizationServerProvider
 
 
 
 
 
14
  from mcp.server.auth.routes import create_auth_routes
15
  from mcp.server.auth.settings import AuthSettings
 
16
  from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
17
  from starlette.applications import Starlette
18
  from starlette.middleware import Middleware
@@ -30,6 +36,7 @@ if TYPE_CHECKING:
30
 
31
  logger = get_logger(__name__)
32
 
 
33
  _current_http_request: ContextVar[Request | None] = ContextVar(
34
  "http_request",
35
  default=None,
@@ -62,7 +69,10 @@ class RequestContextMiddleware:
62
 
63
 
64
  def setup_auth_middleware_and_routes(
65
- auth_server_provider: OAuthAuthorizationServerProvider | None,
 
 
 
66
  auth_settings: AuthSettings | None,
67
  ) -> tuple[list[Middleware], list[BaseRoute], list[str]]:
68
  """Set up authentication middleware and routes if auth is enabled.
@@ -136,10 +146,13 @@ def create_base_app(
136
 
137
 
138
  def create_sse_app(
139
- server: FastMCP,
140
  message_path: str,
141
  sse_path: str,
142
- auth_server_provider: OAuthAuthorizationServerProvider | None = None,
 
 
 
143
  auth_settings: AuthSettings | None = None,
144
  debug: bool = False,
145
  routes: list[BaseRoute] | None = None,
@@ -236,10 +249,13 @@ def create_sse_app(
236
 
237
 
238
  def create_streamable_http_app(
239
- server: FastMCP,
240
  streamable_http_path: str,
241
  event_store: None = None,
242
- auth_server_provider: OAuthAuthorizationServerProvider | None = None,
 
 
 
243
  auth_settings: AuthSettings | None = None,
244
  json_response: bool = False,
245
  stateless_http: bool = False,
 
10
  BearerAuthBackend,
11
  RequireAuthMiddleware,
12
  )
13
+ from mcp.server.auth.provider import (
14
+ AccessTokenT,
15
+ AuthorizationCodeT,
16
+ OAuthAuthorizationServerProvider,
17
+ RefreshTokenT,
18
+ )
19
  from mcp.server.auth.routes import create_auth_routes
20
  from mcp.server.auth.settings import AuthSettings
21
+ from mcp.server.lowlevel.server import LifespanResultT
22
  from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
23
  from starlette.applications import Starlette
24
  from starlette.middleware import Middleware
 
36
 
37
  logger = get_logger(__name__)
38
 
39
+
40
  _current_http_request: ContextVar[Request | None] = ContextVar(
41
  "http_request",
42
  default=None,
 
69
 
70
 
71
  def setup_auth_middleware_and_routes(
72
+ auth_server_provider: OAuthAuthorizationServerProvider[
73
+ AuthorizationCodeT, RefreshTokenT, AccessTokenT
74
+ ]
75
+ | None,
76
  auth_settings: AuthSettings | None,
77
  ) -> tuple[list[Middleware], list[BaseRoute], list[str]]:
78
  """Set up authentication middleware and routes if auth is enabled.
 
146
 
147
 
148
  def create_sse_app(
149
+ server: FastMCP[LifespanResultT],
150
  message_path: str,
151
  sse_path: str,
152
+ auth_server_provider: OAuthAuthorizationServerProvider[
153
+ AuthorizationCodeT, RefreshTokenT, AccessTokenT
154
+ ]
155
+ | None = None,
156
  auth_settings: AuthSettings | None = None,
157
  debug: bool = False,
158
  routes: list[BaseRoute] | None = None,
 
249
 
250
 
251
  def create_streamable_http_app(
252
+ server: FastMCP[LifespanResultT],
253
  streamable_http_path: str,
254
  event_store: None = None,
255
+ auth_server_provider: OAuthAuthorizationServerProvider[
256
+ AuthorizationCodeT, RefreshTokenT, AccessTokenT
257
+ ]
258
+ | None = None,
259
  auth_settings: AuthSettings | None = None,
260
  json_response: bool = False,
261
  stateless_http: bool = False,
src/fastmcp/server/server.py CHANGED
@@ -66,7 +66,7 @@ DuplicateBehavior = Literal["warn", "error", "replace", "ignore"]
66
 
67
 
68
  @asynccontextmanager
69
- async def default_lifespan(server: FastMCP) -> AsyncIterator[Any]:
70
  """Default lifespan context manager that does nothing.
71
 
72
  Args:
@@ -79,8 +79,10 @@ async def default_lifespan(server: FastMCP) -> AsyncIterator[Any]:
79
 
80
 
81
  def _lifespan_wrapper(
82
- app: FastMCP,
83
- lifespan: Callable[[FastMCP], AbstractAsyncContextManager[LifespanResultT]],
 
 
84
  ) -> Callable[
85
  [MCPServer[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT]
86
  ]:
@@ -226,7 +228,7 @@ class FastMCP(Generic[LifespanResultT]):
226
  async def get_tools(self) -> dict[str, Tool]:
227
  """Get all registered tools, indexed by registered key."""
228
  if (tools := self._cache.get("tools")) is self._cache.NOT_FOUND:
229
- tools = {}
230
  for server in self._mounted_servers.values():
231
  server_tools = await server.get_tools()
232
  tools.update(server_tools)
@@ -237,7 +239,7 @@ class FastMCP(Generic[LifespanResultT]):
237
  async def get_resources(self) -> dict[str, Resource]:
238
  """Get all registered resources, indexed by registered key."""
239
  if (resources := self._cache.get("resources")) is self._cache.NOT_FOUND:
240
- resources = {}
241
  for server in self._mounted_servers.values():
242
  server_resources = await server.get_resources()
243
  resources.update(server_resources)
@@ -250,7 +252,7 @@ class FastMCP(Generic[LifespanResultT]):
250
  if (
251
  templates := self._cache.get("resource_templates")
252
  ) is self._cache.NOT_FOUND:
253
- templates = {}
254
  for server in self._mounted_servers.values():
255
  server_templates = await server.get_resource_templates()
256
  templates.update(server_templates)
@@ -263,7 +265,7 @@ class FastMCP(Generic[LifespanResultT]):
263
  List all available prompts.
264
  """
265
  if (prompts := self._cache.get("prompts")) is self._cache.NOT_FOUND:
266
- prompts = {}
267
  for server in self._mounted_servers.values():
268
  server_prompts = await server.get_prompts()
269
  prompts.update(server_prompts)
@@ -741,7 +743,7 @@ class FastMCP(Generic[LifespanResultT]):
741
  port: int | None = None,
742
  log_level: str | None = None,
743
  path: str | None = None,
744
- uvicorn_config: dict | None = None,
745
  middleware: list[Middleware] | None = None,
746
  ) -> None:
747
  """Run the server using HTTP transport.
@@ -778,7 +780,7 @@ class FastMCP(Generic[LifespanResultT]):
778
  log_level: str | None = None,
779
  path: str | None = None,
780
  message_path: str | None = None,
781
- uvicorn_config: dict | None = None,
782
  ) -> None:
783
  """Run the server using SSE transport."""
784
 
@@ -900,7 +902,7 @@ class FastMCP(Generic[LifespanResultT]):
900
  port: int | None = None,
901
  log_level: str | None = None,
902
  path: str | None = None,
903
- uvicorn_config: dict | None = None,
904
  ) -> None:
905
  # Deprecated since 2.3.2
906
  warnings.warn(
@@ -1127,7 +1129,7 @@ class MountedServer:
1127
  def __init__(
1128
  self,
1129
  prefix: str,
1130
- server: FastMCP,
1131
  tool_separator: str | None = None,
1132
  resource_separator: str | None = None,
1133
  prompt_separator: str | None = None,
 
66
 
67
 
68
  @asynccontextmanager
69
+ async def default_lifespan(server: FastMCP[LifespanResultT]) -> AsyncIterator[Any]:
70
  """Default lifespan context manager that does nothing.
71
 
72
  Args:
 
79
 
80
 
81
  def _lifespan_wrapper(
82
+ app: FastMCP[LifespanResultT],
83
+ lifespan: Callable[
84
+ [FastMCP[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT]
85
+ ],
86
  ) -> Callable[
87
  [MCPServer[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT]
88
  ]:
 
228
  async def get_tools(self) -> dict[str, Tool]:
229
  """Get all registered tools, indexed by registered key."""
230
  if (tools := self._cache.get("tools")) is self._cache.NOT_FOUND:
231
+ tools: dict[str, Tool] = {}
232
  for server in self._mounted_servers.values():
233
  server_tools = await server.get_tools()
234
  tools.update(server_tools)
 
239
  async def get_resources(self) -> dict[str, Resource]:
240
  """Get all registered resources, indexed by registered key."""
241
  if (resources := self._cache.get("resources")) is self._cache.NOT_FOUND:
242
+ resources: dict[str, Resource] = {}
243
  for server in self._mounted_servers.values():
244
  server_resources = await server.get_resources()
245
  resources.update(server_resources)
 
252
  if (
253
  templates := self._cache.get("resource_templates")
254
  ) is self._cache.NOT_FOUND:
255
+ templates: dict[str, ResourceTemplate] = {}
256
  for server in self._mounted_servers.values():
257
  server_templates = await server.get_resource_templates()
258
  templates.update(server_templates)
 
265
  List all available prompts.
266
  """
267
  if (prompts := self._cache.get("prompts")) is self._cache.NOT_FOUND:
268
+ prompts: dict[str, Prompt] = {}
269
  for server in self._mounted_servers.values():
270
  server_prompts = await server.get_prompts()
271
  prompts.update(server_prompts)
 
743
  port: int | None = None,
744
  log_level: str | None = None,
745
  path: str | None = None,
746
+ uvicorn_config: dict[str, Any] | None = None,
747
  middleware: list[Middleware] | None = None,
748
  ) -> None:
749
  """Run the server using HTTP transport.
 
780
  log_level: str | None = None,
781
  path: str | None = None,
782
  message_path: str | None = None,
783
+ uvicorn_config: dict[str, Any] | None = None,
784
  ) -> None:
785
  """Run the server using SSE transport."""
786
 
 
902
  port: int | None = None,
903
  log_level: str | None = None,
904
  path: str | None = None,
905
+ uvicorn_config: dict[str, Any] | None = None,
906
  ) -> None:
907
  # Deprecated since 2.3.2
908
  warnings.warn(
 
1129
  def __init__(
1130
  self,
1131
  prefix: str,
1132
+ server: FastMCP[LifespanResultT],
1133
  tool_separator: str | None = None,
1134
  resource_separator: str | None = None,
1135
  prompt_separator: str | None = None,