mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-23 22:14:18 +02:00
Add sdkv2 import shims pending server/client port
This commit is contained in:
parent
1f319df0c3
commit
42e72d71e9
34 changed files with 125 additions and 75 deletions
|
|
@ -32,11 +32,12 @@ from collections.abc import AsyncIterator, Callable, Sequence
|
|||
from contextlib import asynccontextmanager
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypeVar, overload
|
||||
|
||||
from mcp_types import AnyFunction, Icon, ToolAnnotations
|
||||
from mcp_types import Icon, ToolAnnotations
|
||||
|
||||
from fastmcp.server.providers.base import Provider
|
||||
from fastmcp.utilities.authorization import AuthCheck
|
||||
from fastmcp.utilities.logging import get_logger
|
||||
from fastmcp.utilities.types import AnyFunction
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastmcp.server.providers.local_provider import LocalProvider
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from collections.abc import Callable
|
|||
from pathlib import Path
|
||||
from typing import Any, Literal
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
from watchfiles import Change, awatch
|
||||
|
||||
import fastmcp
|
||||
|
|
|
|||
31
fastmcp_slim/fastmcp/client/_sdk_context_shim.py
Normal file
31
fastmcp_slim/fastmcp/client/_sdk_context_shim.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
"""SDK context survival shims pending the Phase C client port.
|
||||
|
||||
The MCP SDK v2 removed ``mcp.shared.context.RequestContext`` and
|
||||
``mcp.shared.context.LifespanContextT``. Client-side handler signatures in
|
||||
FastMCP still reference them as type annotations. These shims keep those
|
||||
modules importable at collection time; the annotations they feed are not
|
||||
semantically load-bearing yet.
|
||||
|
||||
TODO(sdkv2): replace with the real SDK client request-context type in Phase C
|
||||
(client port). Handler wiring that populates/consumes the request context is
|
||||
reworked there.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Generic, TypeVar
|
||||
|
||||
LifespanContextT = TypeVar("LifespanContextT")
|
||||
_SessionT = TypeVar("_SessionT")
|
||||
|
||||
|
||||
class RequestContext(Generic[_SessionT, LifespanContextT]):
|
||||
"""Placeholder for the removed SDK ``RequestContext`` generic.
|
||||
|
||||
Subscriptable with two type parameters to match existing client handler
|
||||
annotations. Not instantiated anywhere; exists only so module imports and
|
||||
annotation evaluation succeed until the Phase C client port lands.
|
||||
"""
|
||||
|
||||
def __class_getitem__(cls, item: Any) -> Any: # pragma: no cover - typing only
|
||||
return super().__class_getitem__(item) # type: ignore[misc]
|
||||
|
|
@ -6,12 +6,12 @@ from typing import Any, Generic, TypeAlias
|
|||
import mcp_types
|
||||
from mcp import ClientSession
|
||||
from mcp.client.session import ElicitationFnT
|
||||
from mcp.shared.context import LifespanContextT, RequestContext
|
||||
from mcp_types import ElicitRequestFormParams, ElicitRequestParams
|
||||
from mcp_types import ElicitResult as MCPElicitResult
|
||||
from pydantic_core import to_jsonable_python
|
||||
from typing_extensions import TypeVar
|
||||
|
||||
from fastmcp.client._sdk_context_shim import LifespanContextT, RequestContext
|
||||
from fastmcp.utilities.json_schema_type import json_schema_to_type
|
||||
|
||||
__all__ = ["ElicitRequestParams", "ElicitResult", "ElicitationHandler"]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ import mcp_types
|
|||
import pydantic
|
||||
from mcp import ClientSession
|
||||
from mcp.client.session import ListRootsFnT
|
||||
from mcp.shared.context import LifespanContextT, RequestContext
|
||||
|
||||
from fastmcp.client._sdk_context_shim import LifespanContextT, RequestContext
|
||||
|
||||
RootsList: TypeAlias = list[str] | list[mcp_types.Root] | list[str | mcp_types.Root]
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import mcp_types
|
|||
from mcp import ClientSession, CreateMessageResult
|
||||
from mcp.client.session import SamplingFnT
|
||||
from mcp.server.session import ServerSession
|
||||
from mcp.shared.context import LifespanContextT, RequestContext
|
||||
from fastmcp.client._sdk_context_shim import LifespanContextT, RequestContext
|
||||
from mcp_types import CreateMessageRequestParams as SamplingParams
|
||||
from mcp_types import CreateMessageResultWithTools, SamplingMessage
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ except ImportError as e:
|
|||
) from e
|
||||
|
||||
from mcp import ClientSession, ServerSession
|
||||
from mcp.shared.context import LifespanContextT, RequestContext
|
||||
from mcp_types import (
|
||||
AudioContent,
|
||||
CreateMessageResult,
|
||||
|
|
@ -50,6 +49,8 @@ from mcp_types import (
|
|||
from mcp_types import CreateMessageRequestParams as SamplingParams
|
||||
from mcp_types import Tool as MCPTool
|
||||
|
||||
from fastmcp.client._sdk_context_shim import LifespanContextT, RequestContext
|
||||
|
||||
__all__ = ["GoogleGenaiSamplingHandler"]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ from collections.abc import Iterator, Sequence
|
|||
from typing import Any, Literal, get_args
|
||||
|
||||
from mcp import ClientSession, ServerSession
|
||||
from mcp.shared.context import LifespanContextT, RequestContext
|
||||
from mcp_types import (
|
||||
AudioContent,
|
||||
CreateMessageResult,
|
||||
|
|
@ -22,6 +21,8 @@ from mcp_types import (
|
|||
)
|
||||
from mcp_types import CreateMessageRequestParams as SamplingParams
|
||||
|
||||
from fastmcp.client._sdk_context_shim import LifespanContextT, RequestContext
|
||||
|
||||
try:
|
||||
from openai import AsyncOpenAI
|
||||
from openai.types.chat import (
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from mcp.server.fastmcp import FastMCP as FastMCP1Server
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1Server
|
||||
|
||||
from fastmcp.client.transports.base import (
|
||||
ClientTransport,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any, cast, overload
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1Server
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1Server
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from fastmcp.client.transports.base import ClientTransport, ClientTransportT
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Any
|
|||
|
||||
import anyio
|
||||
from mcp import ClientSession
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1Server
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1Server
|
||||
from mcp.shared.memory import create_client_server_memory_streams
|
||||
from typing_extensions import Unpack
|
||||
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ from typing import Any, Literal, overload
|
|||
|
||||
import mcp_types
|
||||
from mcp import LoggingLevel, ServerSession
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp.shared.context import RequestContext
|
||||
from mcp.server.context import ServerRequestContext
|
||||
from mcp_types import (
|
||||
GetPromptResult,
|
||||
ModelPreferences,
|
||||
|
|
@ -23,13 +22,13 @@ from mcp_types import (
|
|||
from mcp_types import Prompt as SDKPrompt
|
||||
from mcp_types import Resource as SDKResource
|
||||
from pydantic.networks import AnyUrl
|
||||
from starlette.requests import Request
|
||||
from typing_extensions import TypeVar
|
||||
from uncalled_for import SharedContext
|
||||
|
||||
import fastmcp
|
||||
from fastmcp.exceptions import FastMCPDeprecationWarning
|
||||
from fastmcp.resources.base import ResourceResult
|
||||
from fastmcp.server.dependencies import request_ctx
|
||||
from fastmcp.server.elicitation import (
|
||||
AcceptedElicitation,
|
||||
CancelledElicitation,
|
||||
|
|
@ -322,7 +321,7 @@ class Context:
|
|||
_current_context.reset(token)
|
||||
|
||||
@property
|
||||
def request_context(self) -> RequestContext[ServerSession, Any, Request] | None:
|
||||
def request_context(self) -> ServerRequestContext[Any, Any] | None:
|
||||
"""Access to the underlying request context.
|
||||
|
||||
Returns None when the MCP session has not been established yet.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ from mcp.server.auth.middleware.bearer_auth import AuthenticatedUser
|
|||
from mcp.server.auth.provider import (
|
||||
AccessToken as _SDKAccessToken,
|
||||
)
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp.server.context import ServerRequestContext
|
||||
from packaging.version import Version
|
||||
from starlette.requests import Request
|
||||
from uncalled_for import Dependency, get_dependency_parameters
|
||||
|
|
@ -49,6 +49,15 @@ if TYPE_CHECKING:
|
|||
from fastmcp.server.server import FastMCP
|
||||
|
||||
|
||||
# TODO(sdkv2): set by handler entry, Phase B.
|
||||
# The SDK removed `mcp.server.lowlevel.server.request_ctx`. FastMCP now owns the
|
||||
# per-request ContextVar carrying the active ServerRequestContext. Nothing sets
|
||||
# it yet — the low-level handler entry points that populate it are wired in the
|
||||
# Phase B server-core port. Until then it stays unset and `.get()` raises
|
||||
# LookupError, which existing callers already handle.
|
||||
request_ctx: ContextVar[ServerRequestContext] = ContextVar("request_ctx")
|
||||
|
||||
|
||||
__all__ = [
|
||||
"AccessToken",
|
||||
"CurrentAccessToken",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ from mcp import LoggingLevel, MCPError
|
|||
from mcp.server.lowlevel.server import (
|
||||
LifespanResultT,
|
||||
NotificationOptions,
|
||||
RequestT,
|
||||
)
|
||||
from mcp.server.lowlevel.server import (
|
||||
Server as _Server,
|
||||
|
|
@ -154,7 +153,9 @@ class MiddlewareServerSession(ServerSession):
|
|||
return await super()._received_request(responder)
|
||||
|
||||
|
||||
class LowLevelServer(_Server[LifespanResultT, RequestT]):
|
||||
# TODO(sdkv2): _Server is now single-param generic (RequestT removed); Phase B
|
||||
# should revisit whether LowLevelServer needs its own request-type parameter.
|
||||
class LowLevelServer(_Server[LifespanResultT]):
|
||||
def __init__(self, fastmcp: FastMCP, *args: Any, **kwargs: Any):
|
||||
super().__init__(*args, **kwargs)
|
||||
# Store a weak reference to FastMCP to avoid circular references
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from contextlib import asynccontextmanager
|
|||
from typing import TYPE_CHECKING, Any, overload
|
||||
|
||||
import mcp_types
|
||||
from mcp_types import AnyUrl
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from fastmcp.prompts.base import Prompt, PromptResult
|
||||
from fastmcp.resources.base import Resource, ResourceResult
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@ from functools import partial
|
|||
from typing import TYPE_CHECKING, Any, TypeVar, overload
|
||||
|
||||
import mcp_types
|
||||
from mcp_types import AnyFunction
|
||||
|
||||
import fastmcp
|
||||
from fastmcp.prompts.base import Prompt
|
||||
from fastmcp.prompts.function_prompt import FunctionPrompt
|
||||
from fastmcp.server.auth.authorization import AuthCheck
|
||||
from fastmcp.server.tasks.config import TaskConfig
|
||||
from fastmcp.utilities.types import AnyFunction
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastmcp.server.providers.local_provider import LocalProvider
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from collections.abc import Callable
|
|||
from typing import TYPE_CHECKING, Any, TypeVar
|
||||
|
||||
import mcp_types
|
||||
from mcp_types import Annotations, AnyFunction
|
||||
from mcp_types import Annotations
|
||||
|
||||
import fastmcp
|
||||
from fastmcp.resources.base import Resource
|
||||
|
|
@ -19,6 +19,7 @@ from fastmcp.resources.function_resource import resource as standalone_resource
|
|||
from fastmcp.resources.template import ResourceTemplate
|
||||
from fastmcp.server.auth.authorization import AuthCheck
|
||||
from fastmcp.server.tasks.config import TaskConfig
|
||||
from fastmcp.utilities.types import AnyFunction
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from fastmcp.server.providers.local_provider import LocalProvider
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ from typing import (
|
|||
)
|
||||
|
||||
import mcp_types
|
||||
from mcp_types import AnyFunction, ToolAnnotations
|
||||
from mcp_types import ToolAnnotations
|
||||
|
||||
import fastmcp
|
||||
from fastmcp.exceptions import FastMCPDeprecationWarning
|
||||
|
|
@ -32,7 +32,7 @@ from fastmcp.server.auth.authorization import AuthCheck
|
|||
from fastmcp.server.tasks.config import TaskConfig
|
||||
from fastmcp.tools.base import Tool
|
||||
from fastmcp.tools.function_tool import FunctionTool
|
||||
from fastmcp.utilities.types import NotSet, NotSetT
|
||||
from fastmcp.utilities.types import AnyFunction, NotSet, NotSetT
|
||||
|
||||
try:
|
||||
from prefab_ui.app import PrefabApp as _PrefabApp
|
||||
|
|
|
|||
|
|
@ -17,9 +17,7 @@ import anyio
|
|||
import httpx
|
||||
import mcp_types
|
||||
from mcp import ServerSession
|
||||
from mcp.client.session import ClientSession
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp.shared.context import LifespanContextT, RequestContext
|
||||
from mcp.server.context import ServerRequestContext
|
||||
from mcp.shared.exceptions import MCPError
|
||||
from mcp_types import (
|
||||
METHOD_NOT_FOUND,
|
||||
|
|
@ -44,7 +42,7 @@ from fastmcp.resources import Resource, ResourceTemplate
|
|||
from fastmcp.resources.base import ResourceContent, ResourceResult
|
||||
from fastmcp.resources.template import expand_uri_template
|
||||
from fastmcp.server.context import Context
|
||||
from fastmcp.server.dependencies import get_context
|
||||
from fastmcp.server.dependencies import get_context, request_ctx
|
||||
from fastmcp.server.middleware import CallNext, Middleware, MiddlewareContext
|
||||
from fastmcp.server.providers.aggregate import ProviderErrorStrategy
|
||||
from fastmcp.server.providers.base import Provider
|
||||
|
|
@ -935,7 +933,7 @@ class FastMCPProxy(FastMCP):
|
|||
|
||||
|
||||
async def default_proxy_roots_handler(
|
||||
context: RequestContext[ClientSession, LifespanContextT],
|
||||
context: ServerRequestContext[Any, Any],
|
||||
) -> RootsList:
|
||||
"""Forward list roots request from remote server to proxy's connected clients."""
|
||||
ctx = get_context()
|
||||
|
|
@ -945,7 +943,7 @@ async def default_proxy_roots_handler(
|
|||
async def default_proxy_sampling_handler(
|
||||
messages: list[mcp_types.SamplingMessage],
|
||||
params: mcp_types.CreateMessageRequestParams,
|
||||
context: RequestContext[ClientSession, LifespanContextT],
|
||||
context: ServerRequestContext[Any, Any],
|
||||
) -> mcp_types.CreateMessageResult:
|
||||
"""Forward sampling request from remote server to proxy's connected clients."""
|
||||
ctx = get_context()
|
||||
|
|
@ -969,7 +967,7 @@ async def default_proxy_elicitation_handler(
|
|||
message: str,
|
||||
response_type: type,
|
||||
params: mcp_types.ElicitRequestParams,
|
||||
context: RequestContext[ClientSession, LifespanContextT],
|
||||
context: ServerRequestContext[Any, Any],
|
||||
) -> ElicitResult:
|
||||
"""Forward elicitation request from remote server to proxy's connected clients."""
|
||||
ctx = get_context()
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ from mcp.server.lowlevel.server import LifespanResultT
|
|||
from mcp.shared.exceptions import MCPError
|
||||
from mcp_types import (
|
||||
Annotations,
|
||||
AnyFunction,
|
||||
CallToolRequestParams,
|
||||
ToolAnnotations,
|
||||
)
|
||||
|
|
@ -82,7 +81,7 @@ from fastmcp.tools.function_tool import FunctionTool
|
|||
from fastmcp.tools.tool_transform import ToolTransformConfig
|
||||
from fastmcp.utilities.components import FastMCPComponent, _coerce_version
|
||||
from fastmcp.utilities.logging import get_logger
|
||||
from fastmcp.utilities.types import FastMCPBaseModel, NotSet, NotSetT
|
||||
from fastmcp.utilities.types import AnyFunction, FastMCPBaseModel, NotSet, NotSetT
|
||||
from fastmcp.utilities.versions import (
|
||||
VersionSpec,
|
||||
version_sort_key,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from opentelemetry.context import Context
|
||||
from opentelemetry.trace import Span, SpanKind, Status, StatusCode
|
||||
|
||||
|
|
@ -44,6 +43,8 @@ def get_session_span_attributes() -> dict[str, str]:
|
|||
|
||||
def _get_parent_trace_context() -> Context | None:
|
||||
"""Get parent trace context from request meta for distributed tracing."""
|
||||
from fastmcp.server.dependencies import request_ctx
|
||||
|
||||
try:
|
||||
req_ctx = request_ctx.get()
|
||||
if req_ctx and hasattr(req_ctx, "meta") and req_ctx.meta:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from enum import Enum
|
|||
from typing import Any, Literal, cast
|
||||
|
||||
import pydantic_core
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
import fastmcp
|
||||
from fastmcp import Client
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ class FileSystemSource(Source):
|
|||
The server object (or result of calling a factory function)
|
||||
"""
|
||||
# Avoid circular import by importing here
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
from fastmcp.server.server import FastMCP
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ class FileSystemSource(Source):
|
|||
A server instance
|
||||
"""
|
||||
# Avoid circular import by importing here
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
from fastmcp.server.server import FastMCP
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,11 @@ from typing_extensions import TypeVar
|
|||
|
||||
T = TypeVar("T", default=Any)
|
||||
|
||||
# TODO(sdkv2): the SDK's `mcp.types.AnyFunction` alias was removed with the
|
||||
# mcp.types module. FastMCP owns it now; keep the same `Callable[..., Any]`
|
||||
# meaning used by tool/prompt/resource decorators.
|
||||
AnyFunction: TypeAlias = Callable[..., Any]
|
||||
|
||||
# sentinel values for optional arguments
|
||||
NotSet = ...
|
||||
NotSetT: TypeAlias = EllipsisType
|
||||
|
|
|
|||
|
|
@ -296,14 +296,14 @@ class TestV1ServerAsync:
|
|||
"""Test that v1 server uses async stdio method."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
from fastmcp.cli.run import run_command
|
||||
|
||||
# Create a v1 FastMCP server file with both sync and async tools
|
||||
test_file = tmp_path / "v1_server.py"
|
||||
test_file.write_text("""
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP
|
||||
|
||||
mcp = FastMCP("V1Server")
|
||||
|
||||
|
|
@ -329,14 +329,14 @@ async def async_echo(text: str) -> str:
|
|||
"""Test that v1 server uses async http method."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
from fastmcp.cli.run import run_command
|
||||
|
||||
# Create a v1 FastMCP server file with both sync and async tools
|
||||
test_file = tmp_path / "v1_server.py"
|
||||
test_file.write_text("""
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP
|
||||
|
||||
mcp = FastMCP("V1Server")
|
||||
|
||||
|
|
@ -362,14 +362,14 @@ async def async_echo(text: str) -> str:
|
|||
"""Test that v1 server uses async streamable-http method."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
from fastmcp.cli.run import run_command
|
||||
|
||||
# Create a v1 FastMCP server file with both sync and async tools
|
||||
test_file = tmp_path / "v1_server.py"
|
||||
test_file.write_text("""
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP
|
||||
|
||||
mcp = FastMCP("V1Server")
|
||||
|
||||
|
|
@ -395,14 +395,14 @@ async def async_echo(text: str) -> str:
|
|||
"""Test that v1 server uses async sse method."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
from fastmcp.cli.run import run_command
|
||||
|
||||
# Create a v1 FastMCP server file with both sync and async tools
|
||||
test_file = tmp_path / "v1_server.py"
|
||||
test_file.write_text("""
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP
|
||||
|
||||
mcp = FastMCP("V1Server")
|
||||
|
||||
|
|
@ -428,14 +428,14 @@ async def async_echo(text: str) -> str:
|
|||
"""Test that v1 server uses streamable-http by default."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
from fastmcp.cli.run import run_command
|
||||
|
||||
# Create a v1 FastMCP server file with both sync and async tools
|
||||
test_file = tmp_path / "v1_server.py"
|
||||
test_file.write_text("""
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP
|
||||
|
||||
mcp = FastMCP("V1Server")
|
||||
|
||||
|
|
@ -461,14 +461,14 @@ async def async_echo(text: str) -> str:
|
|||
"""Test that v1 server receives host/port settings."""
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
from fastmcp.cli.run import run_command
|
||||
|
||||
# Create a v1 FastMCP server file with both sync and async tools
|
||||
test_file = tmp_path / "v1_server.py"
|
||||
test_file.write_text("""
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP
|
||||
|
||||
mcp = FastMCP("V1Server")
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ class TestInferTransport:
|
|||
|
||||
def test_infer_fastmcp_v1_server(self):
|
||||
"""FastMCP 1.0 server instances should infer to FastMCPTransport."""
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1
|
||||
|
||||
server = FastMCP1()
|
||||
transport = infer_transport(server)
|
||||
|
|
|
|||
|
|
@ -11,12 +11,11 @@ from unittest.mock import MagicMock
|
|||
|
||||
from mcp.server.auth.middleware.auth_context import auth_context_var
|
||||
from mcp.server.auth.middleware.bearer_auth import AuthenticatedUser
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp.shared.context import RequestContext
|
||||
from mcp.server.context import ServerRequestContext as RequestContext
|
||||
from starlette.requests import Request
|
||||
|
||||
from fastmcp.server.auth import AccessToken
|
||||
from fastmcp.server.dependencies import get_access_token
|
||||
from fastmcp.server.dependencies import get_access_token, request_ctx
|
||||
|
||||
|
||||
class TestStaleAccessToken:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ from unittest.mock import MagicMock
|
|||
|
||||
import pytest
|
||||
from anyio import create_task_group
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp_types import LoggingLevel
|
||||
|
||||
from fastmcp import Client, Context, FastMCP
|
||||
|
|
@ -14,7 +13,7 @@ from fastmcp.client.logging import LogMessage
|
|||
from fastmcp.client.transports import FastMCPTransport
|
||||
from fastmcp.exceptions import ToolError
|
||||
from fastmcp.server.context import _current_context
|
||||
from fastmcp.server.dependencies import get_server
|
||||
from fastmcp.server.dependencies import get_server, request_ctx
|
||||
from fastmcp.server.elicitation import AcceptedElicitation
|
||||
from fastmcp.server.providers.proxy import (
|
||||
FastMCPProxy,
|
||||
|
|
|
|||
|
|
@ -43,8 +43,9 @@ class TestParseModelPreferences:
|
|||
class TestSessionId:
|
||||
def test_session_id_with_http_headers(self, context):
|
||||
"""Test that session_id returns the value from mcp-session-id header."""
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp.shared.context import RequestContext
|
||||
from mcp.server.context import ServerRequestContext as RequestContext
|
||||
|
||||
from fastmcp.server.dependencies import request_ctx
|
||||
|
||||
mock_headers = {"mcp-session-id": "test-session-123"}
|
||||
|
||||
|
|
@ -71,8 +72,9 @@ class TestSessionId:
|
|||
"""
|
||||
import uuid
|
||||
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp.shared.context import RequestContext
|
||||
from mcp.server.context import ServerRequestContext as RequestContext
|
||||
|
||||
from fastmcp.server.dependencies import request_ctx
|
||||
|
||||
mock_session = MagicMock(wraps={})
|
||||
token = request_ctx.set(
|
||||
|
|
@ -338,8 +340,9 @@ class TestContextMeta:
|
|||
|
||||
def test_request_context_meta_access(self, context):
|
||||
"""Test that meta can be accessed from request context."""
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp.shared.context import RequestContext
|
||||
from mcp.server.context import ServerRequestContext as RequestContext
|
||||
|
||||
from fastmcp.server.dependencies import request_ctx
|
||||
|
||||
# Create a mock meta object with attributes
|
||||
class MockMeta:
|
||||
|
|
@ -370,8 +373,9 @@ class TestContextMeta:
|
|||
|
||||
def test_request_context_meta_none(self, context):
|
||||
"""Test that context handles None meta gracefully."""
|
||||
from mcp.server.lowlevel.server import request_ctx
|
||||
from mcp.shared.context import RequestContext
|
||||
from mcp.server.context import ServerRequestContext as RequestContext
|
||||
|
||||
from fastmcp.server.dependencies import request_ctx
|
||||
|
||||
token = request_ctx.set(
|
||||
RequestContext(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ from collections.abc import Sequence
|
|||
from typing import Any
|
||||
|
||||
import pytest
|
||||
from mcp_types import AnyUrl, TextContent
|
||||
from mcp_types import TextContent
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from fastmcp import FastMCP
|
||||
from fastmcp.prompts.base import Prompt
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from mcp_types import (
|
|||
TextContent,
|
||||
TextResourceContents,
|
||||
)
|
||||
from pydantic import AnyUrl, BaseModel
|
||||
from pydantic import BaseModel
|
||||
|
||||
from fastmcp.tools.base import Tool, _convert_to_content
|
||||
from fastmcp.utilities.types import Audio, File, Image
|
||||
|
|
@ -110,14 +110,14 @@ class TestConvertResultToContent:
|
|||
ResourceLink(
|
||||
type="resource_link",
|
||||
name="test resource",
|
||||
uri=AnyUrl("resource://test"),
|
||||
uri="resource://test",
|
||||
)
|
||||
),
|
||||
(
|
||||
EmbeddedResource(
|
||||
type="resource",
|
||||
resource=TextResourceContents(
|
||||
uri=AnyUrl("resource://test"),
|
||||
uri="resource://test",
|
||||
mime_type="text/plain",
|
||||
text="resource content",
|
||||
),
|
||||
|
|
@ -158,7 +158,7 @@ class TestConvertResultToContent:
|
|||
EmbeddedResource(
|
||||
type="resource",
|
||||
resource=BlobResourceContents(
|
||||
uri=AnyUrl("file:///resource.octet-stream"),
|
||||
uri="file:///resource.octet-stream",
|
||||
blob="ZmlsZWRhdGE=",
|
||||
mime_type="application/octet-stream",
|
||||
),
|
||||
|
|
@ -187,12 +187,12 @@ class TestConvertResultToContent:
|
|||
ResourceLink(
|
||||
type="resource_link",
|
||||
name="test resource",
|
||||
uri=AnyUrl("resource://test"),
|
||||
uri="resource://test",
|
||||
),
|
||||
EmbeddedResource(
|
||||
type="resource",
|
||||
resource=TextResourceContents(
|
||||
uri=AnyUrl("resource://test"),
|
||||
uri="resource://test",
|
||||
mime_type="text/plain",
|
||||
text="resource content",
|
||||
),
|
||||
|
|
@ -216,13 +216,13 @@ class TestConvertResultToContent:
|
|||
),
|
||||
ResourceLink(
|
||||
name="test resource",
|
||||
uri=AnyUrl("resource://test"),
|
||||
uri="resource://test",
|
||||
type="resource_link",
|
||||
),
|
||||
EmbeddedResource(
|
||||
type="resource",
|
||||
resource=TextResourceContents(
|
||||
uri=AnyUrl("resource://test"),
|
||||
uri="resource://test",
|
||||
mime_type="text/plain",
|
||||
text="resource content",
|
||||
),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import importlib.metadata
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
import fastmcp
|
||||
from fastmcp import Client, FastMCP
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import importlib.metadata
|
||||
|
||||
from mcp.server.fastmcp import FastMCP as FastMCP1x
|
||||
from mcp.server.mcpserver import MCPServer as FastMCP1x
|
||||
|
||||
import fastmcp
|
||||
from fastmcp import FastMCP
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ from typing import cast
|
|||
|
||||
import pytest
|
||||
from mcp_types import BlobResourceContents, TextResourceContents
|
||||
from pydantic import AnyUrl
|
||||
|
||||
from fastmcp import Client, FastMCP
|
||||
from fastmcp.server.providers.skills import SkillsDirectoryProvider
|
||||
|
|
@ -38,12 +37,12 @@ class FakeResourceReader:
|
|||
|
||||
|
||||
def text_resource(uri: str, text: str) -> TextResourceContents:
|
||||
return TextResourceContents(uri=AnyUrl(uri), text=text)
|
||||
return TextResourceContents(uri=uri, text=text)
|
||||
|
||||
|
||||
def blob_resource(uri: str, data: bytes) -> BlobResourceContents:
|
||||
return BlobResourceContents(
|
||||
uri=AnyUrl(uri),
|
||||
uri=uri,
|
||||
blob=base64.b64encode(data).decode(),
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue