Add sdkv2 import shims pending server/client port

This commit is contained in:
Jeremiah Lowin 2026-07-05 18:26:15 -04:00
commit 42e72d71e9
No known key found for this signature in database
34 changed files with 125 additions and 75 deletions

View file

@ -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

View file

@ -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

View 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]

View file

@ -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"]

View file

@ -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]

View file

@ -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

View file

@ -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"]

View file

@ -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 (

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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",

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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,

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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")

View file

@ -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)

View file

@ -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:

View file

@ -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,

View file

@ -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(

View file

@ -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

View file

@ -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",
),

View file

@ -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

View file

@ -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

View file

@ -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(),
)