Skip to content

Commit ba66a9d

Browse files
authored
MCP package dependency check (#561)
* MCP package dependency check. - Added a runtime check for the "fastmcp" package in `mcp.py`, raising an error if it is not installed. - Updated the error message to provide clearer installation instructions. * fix * apply suggestin * update requirement
1 parent 9da3290 commit ba66a9d

File tree

3 files changed

+32
-13
lines changed

3 files changed

+32
-13
lines changed

_requirements/test.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ openai>=1.12.0
1515
pillow
1616
numpy <3.0
1717
pytest-retry>=1.6.3
18-
mcp>=1.9.2; python_version >= '3.10'
18+
fastmcp>=2.9.2; python_version >= '3.10'

src/litserve/mcp.py

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,27 @@
2020
from contextlib import asynccontextmanager
2121
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union, get_args, get_origin
2222

23-
import mcp.types as types
2423
from fastapi import FastAPI
25-
from mcp.server.fastmcp.server import _convert_to_content
26-
from mcp.server.lowlevel import Server as MCPServer
27-
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
2824
from pydantic import BaseModel
2925
from starlette.applications import Starlette
3026
from starlette.routing import Mount
3127
from starlette.types import Receive, Scope, Send
3228

3329
from litserve.utils import is_package_installed
3430

31+
_is_mcp_installed = is_package_installed("fastmcp")
32+
33+
34+
if _is_mcp_installed:
35+
from fastapi import FastAPI
36+
from mcp.server.fastmcp.server import _convert_to_content
37+
from mcp.server.lowlevel import Server as MCPServer
38+
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
39+
from mcp.types import Tool as ToolType
40+
41+
else:
42+
ToolType = object
43+
3544
if TYPE_CHECKING:
3645
from litserve.api import LitAPI
3746

@@ -243,7 +252,7 @@ async def _call_handler(handler, **kwargs):
243252
return _convert_to_content(await handler(*bound.args, **bound.kwargs))
244253

245254

246-
class ToolEndpointType(types.Tool):
255+
class ToolEndpointType(ToolType):
247256
endpoint: str
248257

249258

@@ -348,6 +357,11 @@ def __init__(
348357
self.input_schema = input_schema
349358
self._connected = False
350359

360+
if not is_package_installed("fastmcp"):
361+
raise RuntimeError(
362+
"mcp package is required for MCP support. To install, run `pip install fastmcp` in the terminal."
363+
)
364+
351365
@property
352366
def name(self) -> str:
353367
return self._name
@@ -364,11 +378,6 @@ def _connect(self, lit_api: "LitAPI"):
364378
self._connected = True
365379

366380
def as_tool(self) -> ToolEndpointType:
367-
if not is_package_installed("mcp"):
368-
raise RuntimeError(
369-
"MCP is not installed. Please install it with `pip install mcp[cli]` or `uv pip install mcp[cli]`"
370-
)
371-
372381
if not self._connected:
373382
raise RuntimeError("MCP is not connected to a LitAPI.")
374383

@@ -400,7 +409,7 @@ def as_tool(self) -> ToolEndpointType:
400409

401410

402411
class _MCPRequestHandler:
403-
def __init__(self, mcp_server: MCPServer):
412+
def __init__(self, mcp_server: "MCPServer"):
404413
self.mcp_server = mcp_server
405414
self._session_manager = None
406415

@@ -536,7 +545,7 @@ async def _call_tool(name: str, arguments: dict):
536545
starlette_app = self.request_handler.streamable_http_app()
537546
app.mount("/", starlette_app, name="mcp")
538547

539-
def connect_mcp_server(self, mcp_tools: List[types.Tool], app: FastAPI):
548+
def connect_mcp_server(self, mcp_tools: List[ToolType], app: FastAPI):
540549
"""LitServer calls this method to connect MCP server to the FastAPI app.
541550
542551
Args:

tests/unit/test_mcp.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import inspect
22
import sys
33
from typing import Dict, List, Optional
4+
from unittest.mock import patch
45

56
import pytest
67
from fastapi import FastAPI
@@ -20,6 +21,15 @@
2021
)
2122

2223

24+
@patch("litserve.mcp.is_package_installed", return_value=False)
25+
def test_mcp_not_installed(mock_is_package_installed):
26+
with pytest.raises(
27+
RuntimeError,
28+
match="mcp package is required for MCP support. To install, run `pip install fastmcp` in the terminal.",
29+
):
30+
MCP()
31+
32+
2333
def test_python_type_to_json_schema():
2434
assert _python_type_to_json_schema(inspect.Parameter.empty) == "string"
2535
assert _python_type_to_json_schema(int) == "integer"

0 commit comments

Comments
 (0)