fastmcp 2.3.1__py3-none-any.whl → 2.3.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fastmcp/cli/cli.py CHANGED
@@ -327,14 +327,14 @@ def run(
327
327
  typer.Option(
328
328
  "--transport",
329
329
  "-t",
330
- help="Transport protocol to use (stdio or sse)",
330
+ help="Transport protocol to use (stdio, streamable-http, or sse)",
331
331
  ),
332
332
  ] = None,
333
333
  host: Annotated[
334
334
  str | None,
335
335
  typer.Option(
336
336
  "--host",
337
- help="Host to bind to when using sse transport (default: 127.0.0.1)",
337
+ help="Host to bind to when using http transport (default: 127.0.0.1)",
338
338
  ),
339
339
  ] = None,
340
340
  port: Annotated[
@@ -342,7 +342,7 @@ def run(
342
342
  typer.Option(
343
343
  "--port",
344
344
  "-p",
345
- help="Port to bind to when using sse transport (default: 8000)",
345
+ help="Port to bind to when using http transport (default: 8000)",
346
346
  ),
347
347
  ] = None,
348
348
  log_level: Annotated[
@@ -350,20 +350,19 @@ def run(
350
350
  typer.Option(
351
351
  "--log-level",
352
352
  "-l",
353
- help="Log level for sse transport (DEBUG, INFO, WARNING, ERROR, CRITICAL)",
353
+ help="Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)",
354
354
  ),
355
355
  ] = None,
356
356
  ) -> None:
357
357
  """Run a MCP server.
358
358
 
359
- The server can be specified in two ways:\n
359
+ The server can be specified in two ways:
360
360
  1. Module approach: server.py - runs the module directly, expecting a server.run() call.\n
361
361
  2. Import approach: server.py:app - imports and runs the specified server object.\n\n
362
362
 
363
363
  Note: This command runs the server directly. You are responsible for ensuring
364
- all dependencies are available.\n
365
- For dependency management, use `mcp install` or `mcp dev` instead.
366
- """ # noqa: E501
364
+ all dependencies are available.
365
+ """
367
366
  file, server_object = _parse_file_path(file_spec)
368
367
 
369
368
  logger.debug(
fastmcp/server/http.py CHANGED
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from collections.abc import AsyncGenerator, Callable, Generator
4
4
  from contextlib import asynccontextmanager, contextmanager
5
5
  from contextvars import ContextVar
6
- from typing import TYPE_CHECKING, cast
6
+ from typing import TYPE_CHECKING
7
7
 
8
8
  from mcp.server.auth.middleware.auth_context import AuthContextMiddleware
9
9
  from mcp.server.auth.middleware.bearer_auth import (
@@ -19,7 +19,7 @@ from starlette.middleware import Middleware
19
19
  from starlette.middleware.authentication import AuthenticationMiddleware
20
20
  from starlette.requests import Request
21
21
  from starlette.responses import Response
22
- from starlette.routing import Mount, Route
22
+ from starlette.routing import BaseRoute, Mount, Route
23
23
  from starlette.types import Receive, Scope, Send
24
24
 
25
25
  from fastmcp.low_level.sse_server_transport import SseServerTransport
@@ -64,7 +64,7 @@ class RequestContextMiddleware:
64
64
  def setup_auth_middleware_and_routes(
65
65
  auth_server_provider: OAuthAuthorizationServerProvider | None,
66
66
  auth_settings: AuthSettings | None,
67
- ) -> tuple[list[Middleware], list[Route | Mount], list[str]]:
67
+ ) -> tuple[list[Middleware], list[BaseRoute], list[str]]:
68
68
  """Set up authentication middleware and routes if auth is enabled.
69
69
 
70
70
  Args:
@@ -75,7 +75,7 @@ def setup_auth_middleware_and_routes(
75
75
  Tuple of (middleware, auth_routes, required_scopes)
76
76
  """
77
77
  middleware: list[Middleware] = []
78
- auth_routes: list[Route | Mount] = []
78
+ auth_routes: list[BaseRoute] = []
79
79
  required_scopes: list[str] = []
80
80
 
81
81
  if auth_server_provider:
@@ -108,7 +108,7 @@ def setup_auth_middleware_and_routes(
108
108
 
109
109
 
110
110
  def create_base_app(
111
- routes: list[Route | Mount],
111
+ routes: list[BaseRoute],
112
112
  middleware: list[Middleware],
113
113
  debug: bool = False,
114
114
  lifespan: Callable | None = None,
@@ -142,7 +142,8 @@ def create_sse_app(
142
142
  auth_server_provider: OAuthAuthorizationServerProvider | None = None,
143
143
  auth_settings: AuthSettings | None = None,
144
144
  debug: bool = False,
145
- additional_routes: list[Route] | list[Mount] | list[Route | Mount] | None = None,
145
+ routes: list[BaseRoute] | None = None,
146
+ middleware: list[Middleware] | None = None,
146
147
  ) -> Starlette:
147
148
  """Return an instance of the SSE server app.
148
149
 
@@ -153,11 +154,15 @@ def create_sse_app(
153
154
  auth_server_provider: Optional auth provider
154
155
  auth_settings: Optional auth settings
155
156
  debug: Whether to enable debug mode
156
- additional_routes: Optional list of custom routes
157
-
157
+ routes: Optional list of custom routes
158
+ middleware: Optional list of middleware
158
159
  Returns:
159
160
  A Starlette application with RequestContextMiddleware
160
161
  """
162
+
163
+ server_routes: list[BaseRoute] = []
164
+ server_middleware: list[Middleware] = []
165
+
161
166
  # Set up SSE transport
162
167
  sse = SseServerTransport(message_path)
163
168
 
@@ -172,24 +177,24 @@ def create_sse_app(
172
177
  return Response()
173
178
 
174
179
  # Get auth middleware and routes
175
- middleware, auth_routes, required_scopes = setup_auth_middleware_and_routes(
180
+ auth_middleware, auth_routes, required_scopes = setup_auth_middleware_and_routes(
176
181
  auth_server_provider, auth_settings
177
182
  )
178
183
 
179
- # Initialize routes with auth routes
180
- routes: list[Route | Mount] = auth_routes.copy()
184
+ server_routes.extend(auth_routes)
185
+ server_middleware.extend(auth_middleware)
181
186
 
182
187
  # Add SSE routes with or without auth
183
188
  if auth_server_provider:
184
189
  # Auth is enabled, wrap endpoints with RequireAuthMiddleware
185
- routes.append(
190
+ server_routes.append(
186
191
  Route(
187
192
  sse_path,
188
193
  endpoint=RequireAuthMiddleware(handle_sse, required_scopes),
189
194
  methods=["GET"],
190
195
  )
191
196
  )
192
- routes.append(
197
+ server_routes.append(
193
198
  Mount(
194
199
  message_path,
195
200
  app=RequireAuthMiddleware(sse.handle_post_message, required_scopes),
@@ -200,14 +205,14 @@ def create_sse_app(
200
205
  async def sse_endpoint(request: Request) -> Response:
201
206
  return await handle_sse(request.scope, request.receive, request._send) # type: ignore[reportPrivateUsage]
202
207
 
203
- routes.append(
208
+ server_routes.append(
204
209
  Route(
205
210
  sse_path,
206
211
  endpoint=sse_endpoint,
207
212
  methods=["GET"],
208
213
  )
209
214
  )
210
- routes.append(
215
+ server_routes.append(
211
216
  Mount(
212
217
  message_path,
213
218
  app=sse.handle_post_message,
@@ -215,13 +220,17 @@ def create_sse_app(
215
220
  )
216
221
 
217
222
  # Add custom routes with lowest precedence
218
- if additional_routes:
219
- routes.extend(cast(list[Route | Mount], additional_routes))
223
+ if routes:
224
+ server_routes.extend(routes)
225
+
226
+ # Add middleware
227
+ if middleware:
228
+ server_middleware.extend(middleware)
220
229
 
221
230
  # Create and return the app
222
231
  return create_base_app(
223
- routes=routes,
224
- middleware=middleware,
232
+ routes=server_routes,
233
+ middleware=server_middleware,
225
234
  debug=debug,
226
235
  )
227
236
 
@@ -235,7 +244,8 @@ def create_streamable_http_app(
235
244
  json_response: bool = False,
236
245
  stateless_http: bool = False,
237
246
  debug: bool = False,
238
- additional_routes: list[Route] | list[Mount] | list[Route | Mount] | None = None,
247
+ routes: list[BaseRoute] | None = None,
248
+ middleware: list[Middleware] | None = None,
239
249
  ) -> Starlette:
240
250
  """Return an instance of the StreamableHTTP server app.
241
251
 
@@ -248,11 +258,15 @@ def create_streamable_http_app(
248
258
  json_response: Whether to use JSON response format
249
259
  stateless_http: Whether to use stateless mode (new transport per request)
250
260
  debug: Whether to enable debug mode
251
- additional_routes: Optional list of custom routes
261
+ routes: Optional list of custom routes
262
+ middleware: Optional list of middleware
252
263
 
253
264
  Returns:
254
265
  A Starlette application with StreamableHTTP support
255
266
  """
267
+ server_routes: list[BaseRoute] = []
268
+ server_middleware: list[Middleware] = []
269
+
256
270
  # Create session manager using the provided event store
257
271
  session_manager = StreamableHTTPSessionManager(
258
272
  app=server._mcp_server,
@@ -268,17 +282,17 @@ def create_streamable_http_app(
268
282
  await session_manager.handle_request(scope, receive, send)
269
283
 
270
284
  # Get auth middleware and routes
271
- middleware, auth_routes, required_scopes = setup_auth_middleware_and_routes(
285
+ auth_middleware, auth_routes, required_scopes = setup_auth_middleware_and_routes(
272
286
  auth_server_provider, auth_settings
273
287
  )
274
288
 
275
- # Initialize routes with auth routes
276
- routes: list[Route | Mount] = auth_routes.copy()
289
+ server_routes.extend(auth_routes)
290
+ server_middleware.extend(auth_middleware)
277
291
 
278
292
  # Add StreamableHTTP routes with or without auth
279
293
  if auth_server_provider:
280
294
  # Auth is enabled, wrap endpoint with RequireAuthMiddleware
281
- routes.append(
295
+ server_routes.append(
282
296
  Mount(
283
297
  streamable_http_path,
284
298
  app=RequireAuthMiddleware(handle_streamable_http, required_scopes),
@@ -286,7 +300,7 @@ def create_streamable_http_app(
286
300
  )
287
301
  else:
288
302
  # No auth required
289
- routes.append(
303
+ server_routes.append(
290
304
  Mount(
291
305
  streamable_http_path,
292
306
  app=handle_streamable_http,
@@ -294,8 +308,12 @@ def create_streamable_http_app(
294
308
  )
295
309
 
296
310
  # Add custom routes with lowest precedence
297
- if additional_routes:
298
- routes.extend(cast(list[Route | Mount], additional_routes))
311
+ if routes:
312
+ server_routes.extend(routes)
313
+
314
+ # Add middleware
315
+ if middleware:
316
+ server_middleware.extend(middleware)
299
317
 
300
318
  # Create a lifespan manager to start and stop the session manager
301
319
  @asynccontextmanager
@@ -305,8 +323,8 @@ def create_streamable_http_app(
305
323
 
306
324
  # Create and return the app with lifespan
307
325
  return create_base_app(
308
- routes=routes,
309
- middleware=middleware,
326
+ routes=server_routes,
327
+ middleware=server_middleware,
310
328
  debug=debug,
311
329
  lifespan=lifespan,
312
330
  )
fastmcp/server/server.py CHANGED
@@ -3,6 +3,8 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import datetime
6
+ import inspect
7
+ import warnings
6
8
  from collections.abc import AsyncIterator, Awaitable, Callable
7
9
  from contextlib import (
8
10
  AbstractAsyncContextManager,
@@ -35,9 +37,10 @@ from mcp.types import ResourceTemplate as MCPResourceTemplate
35
37
  from mcp.types import Tool as MCPTool
36
38
  from pydantic import AnyUrl
37
39
  from starlette.applications import Starlette
40
+ from starlette.middleware import Middleware
38
41
  from starlette.requests import Request
39
42
  from starlette.responses import Response
40
- from starlette.routing import Route
43
+ from starlette.routing import BaseRoute, Route
41
44
 
42
45
  import fastmcp.server
43
46
  import fastmcp.settings
@@ -147,7 +150,7 @@ class FastMCP(Generic[LifespanResultT]):
147
150
  )
148
151
  self._auth_server_provider = auth_server_provider
149
152
 
150
- self._additional_http_routes: list[Route] = []
153
+ self._additional_http_routes: list[BaseRoute] = []
151
154
  self.dependencies = self.settings.dependencies
152
155
 
153
156
  # Set up MCP protocol handlers
@@ -169,7 +172,7 @@ class FastMCP(Generic[LifespanResultT]):
169
172
 
170
173
  async def run_async(
171
174
  self,
172
- transport: Literal["stdio", "sse", "streamable-http"] | None = None,
175
+ transport: Literal["stdio", "streamable-http", "sse"] | None = None,
173
176
  **transport_kwargs: Any,
174
177
  ) -> None:
175
178
  """Run the FastMCP server asynchronously.
@@ -179,19 +182,21 @@ class FastMCP(Generic[LifespanResultT]):
179
182
  """
180
183
  if transport is None:
181
184
  transport = "stdio"
182
- if transport not in ["stdio", "sse", "streamable-http"]:
185
+ if transport not in ["stdio", "streamable-http", "sse"]:
183
186
  raise ValueError(f"Unknown transport: {transport}")
184
187
 
185
188
  if transport == "stdio":
186
189
  await self.run_stdio_async(**transport_kwargs)
190
+ elif transport == "streamable-http":
191
+ await self.run_http_async(transport="streamable-http", **transport_kwargs)
187
192
  elif transport == "sse":
188
- await self.run_sse_async(**transport_kwargs)
189
- else: # transport == "streamable-http"
190
- await self.run_streamable_http_async(**transport_kwargs)
193
+ await self.run_http_async(transport="sse", **transport_kwargs)
194
+ else:
195
+ raise ValueError(f"Unknown transport: {transport}")
191
196
 
192
197
  def run(
193
198
  self,
194
- transport: Literal["stdio", "sse", "streamable-http"] | None = None,
199
+ transport: Literal["stdio", "streamable-http", "sse"] | None = None,
195
200
  **transport_kwargs: Any,
196
201
  ) -> None:
197
202
  """Run the FastMCP server. Note this is a synchronous function.
@@ -713,22 +718,31 @@ class FastMCP(Generic[LifespanResultT]):
713
718
  self._mcp_server.create_initialization_options(),
714
719
  )
715
720
 
716
- async def run_sse_async(
721
+ async def run_http_async(
717
722
  self,
723
+ transport: Literal["streamable-http", "sse"] = "streamable-http",
718
724
  host: str | None = None,
719
725
  port: int | None = None,
720
726
  log_level: str | None = None,
721
727
  path: str | None = None,
722
- message_path: str | None = None,
723
728
  uvicorn_config: dict | None = None,
724
729
  ) -> None:
725
- """Run the server using SSE transport."""
730
+ """Run the server using HTTP transport.
731
+
732
+ Args:
733
+ transport: Transport protocol to use - either "streamable-http" (default) or "sse"
734
+ host: Host address to bind to (defaults to settings.host)
735
+ port: Port to bind to (defaults to settings.port)
736
+ log_level: Log level for the server (defaults to settings.log_level)
737
+ path: Path for the endpoint (defaults to settings.streamable_http_path or settings.sse_path)
738
+ uvicorn_config: Additional configuration for the Uvicorn server
739
+ """
726
740
  uvicorn_config = uvicorn_config or {}
727
- # the SSE app hangs even when a signal is sent, so we disable the
728
- # timeout to make it possible to close immediately. see
729
- # https://github.com/jlowin/fastmcp/issues/296
730
741
  uvicorn_config.setdefault("timeout_graceful_shutdown", 0)
731
- app = self.sse_app(path=path, message_path=message_path)
742
+ # lifespan is required for streamable http
743
+ uvicorn_config["lifespan"] = "on"
744
+
745
+ app = self.http_app(path=path, transport=transport)
732
746
 
733
747
  config = uvicorn.Config(
734
748
  app,
@@ -740,12 +754,58 @@ class FastMCP(Generic[LifespanResultT]):
740
754
  server = uvicorn.Server(config)
741
755
  await server.serve()
742
756
 
757
+ async def run_sse_async(
758
+ self,
759
+ host: str | None = None,
760
+ port: int | None = None,
761
+ log_level: str | None = None,
762
+ path: str | None = None,
763
+ message_path: str | None = None,
764
+ uvicorn_config: dict | None = None,
765
+ ) -> None:
766
+ """Run the server using SSE transport."""
767
+ warnings.warn(
768
+ inspect.cleandoc(
769
+ """
770
+ The run_sse_async method is deprecated. Use run_http_async for a
771
+ modern (non-SSE) alternative, or create an SSE app with
772
+ `fastmcp.server.http.create_sse_app` and run it directly.
773
+ """
774
+ ),
775
+ DeprecationWarning,
776
+ )
777
+ await self.run_http_async(
778
+ transport="sse",
779
+ host=host,
780
+ port=port,
781
+ log_level=log_level,
782
+ path=path,
783
+ uvicorn_config=uvicorn_config,
784
+ )
785
+
743
786
  def sse_app(
744
787
  self,
745
788
  path: str | None = None,
746
789
  message_path: str | None = None,
790
+ middleware: list[Middleware] | None = None,
747
791
  ) -> Starlette:
748
- """Return an instance of the SSE server app."""
792
+ """
793
+ Create a Starlette app for the SSE server.
794
+
795
+ Args:
796
+ path: The path to the SSE endpoint
797
+ message_path: The path to the message endpoint
798
+ middleware: A list of middleware to apply to the app
799
+ """
800
+ warnings.warn(
801
+ inspect.cleandoc(
802
+ """
803
+ The sse_app method is deprecated. Use http_app as a modern (non-SSE)
804
+ alternative, or call `fastmcp.server.http.create_sse_app` directly.
805
+ """
806
+ ),
807
+ DeprecationWarning,
808
+ )
749
809
  return create_sse_app(
750
810
  server=self,
751
811
  message_path=message_path or self.settings.message_path,
@@ -753,24 +813,70 @@ class FastMCP(Generic[LifespanResultT]):
753
813
  auth_server_provider=self._auth_server_provider,
754
814
  auth_settings=self.settings.auth,
755
815
  debug=self.settings.debug,
756
- additional_routes=self._additional_http_routes,
816
+ routes=self._additional_http_routes,
817
+ middleware=middleware,
757
818
  )
758
819
 
759
- def streamable_http_app(self, path: str | None = None) -> Starlette:
760
- """Return an instance of the StreamableHTTP server app."""
761
- from fastmcp.server.http import create_streamable_http_app
820
+ def streamable_http_app(
821
+ self,
822
+ path: str | None = None,
823
+ middleware: list[Middleware] | None = None,
824
+ ) -> Starlette:
825
+ """
826
+ Create a Starlette app for the StreamableHTTP server.
762
827
 
763
- return create_streamable_http_app(
764
- server=self,
765
- streamable_http_path=path or self.settings.streamable_http_path,
766
- event_store=None,
767
- auth_server_provider=self._auth_server_provider,
768
- auth_settings=self.settings.auth,
769
- json_response=self.settings.json_response,
770
- stateless_http=self.settings.stateless_http,
771
- debug=self.settings.debug,
772
- additional_routes=self._additional_http_routes,
828
+ Args:
829
+ path: The path to the StreamableHTTP endpoint
830
+ middleware: A list of middleware to apply to the app
831
+ """
832
+ warnings.warn(
833
+ "The streamable_http_app method is deprecated. Use http_app() instead.",
834
+ DeprecationWarning,
773
835
  )
836
+ return self.http_app(path=path, middleware=middleware)
837
+
838
+ def http_app(
839
+ self,
840
+ path: str | None = None,
841
+ middleware: list[Middleware] | None = None,
842
+ transport: Literal["streamable-http", "sse"] = "streamable-http",
843
+ ) -> Starlette:
844
+ """Create a Starlette app using the specified HTTP transport.
845
+
846
+ Args:
847
+ path: The path for the HTTP endpoint
848
+ middleware: A list of middleware to apply to the app
849
+ transport: Transport protocol to use - either "streamable-http" (default) or "sse"
850
+
851
+ Returns:
852
+ A Starlette application configured with the specified transport
853
+ """
854
+ from fastmcp.server.http import create_streamable_http_app
855
+
856
+ if transport == "streamable-http":
857
+ return create_streamable_http_app(
858
+ server=self,
859
+ streamable_http_path=path or self.settings.streamable_http_path,
860
+ event_store=None,
861
+ auth_server_provider=self._auth_server_provider,
862
+ auth_settings=self.settings.auth,
863
+ json_response=self.settings.json_response,
864
+ stateless_http=self.settings.stateless_http,
865
+ debug=self.settings.debug,
866
+ routes=self._additional_http_routes,
867
+ middleware=middleware,
868
+ )
869
+ elif transport == "sse":
870
+ return create_sse_app(
871
+ server=self,
872
+ message_path=self.settings.message_path,
873
+ sse_path=path or self.settings.sse_path,
874
+ auth_server_provider=self._auth_server_provider,
875
+ auth_settings=self.settings.auth,
876
+ debug=self.settings.debug,
877
+ routes=self._additional_http_routes,
878
+ middleware=middleware,
879
+ )
774
880
 
775
881
  async def run_streamable_http_async(
776
882
  self,
@@ -780,23 +886,18 @@ class FastMCP(Generic[LifespanResultT]):
780
886
  path: str | None = None,
781
887
  uvicorn_config: dict | None = None,
782
888
  ) -> None:
783
- """Run the server using StreamableHTTP transport."""
784
- uvicorn_config = uvicorn_config or {}
785
- uvicorn_config.setdefault("timeout_graceful_shutdown", 0)
786
-
787
- app = self.streamable_http_app(path=path)
788
-
789
- config = uvicorn.Config(
790
- app,
791
- host=host or self.settings.host,
792
- port=port or self.settings.port,
793
- log_level=log_level or self.settings.log_level.lower(),
794
- # lifespan is required for streamable http
795
- lifespan="on",
796
- **uvicorn_config,
889
+ warnings.warn(
890
+ "The run_streamable_http_async method is deprecated. Use run_http_async instead.",
891
+ DeprecationWarning,
892
+ )
893
+ await self.run_http_async(
894
+ transport="streamable-http",
895
+ host=host,
896
+ port=port,
897
+ log_level=log_level,
898
+ path=path,
899
+ uvicorn_config=uvicorn_config,
797
900
  )
798
- server = uvicorn.Server(config)
799
- await server.serve()
800
901
 
801
902
  def mount(
802
903
  self,
@@ -993,11 +1094,13 @@ class FastMCP(Generic[LifespanResultT]):
993
1094
 
994
1095
  def _validate_resource_prefix(prefix: str) -> None:
995
1096
  valid_resource = "resource://path/to/resource"
1097
+ test_case = f"{prefix}{valid_resource}"
996
1098
  try:
997
- AnyUrl(f"{prefix}{valid_resource}")
1099
+ AnyUrl(test_case)
998
1100
  except pydantic.ValidationError as e:
999
1101
  raise ValueError(
1000
- f"Resource prefix or separator would result in an invalid resource URI: {e}"
1102
+ "Resource prefix or separator would result in an "
1103
+ f"invalid resource URI (test case was {test_case!r}): {e}"
1001
1104
  )
1002
1105
 
1003
1106
 
@@ -55,7 +55,7 @@ def temporary_settings(**kwargs: Any):
55
55
  def _run_server(mcp_server: FastMCP, transport: Literal["sse"], port: int) -> None:
56
56
  # Some Starlette apps are not pickleable, so we need to create them here based on the indicated transport
57
57
  if transport == "sse":
58
- app = mcp_server.sse_app()
58
+ app = mcp_server.http_app(transport="sse")
59
59
  else:
60
60
  raise ValueError(f"Invalid transport: {transport}")
61
61
  uvicorn_server = uvicorn.Server(
@@ -71,7 +71,7 @@ def _run_server(mcp_server: FastMCP, transport: Literal["sse"], port: int) -> No
71
71
 
72
72
  @contextmanager
73
73
  def run_server_in_process(
74
- server_fn: Callable[[str, int], None],
74
+ server_fn: Callable[[str, int], None], *args
75
75
  ) -> Generator[str, None, None]:
76
76
  """
77
77
  Context manager that runs a Starlette app in a separate process and returns the
@@ -88,7 +88,9 @@ def run_server_in_process(
88
88
  s.bind((host, 0))
89
89
  port = s.getsockname()[1]
90
90
 
91
- proc = multiprocessing.Process(target=server_fn, args=(host, port), daemon=True)
91
+ proc = multiprocessing.Process(
92
+ target=server_fn, args=(host, port, *args), daemon=True
93
+ )
92
94
  proc.start()
93
95
 
94
96
  # Wait for server to be running
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastmcp
3
- Version: 2.3.1
3
+ Version: 2.3.3
4
4
  Summary: The fast, Pythonic way to build MCP servers.
5
5
  Project-URL: Homepage, https://gofastmcp.com
6
6
  Project-URL: Repository, https://github.com/jlowin/fastmcp
@@ -44,7 +44,7 @@ Description-Content-Type: text/markdown
44
44
  > [!NOTE]
45
45
  > #### FastMCP 2.0 & The Official MCP SDK
46
46
  >
47
- > Recognize the `FastMCP` name? You might have used the version integrated into the [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk), which was based on **FastMCP 1.0**.
47
+ > Recognize the `FastMCP` name? You might have seen the version that was contributed to the [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk), which was based on **FastMCP 1.0**.
48
48
  >
49
49
  > **Welcome to FastMCP 2.0!** This is the actively developed successor, and it significantly expands on 1.0 by introducing powerful client capabilities, server proxying & composition, OpenAPI/FastAPI integration, and more advanced features.
50
50
  >
@@ -4,7 +4,7 @@ fastmcp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  fastmcp/settings.py,sha256=rDClnYEpYjEl8VsvvVrKp9oaE4YLfNQcMoZ41H_bDL0,2968
5
5
  fastmcp/cli/__init__.py,sha256=Ii284TNoG5lxTP40ETMGhHEq3lQZWxu9m9JuU57kUpQ,87
6
6
  fastmcp/cli/claude.py,sha256=IAlcZ4qZKBBj09jZUMEx7EANZE_IR3vcu7zOBJmMOuU,4567
7
- fastmcp/cli/cli.py,sha256=7s5RsV8D_tPs20EJcrCvyO-i69DmV60OiRGD21oEJSI,15728
7
+ fastmcp/cli/cli.py,sha256=Tb-WiIXFZiq4nqlZ6LMXN2iYY30clC4Om_gP89HbJcE,15641
8
8
  fastmcp/client/__init__.py,sha256=BXO9NUhntZ5GnUACfaRCzDJ5IzxqFJs8qKG-CRMSco4,490
9
9
  fastmcp/client/base.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  fastmcp/client/client.py,sha256=zfSLWSGqiBoADveKehsAL66CdyGGqmzVHR1q46zfdQY,15479
@@ -35,10 +35,10 @@ fastmcp/resources/types.py,sha256=QPDeka_cM1hmvwW4FeFhqy6BEEi4MlwtpvhWUVWh5Fc,64
35
35
  fastmcp/server/__init__.py,sha256=bMD4aQD4yJqLz7-mudoNsyeV8UgQfRAg3PRwPvwTEds,119
36
36
  fastmcp/server/context.py,sha256=ykitQygA7zT5prbFTLCuYlnAzuljf_9ErUT0FYBPv3E,8135
37
37
  fastmcp/server/dependencies.py,sha256=1utkxFsV37HZcWBwI69JyngVN2ppGO_PEgxUlUHHy_Q,742
38
- fastmcp/server/http.py,sha256=esmeQZJCOxbvYBwF9gTzniymnL93n09hbjgRpmv-9bw,10076
38
+ fastmcp/server/http.py,sha256=utl7vJkMvKUnKIflCptVWk1oqOi7_sJJHqUl22g4JC8,10473
39
39
  fastmcp/server/openapi.py,sha256=0nANnwHJ5VZInNyo2f9ErmO0K3igMv6bwyxf3G-BSls,23473
40
40
  fastmcp/server/proxy.py,sha256=LDTjzc_iQj8AldsfMU37flGRAfJic1w6qsherfyHPAA,9622
41
- fastmcp/server/server.py,sha256=2pwYzjHFlg42Mq8qfjX5VttP1OjVJYNOCbW5H7R0hjk,40826
41
+ fastmcp/server/server.py,sha256=FLcZe-ccCUe5288sdEEPl7xlrKgaVunGhJnq7nv70vc,44483
42
42
  fastmcp/tools/__init__.py,sha256=ocw-SFTtN6vQ8fgnlF8iNAOflRmh79xS1xdO0Bc3QPE,96
43
43
  fastmcp/tools/tool.py,sha256=HGcHjMecqAeN6eI-IfE_2UBcd1KpTV-VOTFLx9tlbpU,7809
44
44
  fastmcp/tools/tool_manager.py,sha256=p2nHyLFgz28tbsLpWOurkbWRU2Z34_HcDohjrvwjI0E,3369
@@ -48,10 +48,10 @@ fastmcp/utilities/decorators.py,sha256=AjhjsetQZF4YOPV5MTZmIxO21iFp_4fDIS3O2_KNC
48
48
  fastmcp/utilities/json_schema.py,sha256=mSakhP8bENxhLFMwHJSxJAFllNeByIBDjVohwlpac6w,2026
49
49
  fastmcp/utilities/logging.py,sha256=zav8pnFxG_fvGJHUV2XpobmT9WVrmv1mlQBSCz-CPx4,1159
50
50
  fastmcp/utilities/openapi.py,sha256=Er3G1MyFwiWVxZXicXtD2j-BvttHEDTi1dgkq1KiBQc,51073
51
- fastmcp/utilities/tests.py,sha256=uUV-8CkhCe5zZJkxhgJXnxrjJ3Yq7cCMZN8xWKGuqdY,3181
51
+ fastmcp/utilities/tests.py,sha256=mAV2EjDeCbm9V9NsVIUjcmzf93MgDjfj8kMvHpf4vgo,3224
52
52
  fastmcp/utilities/types.py,sha256=6CcqAQ1QqCO2HGSFlPS6FO5JRWnacjCcO2-EhyEnZV0,4400
53
- fastmcp-2.3.1.dist-info/METADATA,sha256=EM2ah3-Gf3_vtum6tbRL4627SfRuugJ0xJdbsNa8EJE,15746
54
- fastmcp-2.3.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
55
- fastmcp-2.3.1.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
56
- fastmcp-2.3.1.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
57
- fastmcp-2.3.1.dist-info/RECORD,,
53
+ fastmcp-2.3.3.dist-info/METADATA,sha256=4z9X0B1oEDwqQBFJ7d2_YJtEoj2cKLn6TcJafKxATIE,15754
54
+ fastmcp-2.3.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
55
+ fastmcp-2.3.3.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
56
+ fastmcp-2.3.3.dist-info/licenses/LICENSE,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
57
+ fastmcp-2.3.3.dist-info/RECORD,,