|
1 | 1 | import asyncio
|
2 | 2 | import uvicorn
|
3 |
| -from typing import Any, Callable, Literal |
| 3 | +from typing import Any, Callable, Literal, Generic |
4 | 4 | from mcp.server.stdio import stdio_server
|
5 | 5 | from mcp.server.sse import SseServerTransport
|
| 6 | +from mcp.server.session import ServerSession, ServerSessionT |
6 | 7 | from mcp.server.models import InitializationOptions
|
7 | 8 | from pydantic_settings import BaseSettings, SettingsConfigDict
|
8 | 9 | from mcp.server.lowlevel import NotificationOptions, Server
|
|
11 | 12 | from mcp.server.fastmcp.resources import ResourceManager
|
12 | 13 | from mcp.server.fastmcp import FastMCP
|
13 | 14 | from mcp.server.fastmcp import Context as FastMCPContext
|
| 15 | +from mcp.shared.context import LifespanContextT |
14 | 16 | from mcp.server.fastmcp.utilities.logging import configure_logging, get_logger
|
15 | 17 |
|
16 | 18 | logger = get_logger(__name__)
|
17 | 19 |
|
18 | 20 | Context = FastMCPContext
|
19 | 21 |
|
20 | 22 |
|
| 23 | +class MCPServerContext(Context, Generic[ServerSessionT, LifespanContextT]): |
| 24 | + def __init__( |
| 25 | + self, |
| 26 | + *, |
| 27 | + request_context, |
| 28 | + fastmcp: FastMCP | None = None, |
| 29 | + **kwargs: Any, |
| 30 | + ): |
| 31 | + super().__init__(request_context=request_context, fastmcp=fastmcp, **kwargs) |
| 32 | + |
| 33 | + @property |
| 34 | + def iris(self) -> any: |
| 35 | + iris = self.request_context.lifespan_context["iris"] |
| 36 | + assert iris, "IRIS connection not available" |
| 37 | + return iris |
| 38 | + |
| 39 | + @property |
| 40 | + def db(self) -> any: |
| 41 | + db = self.request_context.lifespan_context["db"] |
| 42 | + assert db, "Database connection not available" |
| 43 | + return db |
| 44 | + |
| 45 | + |
21 | 46 | class Settings(BaseSettings):
|
22 | 47 | """MCPServer server settings.
|
23 | 48 |
|
@@ -96,15 +121,16 @@ def name(self) -> str:
|
96 | 121 | def version(self) -> str:
|
97 | 122 | return self._mcp_server.version
|
98 | 123 |
|
99 |
| - # def _setup_handlers(self) -> None: |
100 |
| - # """Set up core MCP protocol handlers.""" |
101 |
| - # self._mcp_server.list_tools()(self.list_tools) |
102 |
| - # self._mcp_server.call_tool()(self.call_tool) |
103 |
| - # self._mcp_server.list_resources()(self.list_resources) |
104 |
| - # self._mcp_server.read_resource()(self.read_resource) |
105 |
| - # self._mcp_server.list_prompts()(self.list_prompts) |
106 |
| - # self._mcp_server.get_prompt()(self.get_prompt) |
107 |
| - # self._mcp_server.list_resource_templates()(self.list_resource_templates) |
| 124 | + def get_context(self) -> "Context[ServerSession, object]": |
| 125 | + """ |
| 126 | + Returns a Context object. Note that the context will only be valid |
| 127 | + during a request; outside a request, most methods will error. |
| 128 | + """ |
| 129 | + try: |
| 130 | + request_context = self._mcp_server.request_context |
| 131 | + except LookupError: |
| 132 | + request_context = None |
| 133 | + return MCPServerContext(request_context=request_context, fastmcp=self) |
108 | 134 |
|
109 | 135 | def run(self, transport: Literal["stdio", "sse"] = "stdio") -> None:
|
110 | 136 | """Run the FastMCP server. Note this is a synchronous function.
|
|
0 commit comments