Jeremiah Lowin commited on
Commit
0fa02ae
·
1 Parent(s): 8e52c19

Add http as an alias for streamable http

Browse files
README.md CHANGED
@@ -349,7 +349,7 @@ mcp.run(transport="stdio") # Default, so transport argument is optional
349
  **Streamable HTTP**: Recommended for web deployments.
350
 
351
  ```python
352
- mcp.run(transport="streamable-http", host="127.0.0.1", port=8000, path="/mcp")
353
  ```
354
 
355
  **SSE**: For compatibility with existing SSE clients.
 
349
  **Streamable HTTP**: Recommended for web deployments.
350
 
351
  ```python
352
+ mcp.run(transport="http", host="127.0.0.1", port=8000, path="/mcp")
353
  ```
354
 
355
  **SSE**: For compatibility with existing SSE clients.
src/fastmcp/cli/cli.py CHANGED
@@ -235,7 +235,7 @@ def run(
235
  typer.Option(
236
  "--transport",
237
  "-t",
238
- help="Transport protocol to use (stdio, streamable-http, or sse)",
239
  ),
240
  ] = None,
241
  host: Annotated[
 
235
  typer.Option(
236
  "--transport",
237
  "-t",
238
+ help="Transport protocol to use (stdio, http, or sse)",
239
  ),
240
  ] = None,
