Rename FastMCP to MCPServer (#1951)

This commit is contained in:
Marcelo Trylesinski 2026-01-25 14:45:52 +01:00 • committed by GitHub
commit 65c614e48e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 713 additions and 693 deletions

View file

@ -9,7 +9,7 @@ from inline_snapshot import snapshot
import mcp.types as types
from mcp.client.client import Client
from mcp.server import Server
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
from mcp.types import (
CallToolResult,
EmptyResult,
@ -68,9 +68,9 @@ def simple_server() -> Server:
@pytest.fixture
def app() -> FastMCP:
"""Create a FastMCP server for testing."""
server = FastMCP("test")
def app() -> MCPServer:
"""Create an MCPServer server for testing."""
server = MCPServer("test")
@server.tool()
def greet(name: str) -> str:
@ -90,7 +90,7 @@ def app() -> FastMCP:
return server
async def test_client_is_initialized(app: FastMCP):
async def test_client_is_initialized(app: MCPServer):
"""Test that the client is initialized after entering context."""
async with Client(app) as client:
assert client.server_capabilities == snapshot(
@ -114,13 +114,13 @@ async def test_client_with_simple_server(simple_server: Server):
)
async def test_client_send_ping(app: FastMCP):
async def test_client_send_ping(app: MCPServer):
async with Client(app) as client:
result = await client.send_ping()
assert result == snapshot(EmptyResult())
async def test_client_list_tools(app: FastMCP):
async def test_client_list_tools(app: MCPServer):
async with Client(app) as client:
result = await client.list_tools()
assert result == snapshot(
@ -147,7 +147,7 @@ async def test_client_list_tools(app: FastMCP):
)
async def test_client_call_tool(app: FastMCP):
async def test_client_call_tool(app: MCPServer):
async with Client(app) as client:
result = await client.call_tool("greet", {"name": "World"})
assert result == snapshot(
@ -158,7 +158,7 @@ async def test_client_call_tool(app: FastMCP):
)
async def test_read_resource(app: FastMCP):
async def test_read_resource(app: MCPServer):
"""Test reading a resource."""
async with Client(app) as client:
result = await client.read_resource("test://resource")
@ -169,7 +169,7 @@ async def test_read_resource(app: FastMCP):
)
async def test_get_prompt(app: FastMCP):
async def test_get_prompt(app: MCPServer):
"""Test getting a prompt."""
async with Client(app) as client:
result = await client.get_prompt("greeting_prompt", {"name": "Alice"})
@ -181,14 +181,14 @@ async def test_get_prompt(app: FastMCP):
)
def test_client_session_property_before_enter(app: FastMCP):
def test_client_session_property_before_enter(app: MCPServer):
"""Test that accessing session before context manager raises RuntimeError."""
client = Client(app)
with pytest.raises(RuntimeError, match="Client must be used within an async context manager"):
client.session
async def test_client_reentry_raises_runtime_error(app: FastMCP):
async def test_client_reentry_raises_runtime_error(app: MCPServer):
"""Test that reentering a client raises RuntimeError."""
async with Client(app) as client:
with pytest.raises(RuntimeError, match="Client is already entered"):
@ -237,7 +237,7 @@ async def test_client_set_logging_level(simple_server: Server):
assert result == snapshot(EmptyResult())
async def test_client_list_resources_with_params(app: FastMCP):
async def test_client_list_resources_with_params(app: MCPServer):
"""Test listing resources with params parameter."""
async with Client(app) as client:
result = await client.list_resources()
@ -255,14 +255,14 @@ async def test_client_list_resources_with_params(app: FastMCP):
)
async def test_client_list_resource_templates(app: FastMCP):
async def test_client_list_resource_templates(app: MCPServer):
"""Test listing resource templates with params parameter."""
async with Client(app) as client:
result = await client.list_resource_templates()
assert result == snapshot(ListResourceTemplatesResult(resource_templates=[]))
async def test_list_prompts(app: FastMCP):
async def test_list_prompts(app: MCPServer):
"""Test listing prompts with params parameter."""
async with Client(app) as client:
result = await client.list_prompts()

