mirror of
https://github.com/aljazceru/mcp-python-sdk.git
synced 2025-12-19 14:54:24 +01:00
Add ServerSessionT type var to Context (#271)
* Add ServerSessionT type var to Context * Passing locally * Try now
This commit is contained in:
committed by
GitHub
parent
78fc5c12c0
commit
e756315dea
@@ -1,5 +1,7 @@
|
|||||||
"""FastMCP - A more ergonomic interface for MCP servers."""
|
"""FastMCP - A more ergonomic interface for MCP servers."""
|
||||||
|
|
||||||
|
from __future__ import annotations as _annotations
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
@@ -25,16 +27,10 @@ from mcp.server.fastmcp.tools import ToolManager
|
|||||||
from mcp.server.fastmcp.utilities.logging import configure_logging, get_logger
|
from mcp.server.fastmcp.utilities.logging import configure_logging, get_logger
|
||||||
from mcp.server.fastmcp.utilities.types import Image
|
from mcp.server.fastmcp.utilities.types import Image
|
||||||
from mcp.server.lowlevel.helper_types import ReadResourceContents
|
from mcp.server.lowlevel.helper_types import ReadResourceContents
|
||||||
from mcp.server.lowlevel.server import (
|
from mcp.server.lowlevel.server import LifespanResultT
|
||||||
LifespanResultT,
|
from mcp.server.lowlevel.server import Server as MCPServer
|
||||||
)
|
from mcp.server.lowlevel.server import lifespan as default_lifespan
|
||||||
from mcp.server.lowlevel.server import (
|
from mcp.server.session import ServerSession, ServerSessionT
|
||||||
Server as MCPServer,
|
|
||||||
)
|
|
||||||
from mcp.server.lowlevel.server import (
|
|
||||||
lifespan as default_lifespan,
|
|
||||||
)
|
|
||||||
from mcp.server.session import ServerSession
|
|
||||||
from mcp.server.sse import SseServerTransport
|
from mcp.server.sse import SseServerTransport
|
||||||
from mcp.server.stdio import stdio_server
|
from mcp.server.stdio import stdio_server
|
||||||
from mcp.shared.context import LifespanContextT, RequestContext
|
from mcp.shared.context import LifespanContextT, RequestContext
|
||||||
@@ -45,21 +41,11 @@ from mcp.types import (
|
|||||||
ImageContent,
|
ImageContent,
|
||||||
TextContent,
|
TextContent,
|
||||||
)
|
)
|
||||||
from mcp.types import (
|
from mcp.types import Prompt as MCPPrompt
|
||||||
Prompt as MCPPrompt,
|
from mcp.types import PromptArgument as MCPPromptArgument
|
||||||
)
|
from mcp.types import Resource as MCPResource
|
||||||
from mcp.types import (
|
from mcp.types import ResourceTemplate as MCPResourceTemplate
|
||||||
PromptArgument as MCPPromptArgument,
|
from mcp.types import Tool as MCPTool
|
||||||
)
|
|
||||||
from mcp.types import (
|
|
||||||
Resource as MCPResource,
|
|
||||||
)
|
|
||||||
from mcp.types import (
|
|
||||||
ResourceTemplate as MCPResourceTemplate,
|
|
||||||
)
|
|
||||||
from mcp.types import (
|
|
||||||
Tool as MCPTool,
|
|
||||||
)
|
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@@ -105,11 +91,11 @@ class Settings(BaseSettings, Generic[LifespanResultT]):
|
|||||||
|
|
||||||
|
|
||||||
def lifespan_wrapper(
|
def lifespan_wrapper(
|
||||||
app: "FastMCP",
|
app: FastMCP,
|
||||||
lifespan: Callable[["FastMCP"], AbstractAsyncContextManager[LifespanResultT]],
|
lifespan: Callable[["FastMCP"], AbstractAsyncContextManager[LifespanResultT]],
|
||||||
) -> Callable[[MCPServer], AbstractAsyncContextManager[object]]:
|
) -> Callable[[MCPServer[LifespanResultT]], AbstractAsyncContextManager[object]]:
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def wrap(s: MCPServer) -> AsyncIterator[object]:
|
async def wrap(s: MCPServer[LifespanResultT]) -> AsyncIterator[object]:
|
||||||
async with lifespan(app) as context:
|
async with lifespan(app) as context:
|
||||||
yield context
|
yield context
|
||||||
|
|
||||||
@@ -191,7 +177,7 @@ class FastMCP:
|
|||||||
for info in tools
|
for info in tools
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_context(self) -> "Context":
|
def get_context(self) -> "Context[ServerSession, object]":
|
||||||
"""
|
"""
|
||||||
Returns a Context object. Note that the context will only be valid
|
Returns a Context object. Note that the context will only be valid
|
||||||
during a request; outside a request, most methods will error.
|
during a request; outside a request, most methods will error.
|
||||||
@@ -564,7 +550,7 @@ def _convert_to_content(
|
|||||||
return [TextContent(type="text", text=result)]
|
return [TextContent(type="text", text=result)]
|
||||||
|
|
||||||
|
|
||||||
class Context(BaseModel, Generic[LifespanContextT]):
|
class Context(BaseModel, Generic[ServerSessionT, LifespanContextT]):
|
||||||
"""Context object providing access to MCP capabilities.
|
"""Context object providing access to MCP capabilities.
|
||||||
|
|
||||||
This provides a cleaner interface to MCP's RequestContext functionality.
|
This provides a cleaner interface to MCP's RequestContext functionality.
|
||||||
@@ -598,13 +584,13 @@ class Context(BaseModel, Generic[LifespanContextT]):
|
|||||||
The context is optional - tools that don't need it can omit the parameter.
|
The context is optional - tools that don't need it can omit the parameter.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_request_context: RequestContext[ServerSession, LifespanContextT] | None
|
_request_context: RequestContext[ServerSessionT, LifespanContextT] | None
|
||||||
_fastmcp: FastMCP | None
|
_fastmcp: FastMCP | None
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
request_context: RequestContext[ServerSession, LifespanContextT] | None = None,
|
request_context: RequestContext[ServerSessionT, LifespanContextT] | None = None,
|
||||||
fastmcp: FastMCP | None = None,
|
fastmcp: FastMCP | None = None,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
):
|
):
|
||||||
@@ -620,7 +606,7 @@ class Context(BaseModel, Generic[LifespanContextT]):
|
|||||||
return self._fastmcp
|
return self._fastmcp
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def request_context(self) -> RequestContext[ServerSession, LifespanContextT]:
|
def request_context(self) -> RequestContext[ServerSessionT, LifespanContextT]:
|
||||||
"""Access to the underlying request context."""
|
"""Access to the underlying request context."""
|
||||||
if self._request_context is None:
|
if self._request_context is None:
|
||||||
raise ValueError("Context is not available outside of a request")
|
raise ValueError("Context is not available outside of a request")
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations as _annotations
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
from typing import TYPE_CHECKING, Any, Callable
|
from typing import TYPE_CHECKING, Any, Callable
|
||||||
|
|
||||||
@@ -9,6 +11,8 @@ from mcp.server.fastmcp.utilities.func_metadata import FuncMetadata, func_metada
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from mcp.server.fastmcp.server import Context
|
from mcp.server.fastmcp.server import Context
|
||||||
|
from mcp.server.session import ServerSessionT
|
||||||
|
from mcp.shared.context import LifespanContextT
|
||||||
|
|
||||||
|
|
||||||
class Tool(BaseModel):
|
class Tool(BaseModel):
|
||||||
@@ -68,7 +72,11 @@ class Tool(BaseModel):
|
|||||||
context_kwarg=context_kwarg,
|
context_kwarg=context_kwarg,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def run(self, arguments: dict, context: "Context | None" = None) -> Any:
|
async def run(
|
||||||
|
self,
|
||||||
|
arguments: dict[str, Any],
|
||||||
|
context: Context[ServerSessionT, LifespanContextT] | None = None,
|
||||||
|
) -> Any:
|
||||||
"""Run the tool with arguments."""
|
"""Run the tool with arguments."""
|
||||||
try:
|
try:
|
||||||
return await self.fn_metadata.call_fn_with_arg_validation(
|
return await self.fn_metadata.call_fn_with_arg_validation(
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
|
from __future__ import annotations as _annotations
|
||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
from mcp.server.fastmcp.exceptions import ToolError
|
from mcp.server.fastmcp.exceptions import ToolError
|
||||||
from mcp.server.fastmcp.tools.base import Tool
|
from mcp.server.fastmcp.tools.base import Tool
|
||||||
from mcp.server.fastmcp.utilities.logging import get_logger
|
from mcp.server.fastmcp.utilities.logging import get_logger
|
||||||
|
from mcp.shared.context import LifespanContextT
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from mcp.server.fastmcp.server import Context
|
from mcp.server.fastmcp.server import Context
|
||||||
|
from mcp.server.session import ServerSessionT
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@@ -43,7 +47,10 @@ class ToolManager:
|
|||||||
return tool
|
return tool
|
||||||
|
|
||||||
async def call_tool(
|
async def call_tool(
|
||||||
self, name: str, arguments: dict, context: "Context | None" = None
|
self,
|
||||||
|
name: str,
|
||||||
|
arguments: dict[str, Any],
|
||||||
|
context: Context[ServerSessionT, LifespanContextT] | None = None,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""Call a tool by name with arguments."""
|
"""Call a tool by name with arguments."""
|
||||||
tool = self.get_tool(name)
|
tool = self.get_tool(name)
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ notifications. It automatically manages the request context and handles incoming
|
|||||||
messages from the client.
|
messages from the client.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations as _annotations
|
||||||
|
|
||||||
import contextvars
|
import contextvars
|
||||||
import logging
|
import logging
|
||||||
import warnings
|
import warnings
|
||||||
@@ -107,7 +109,7 @@ class NotificationOptions:
|
|||||||
|
|
||||||
|
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(server: "Server") -> AsyncIterator[object]:
|
async def lifespan(server: Server[LifespanResultT]) -> AsyncIterator[object]:
|
||||||
"""Default lifespan context manager that does nothing.
|
"""Default lifespan context manager that does nothing.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -126,7 +128,7 @@ class Server(Generic[LifespanResultT]):
|
|||||||
version: str | None = None,
|
version: str | None = None,
|
||||||
instructions: str | None = None,
|
instructions: str | None = None,
|
||||||
lifespan: Callable[
|
lifespan: Callable[
|
||||||
["Server"], AbstractAsyncContextManager[LifespanResultT]
|
[Server[LifespanResultT]], AbstractAsyncContextManager[LifespanResultT]
|
||||||
] = lifespan,
|
] = lifespan,
|
||||||
):
|
):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ be instantiated directly by users of the MCP framework.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Any
|
from typing import Any, TypeVar
|
||||||
|
|
||||||
import anyio
|
import anyio
|
||||||
import anyio.lowlevel
|
import anyio.lowlevel
|
||||||
@@ -59,6 +59,9 @@ class InitializationState(Enum):
|
|||||||
Initialized = 3
|
Initialized = 3
|
||||||
|
|
||||||
|
|
||||||
|
ServerSessionT = TypeVar("ServerSessionT", bound="ServerSession")
|
||||||
|
|
||||||
|
|
||||||
class ServerSession(
|
class ServerSession(
|
||||||
BaseSession[
|
BaseSession[
|
||||||
types.ServerRequest,
|
types.ServerRequest,
|
||||||
|
|||||||
Reference in New Issue
Block a user