241
  host: Annotated[
src/fastmcp/cli/run.py CHANGED
@@ -4,14 +4,12 @@ import importlib.util
4
  import re
5
  import sys
6
  from pathlib import Path
7
- from typing import Any, Literal
8
 
9
  from fastmcp.utilities.logging import get_logger
10
 
11
  logger = get_logger("cli.run")
12
 
13
- TransportType = Literal["stdio", "streamable-http", "sse"]
14
-
15
 
16
  def is_url(path: str) -> bool:
17
  """Check if a string is a URL."""
 
4
  import re
5
  import sys
6
  from pathlib import Path
7
+ from typing import Any
8
 
9
  from fastmcp.utilities.logging import get_logger
10
 
11
  logger = get_logger("cli.run")
12
 
 
 
13
 
14
  def is_url(path: str) -> bool:
15
  """Check if a string is a URL."""
src/fastmcp/server/server.py CHANGED
@@ -74,6 +74,7 @@ if TYPE_CHECKING:
74
  logger = get_logger(__name__)
75
 
76
  DuplicateBehavior = Literal["warn", "error", "replace", "ignore"]
 
77
 
78
  # Compiled URI parsing regex to split a URI into protocol and path components
79
  URI_PATTERN = re.compile(r"^([^:]+://)(.*?)$")
@@ -280,7 +281,7 @@ class FastMCP(Generic[LifespanResultT]):
280
 
281
  async def run_async(
282
  self,
283
- transport: Literal["stdio", "streamable-http", "sse"] | None = None,
284
  **transport_kwargs: Any,
285
  ) -> None:
286
  """Run the FastMCP server asynchronously.
@@ -290,19 +291,19 @@ class FastMCP(Generic[LifespanResultT]):
290
  """
291
  if transport is None:
292
  transport = "stdio"
293
- if transport not in {"stdio", "streamable-http", "sse"}:
294
  raise ValueError(f"Unknown transport: {transport}")
295
 
296
  if transport == "stdio":
297
  await self.run_stdio_async(**transport_kwargs)
298
- elif transport in {"streamable-http", "sse"}:
299
  await self.run_http_async(transport=transport, **transport_kwargs)
300
  else:
301
  raise ValueError(f"Unknown transport: {transport}")
302
 
303
  def run(
304
  self,
305
- transport: Literal["stdio", "streamable-http", "sse"] | None = None,
306
  **transport_kwargs: Any,
307
  ) -> None:
308
  """Run the FastMCP server. Note this is a synchronous function.
@@ -1253,7 +1254,7 @@ class FastMCP(Generic[LifespanResultT]):
1253
 
1254
  async def run_http_async(
1255
  self,
1256
- transport: Literal["streamable-http", "sse"] = "streamable-http",
1257
  host: str | None = None,
1258
  port: int | None = None,
1259
  log_level: str | None = None,
@@ -1384,7 +1385,7 @@ class FastMCP(Generic[LifespanResultT]):
1384
  middleware: list[ASGIMiddleware] | None = None,
1385
  json_response: bool | None = None,
1386
  stateless_http: bool | None = None,
1387
- transport: Literal["streamable-http", "sse"] = "streamable-http",
1388
  ) -> StarletteWithLifespan:
1389
  """Create a Starlette app using the specified HTTP transport.
1390
 
@@ -1397,7 +1398,7 @@ class FastMCP(Generic[LifespanResultT]):
1397
  A Starlette application configured with the specified transport
1398
  """
1399
 
1400
- if transport == "streamable-http":
1401
  return create_streamable_http_app(
1402
  server=self,
1403
  streamable_http_path=path
@@ -1444,7 +1445,7 @@ class FastMCP(Generic[LifespanResultT]):
1444
  stacklevel=2,
1445
  )
1446
  await self.run_http_async(
1447
- transport="streamable-http",
1448
  host=host,
1449
  port=port,
1450
  log_level=log_level,
 
74
  logger = get_logger(__name__)
75
 
76
  DuplicateBehavior = Literal["warn", "error", "replace", "ignore"]
77
+ Transport = Literal["stdio", "http", "sse", "streamable-http"]
78
 
79
  # Compiled URI parsing regex to split a URI into protocol and path components
80
  URI_PATTERN = re.compile(r"^([^:]+://)(.*?)$")
 
281
 
282
  async def run_async(
283
  self,
284
+ transport: Transport | None = None,
285
  **transport_kwargs: Any,
286
  ) -> None:
287
  """Run the FastMCP server asynchronously.
 
291
  """
292
  if transport is None:
293
  transport = "stdio"
294
+ if transport not in {"stdio", "http", "sse", "streamable-http"}:
295
  raise ValueError(f"Unknown transport: {transport}")
296
 
297
  if transport == "stdio":
298
  await self.run_stdio_async(**transport_kwargs)
299
+ elif transport in {"http", "sse", "streamable-http"}:
300
  await self.run_http_async(transport=transport, **transport_kwargs)
301
  else:
302
  raise ValueError(f"Unknown transport: {transport}")
303
 
304
  def run(
305
  self,
306
+ transport: Transport | None = None,
307
  **transport_kwargs: Any,
308
  ) -> None:
309
  """Run the FastMCP server. Note this is a synchronous function.
 
1254
 
1255
  async def run_http_async(
1256
  self,
1257
+ transport: Literal["http", "streamable-http", "sse"] = "http",
1258
  host: str | None = None,
1259
  port: int | None = None,
1260
  log_level: str | None = None,
 
1385
  middleware: list[ASGIMiddleware] | None = None,
1386
  json_response: bool | None = None,
1387
  stateless_http: bool | None = None,
1388
+ transport: Literal["http", "streamable-http", "sse"] = "http",
1389
  ) -> StarletteWithLifespan:
1390
  """Create a Starlette app using the specified HTTP transport.
1391
 
 
1398
  A Starlette application configured with the specified transport
1399
  """
1400
 
1401
+ if transport in ("streamable-http", "http"):
1402
  return create_streamable_http_app(
1403
  server=self,
1404
  streamable_http_path=path
 
1445
  stacklevel=2,
1446
  )
1447
  await self.run_http_async(
1448
+ transport="http",
1449
  host=host,
1450
  port=port,
1451
  log_level=log_level,
src/fastmcp/utilities/mcp_config.py CHANGED
@@ -19,7 +19,7 @@ if TYPE_CHECKING:
19
 
20
  def infer_transport_type_from_url(
21
  url: str | AnyUrl,
22
- ) -> Literal["streamable-http", "sse"]:
23
  """
24
  Infer the appropriate transport type from the given URL.
25
  """
@@ -34,7 +34,7 @@ def infer_transport_type_from_url(
34
  if re.search(r"/sse(/|\?|&|$)", path):
35
  return "sse"
36
  else:
37
- return "streamable-http"
38
 
39
 
40
  class StdioMCPServer(FastMCPBaseModel):
@@ -58,7 +58,7 @@ class StdioMCPServer(FastMCPBaseModel):
58
  class RemoteMCPServer(FastMCPBaseModel):
59
  url: str
60
  headers: dict[str, str] = Field(default_factory=dict)
61
- transport: Literal["streamable-http", "sse"] | None = None
62
  auth: Annotated[
63
  str | Literal["oauth"] | httpx.Auth | None,
64
  Field(
@@ -79,6 +79,7 @@ class RemoteMCPServer(FastMCPBaseModel):
79
  if transport == "sse":
80
  return SSETransport(self.url, headers=self.headers, auth=self.auth)
81
  else:
 
82
  return StreamableHttpTransport(
83
  self.url, headers=self.headers, auth=self.auth
84
  )
 
19
 
20
  def infer_transport_type_from_url(
21
  url: str | AnyUrl,
22
+ ) -> Literal["http", "sse"]:
23
  """
24
  Infer the appropriate transport type from the given URL.
25
  """
 
34
  if re.search(r"/sse(/|\?|&|$)", path):
35
  return "sse"
36
  else:
37
+ return "http"
38
 
39
 
40
  class StdioMCPServer(FastMCPBaseModel):
 
58
  class RemoteMCPServer(FastMCPBaseModel):
59
  url: str
60
  headers: dict[str, str] = Field(default_factory=dict)
61
+ transport: Literal["http", "streamable-http", "sse"] | None = None
62
  auth: Annotated[
63
  str | Literal["oauth"] | httpx.Auth | None,
64
  Field(
 
79
  if transport == "sse":
80
  return SSETransport(self.url, headers=self.headers, auth=self.auth)
81
  else:
82
+ # Both "http" and "streamable-http" map to StreamableHttpTransport
83
  return StreamableHttpTransport(
84
  self.url, headers=self.headers, auth=self.auth
85
  )
tests/deprecated/test_deprecated.py CHANGED
@@ -85,7 +85,7 @@ async def test_run_streamable_http_async_deprecation_warning():
85
  # Verify the mock was called with the right transport
86
  mock_run.assert_called_once()
87
  call_kwargs = mock_run.call_args.kwargs
88
- assert call_kwargs.get("transport") == "streamable-http"
89
 
90
 
91
  def test_http_app_with_sse_transport():
 
85
  # Verify the mock was called with the right transport
86
  mock_run.assert_called_once()
87
  call_kwargs = mock_run.call_args.kwargs
88
+ assert call_kwargs.get("transport") == "http"
89
 
90
 
91
  def test_http_app_with_sse_transport():