View file

@ -5,7 +5,7 @@ import pytest
import mcp.types as types
from mcp import Client
from mcp.server import Server
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
from mcp.types import ListToolsRequest, ListToolsResult
from .conftest import StreamSpyCollection
@ -16,7 +16,7 @@ pytestmark = pytest.mark.anyio
@pytest.fixture
async def full_featured_server():
"""Create a server with tools, resources, prompts, and templates."""
server = FastMCP("test")
server = MCPServer("test")
# pragma: no cover on handlers below - these exist only to register items with the
# server so list_* methods return results. The handlers themselves are never called
@ -55,7 +55,7 @@ async def full_featured_server():
)
async def test_list_methods_params_parameter(
stream_spy: Callable[[], StreamSpyCollection],
full_featured_server: FastMCP,
full_featured_server: MCPServer,
method_name: str,
request_method: str,
):
@ -95,7 +95,7 @@ async def test_list_methods_params_parameter(
async def test_list_tools_with_strict_server_validation(
full_featured_server: FastMCP,
full_featured_server: MCPServer,
):
"""Test pagination with a server that validates request format strictly."""
async with Client(full_featured_server) as client:

View file

@ -3,8 +3,8 @@ from pydantic import FileUrl
from mcp import Client
from mcp.client.session import ClientSession
from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.server import Context
from mcp.server.mcpserver import MCPServer
from mcp.server.mcpserver.server import Context
from mcp.server.session import ServerSession
from mcp.shared.context import RequestContext
from mcp.types import ListRootsResult, Root, TextContent
@ -12,7 +12,7 @@ from mcp.types import ListRootsResult, Root, TextContent
@pytest.mark.anyio
async def test_list_roots_callback():
server = FastMCP("test")
server = MCPServer("test")
callback_return = ListRootsResult(
roots=[

View file

@ -4,7 +4,7 @@ import pytest
import mcp.types as types
from mcp import Client
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
from mcp.shared.session import RequestResponder
from mcp.types import (
LoggingMessageNotificationParams,
@ -22,7 +22,7 @@ class LoggingCollector:
@pytest.mark.anyio
async def test_logging_callback():
server = FastMCP("test")
server = MCPServer("test")
logging_collector = LoggingCollector()
# Create a simple test tool

View file

@ -2,7 +2,7 @@ import pytest
from mcp import Client
from mcp.client.session import ClientSession
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
from mcp.shared.context import RequestContext
from mcp.types import (
CreateMessageRequestParams,
@ -16,7 +16,7 @@ from mcp.types import (
@pytest.mark.anyio
async def test_sampling_callback():
server = FastMCP("test")
server = MCPServer("test")
callback_return = CreateMessageResult(
role="assistant",
@ -60,7 +60,7 @@ async def test_sampling_callback():
@pytest.mark.anyio
async def test_create_message_backwards_compat_single_content():
"""Test backwards compatibility: create_message without tools returns single content."""
server = FastMCP("test")
server = MCPServer("test")
# Callback returns single content (text)
callback_return = CreateMessageResult(

View file

@ -5,7 +5,7 @@ import pytest
from mcp import Client
from mcp.client._memory import InMemoryTransport
from mcp.server import Server
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
from mcp.types import Resource
@ -30,9 +30,9 @@ def simple_server() -> Server:
@pytest.fixture
def fastmcp_server() -> FastMCP:
"""Create a FastMCP server for testing."""
server = FastMCP("test")
def mcpserver_server() -> MCPServer:
"""Create an MCPServer server for testing."""
server = MCPServer("test")
@server.tool()
def greet(name: str) -> str:
@ -58,40 +58,40 @@ async def test_with_server(simple_server: Server):
assert write_stream is not None
async def test_with_fastmcp(fastmcp_server: FastMCP):
"""Test creating transport with a FastMCP instance."""
transport = InMemoryTransport(fastmcp_server)
async def test_with_mcpserver(mcpserver_server: MCPServer):
"""Test creating transport with an MCPServer instance."""
transport = InMemoryTransport(mcpserver_server)
async with transport.connect() as (read_stream, write_stream):
assert read_stream is not None
assert write_stream is not None
async def test_server_is_running(fastmcp_server: FastMCP):
async def test_server_is_running(mcpserver_server: MCPServer):
"""Test that the server is running and responding to requests."""
async with Client(fastmcp_server) as client:
async with Client(mcpserver_server) as client:
assert client.server_capabilities is not None
async def test_list_tools(fastmcp_server: FastMCP):
async def test_list_tools(mcpserver_server: MCPServer):
"""Test listing tools through the transport."""
async with Client(fastmcp_server) as client:
async with Client(mcpserver_server) as client:
tools_result = await client.list_tools()
assert len(tools_result.tools) > 0
tool_names = [t.name for t in tools_result.tools]
assert "greet" in tool_names
async def test_call_tool(fastmcp_server: FastMCP):
async def test_call_tool(mcpserver_server: MCPServer):
"""Test calling a tool through the transport."""
async with Client(fastmcp_server) as client:
async with Client(mcpserver_server) as client:
result = await client.call_tool("greet", {"name": "World"})
assert result is not None
assert len(result.content) > 0
assert "Hello, World!" in str(result.content[0])
async def test_raise_exceptions(fastmcp_server: FastMCP):
async def test_raise_exceptions(mcpserver_server: MCPServer):
"""Test that raise_exceptions parameter is passed through."""
transport = InMemoryTransport(fastmcp_server, raise_exceptions=True)
transport = InMemoryTransport(mcpserver_server, raise_exceptions=True)
async with transport.connect() as (read_stream, _write_stream):
assert read_stream is not None

View file

@ -1,12 +1,12 @@
import pytest
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
pytestmark = pytest.mark.anyio
async def test_list_tools_returns_all_tools():
mcp = FastMCP("TestTools")
mcp = MCPServer("TestTools")
# Create 100 tools with unique names
num_tools = 100

View file

@ -43,13 +43,13 @@ async def test_lifespan_cleanup_executed():
Path(startup_marker).unlink()
Path(cleanup_marker).unlink()
# Create a minimal MCP server using FastMCP that tracks lifecycle
# Create a minimal MCP server using MCPServer that tracks lifecycle
server_code = textwrap.dedent(f"""
import asyncio
import sys
from pathlib import Path
from contextlib import asynccontextmanager
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
STARTUP_MARKER = {escape_path_for_python(startup_marker)}
CLEANUP_MARKER = {escape_path_for_python(cleanup_marker)}
@ -64,7 +64,7 @@ async def test_lifespan_cleanup_executed():
# This cleanup code now runs properly during shutdown
Path(CLEANUP_MARKER).write_text("cleaned up")
mcp = FastMCP("test-server", lifespan=lifespan)
mcp = MCPServer("test-server", lifespan=lifespan)
@mcp.tool()
def echo(text: str) -> str:
@ -156,7 +156,7 @@ async def test_stdin_close_triggers_cleanup():
import sys
from pathlib import Path
from contextlib import asynccontextmanager
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
STARTUP_MARKER = {escape_path_for_python(startup_marker)}
CLEANUP_MARKER = {escape_path_for_python(cleanup_marker)}
@ -171,7 +171,7 @@ async def test_stdin_close_triggers_cleanup():
# This cleanup code runs when stdin closes, enabling graceful shutdown
Path(CLEANUP_MARKER).write_text("cleaned up")
mcp = FastMCP("test-server", lifespan=lifespan)
mcp = MCPServer("test-server", lifespan=lifespan)
@mcp.tool()
def echo(text: str) -> str:

View file

@ -1,13 +1,13 @@
import pytest
from mcp import types
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
@pytest.mark.anyio
async def test_resource_templates():
# Create an MCP server
mcp = FastMCP("Demo")
mcp = MCPServer("Demo")
# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
@ -23,7 +23,7 @@ async def test_resource_templates():
# Get the list of resource templates using the underlying server
# Note: list_resource_templates() returns a decorator that wraps the handler
# The handler returns a ServerResult with a ListResourceTemplatesResult inside
result = await mcp._mcp_server.request_handlers[types.ListResourceTemplatesRequest](
result = await mcp._lowlevel_server.request_handlers[types.ListResourceTemplatesRequest](
types.ListResourceTemplatesRequest(params=None)
)
assert isinstance(result, types.ListResourceTemplatesResult)

View file

@ -2,7 +2,7 @@
import pytest
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
from mcp.types import Icon
pytestmark = pytest.mark.anyio
@ -19,7 +19,7 @@ async def test_icons_and_website_url():
)
# Create server with website URL and icon
mcp = FastMCP("TestServer", website_url="https://example.com", icons=[test_icon])
mcp = MCPServer("TestServer", website_url="https://example.com", icons=[test_icon])
# Create tool with icon
@mcp.tool(icons=[test_icon])
@ -100,7 +100,7 @@ async def test_multiple_icons():
icon2 = Icon(src="data:image/png;base64,icon2", mime_type="image/png", sizes=["32x32"])
icon3 = Icon(src="data:image/png;base64,icon3", mime_type="image/png", sizes=["64x64"])
mcp = FastMCP("MultiIconServer")
mcp = MCPServer("MultiIconServer")
# Create tool with multiple icons
@mcp.tool(icons=[icon1, icon2, icon3])
@ -122,7 +122,7 @@ async def test_multiple_icons():
async def test_no_icons_or_website():
"""Test that server works without icons or websiteUrl."""
mcp = FastMCP("BasicServer")
mcp = MCPServer("BasicServer")
@mcp.tool()
def basic_tool() -> str: # pragma: no cover

View file

@ -1,7 +1,7 @@
import pytest
from mcp import Client
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
from mcp.types import (
ListResourceTemplatesResult,
TextResourceContents,
@ -11,7 +11,7 @@ from mcp.types import (
@pytest.mark.anyio
async def test_resource_template_edge_cases():
"""Test server-side resource template validation"""
mcp = FastMCP("Demo")
mcp = MCPServer("Demo")
# Test case 1: Template with multiple parameters
@mcp.resource("resource://users/{user_id}/posts/{post_id}")
@ -64,7 +64,7 @@ async def test_resource_template_edge_cases():
@pytest.mark.anyio
async def test_resource_template_client_interaction():
"""Test client-side resource template interaction"""
mcp = FastMCP("Demo")
mcp = MCPServer("Demo")
# Register some templated resources
@mcp.resource("resource://users/{user_id}/posts/{post_id}")

View file

@ -3,16 +3,16 @@ import base64
import pytest
from mcp import Client, types
from mcp.server.fastmcp import FastMCP
from mcp.server.lowlevel import Server
from mcp.server.lowlevel.helper_types import ReadResourceContents
from mcp.server.mcpserver import MCPServer
pytestmark = pytest.mark.anyio
async def test_fastmcp_resource_mime_type():
async def test_mcpserver_resource_mime_type():
"""Test that mime_type parameter is respected for resources."""
mcp = FastMCP("test")
mcp = MCPServer("test")
# Create a small test image as bytes
image_bytes = b"fake_image_data"

View file

@ -7,14 +7,14 @@ with parameters like 'text/html;profile=mcp-app' which are valid per RFC 2045.
import pytest
from mcp import Client
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
pytestmark = pytest.mark.anyio
async def test_mime_type_with_parameters():
"""Test that MIME types with parameters are accepted (RFC 2045)."""
mcp = FastMCP("test")
mcp = MCPServer("test")
# This should NOT raise a validation error
@mcp.resource("ui://widget", mime_type="text/html;profile=mcp-app")
@ -28,7 +28,7 @@ async def test_mime_type_with_parameters():
async def test_mime_type_with_parameters_and_space():
"""Test MIME type with space after semicolon."""
mcp = FastMCP("test")
mcp = MCPServer("test")
@mcp.resource("data://json", mime_type="application/json; charset=utf-8")
def data() -> str:
@ -41,7 +41,7 @@ async def test_mime_type_with_parameters_and_space():
async def test_mime_type_with_multiple_parameters():
"""Test MIME type with multiple parameters."""
mcp = FastMCP("test")
mcp = MCPServer("test")
@mcp.resource("data://multi", mime_type="text/plain; charset=utf-8; format=fixed")
def data() -> str:
@ -54,7 +54,7 @@ async def test_mime_type_with_multiple_parameters():
async def test_mime_type_preserved_in_read_resource():
"""Test that MIME type with parameters is preserved when reading resource."""
mcp = FastMCP("test")
mcp = MCPServer("test")
@mcp.resource("ui://my-widget", mime_type="text/html;profile=mcp-app")
def my_widget() -> str:

View file

@ -2,7 +2,7 @@ from unittest.mock import AsyncMock, MagicMock
import pytest
from mcp.server.fastmcp import Context
from mcp.server.mcpserver import Context
from mcp.shared.context import RequestContext
pytestmark = pytest.mark.anyio
@ -24,7 +24,7 @@ async def test_progress_token_zero_first_call():
)
# Create context with our mocks
ctx = Context(request_context=request_context, fastmcp=MagicMock())
ctx = Context(request_context=request_context, mcp_server=MagicMock())
# Test progress reporting
await ctx.report_progress(0, 10) # First call with 0

View file

@ -2,12 +2,12 @@ import anyio
import pytest
from mcp import Client
from mcp.server.fastmcp import FastMCP
from mcp.server.mcpserver import MCPServer
@pytest.mark.anyio
async def test_messages_are_executed_concurrently_tools():
server = FastMCP("test")
server = MCPServer("test")
event = anyio.Event()
tool_started = anyio.Event()
call_order: list[str] = []
@ -48,7 +48,7 @@ async def test_messages_are_executed_concurrently_tools():
@pytest.mark.anyio
async def test_messages_are_executed_concurrently_tools_and_resources():
server = FastMCP("test")
server = MCPServer("test")
event = anyio.Event()
tool_started = anyio.Event()
call_order: list[str] = []

View file

@ -2,7 +2,7 @@ from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from dataclasses import dataclass
from mcp.server.fastmcp import Context, FastMCP
from mcp.server.mcpserver import Context, MCPServer
from mcp.server.session import ServerSession
@ -19,7 +19,7 @@ class Database: # Replace with your actual DB type
# Create a named server
mcp = FastMCP("My App")
mcp = MCPServer("My App")
@dataclass
@ -28,7 +28,7 @@ class AppContext:
@asynccontextmanager
async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]: # pragma: no cover
async def app_lifespan(server: MCPServer) -> AsyncIterator[AppContext]: # pragma: no cover
"""Manage application lifecycle with type-safe context"""
# Initialize on startup
db = await Database.connect()
@ -40,7 +40,7 @@ async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]: # pragma:
# Pass lifespan to server
mcp = FastMCP("My App", lifespan=app_lifespan)
mcp = MCPServer("My App", lifespan=app_lifespan)
# Access type-safe lifespan context in tools

View file

@ -3,7 +3,7 @@
Regression test for https://github.com/modelcontextprotocol/python-sdk/issues/973
"""
from mcp.server.fastmcp.resources import ResourceTemplate
from mcp.server.mcpserver.resources import ResourceTemplate
def test_template_matches_decodes_space():

View file

@ -16,7 +16,7 @@ from starlette.applications import Starlette
from mcp.server.auth.provider import AuthorizeError, RegistrationError, TokenError
from mcp.server.auth.routes import create_auth_routes
from mcp.server.auth.settings import ClientRegistrationOptions, RevocationOptions
from tests.server.fastmcp.auth.test_auth_integration import MockOAuthProvider
from tests.server.mcpserver.auth.test_auth_integration import MockOAuthProvider
@pytest.fixture

View file

View file

@ -0,0 +1 @@
"""Tests for the MCP server auth components."""

Some files were not shown because too many files have changed in this diff Show more