refactor: move inline imports to module level (#1893)

This commit is contained in:
Max Isbey 2026-01-16 15:54:08 +01:00 • committed by GitHub
commit 5d80f4efc8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 58 additions and 122 deletions

View file

@ -2,6 +2,9 @@
Tests for OAuth error handling in the auth handlers.
"""
import base64
import hashlib
import secrets
import unittest.mock
from typing import Any
from urllib.parse import parse_qs, urlparse
@ -14,6 +17,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
@ -25,8 +29,6 @@ def oauth_provider():
@pytest.fixture
def app(oauth_provider: MockOAuthProvider):
from mcp.server.auth.settings import ClientRegistrationOptions, RevocationOptions
# Enable client registration
client_registration_options = ClientRegistrationOptions(enabled=True)
revocation_options = RevocationOptions(enabled=True)
@ -53,10 +55,6 @@ def client(app: Starlette):
@pytest.fixture
def pkce_challenge():
"""Create a PKCE challenge with code_verifier and code_challenge."""
import base64
import hashlib
import secrets
# Generate a code verifier
code_verifier = secrets.token_urlsafe(64)[:128]

View file

@ -2,6 +2,8 @@
Integration tests for MCP Oauth Protected Resource.
"""
from urllib.parse import urlparse
import httpx
import pytest
from inline_snapshot import snapshot
@ -159,8 +161,6 @@ class TestRouteConsistency:
)
# Extract path from metadata URL
from urllib.parse import urlparse
metadata_path = urlparse(str(metadata_url)).path
# Verify consistency
@ -181,8 +181,6 @@ class TestRouteConsistency:
# Test URL generation
metadata_url = build_resource_metadata_url(resource_url_obj)
from urllib.parse import urlparse
url_path = urlparse(str(metadata_url)).path
# Test route creation

View file

@ -1258,8 +1258,6 @@ class TestAuthEndpoints:
)
# Send base64 without colon (invalid format)
import base64
invalid_creds = base64.b64encode(b"no-colon-here").decode()
response = await test_client.post(
"/token",
@ -1306,8 +1304,6 @@ class TestAuthEndpoints:
)
# Send different client_id in Basic auth header
import base64
wrong_creds = base64.b64encode(f"wrong-client-id:{client_info['client_secret']}".encode()).decode()
response = await test_client.post(
"/token",

View file

@ -5,13 +5,14 @@
# pyright: reportUnknownLambdaType=false
from collections.abc import Callable
from dataclasses import dataclass
from typing import Annotated, Any, Final, TypedDict
from typing import Annotated, Any, Final, NamedTuple, TypedDict
import annotated_types
import pytest
from dirty_equals import IsPartialDict
from pydantic import BaseModel, Field
from mcp.server.fastmcp.exceptions import InvalidSignature
from mcp.server.fastmcp.utilities.func_metadata import func_metadata
from mcp.types import CallToolResult
@ -558,7 +559,6 @@ async def test_str_annotation_runtime_validation():
def test_structured_output_requires_return_annotation():
"""Test that structured_output=True requires a return annotation"""
from mcp.server.fastmcp.exceptions import InvalidSignature
def func_no_annotation(): # pragma: no cover
return "hello"
@ -881,8 +881,6 @@ def test_tool_call_result_annotated_is_structured_and_invalid():
def test_tool_call_result_in_optional_is_rejected():
"""Test that Optional[CallToolResult] raises InvalidSignature"""
from mcp.server.fastmcp.exceptions import InvalidSignature
def func_optional_call_tool_result() -> CallToolResult | None: # pragma: no cover
return CallToolResult(content=[])
@ -896,8 +894,6 @@ def test_tool_call_result_in_optional_is_rejected():
def test_tool_call_result_in_union_is_rejected():
"""Test that Union[str, CallToolResult] raises InvalidSignature"""
from mcp.server.fastmcp.exceptions import InvalidSignature
def func_union_call_tool_result() -> str | CallToolResult: # pragma: no cover
return CallToolResult(content=[])
@ -910,7 +906,6 @@ def test_tool_call_result_in_union_is_rejected():
def test_tool_call_result_in_pipe_union_is_rejected():
"""Test that str | CallToolResult raises InvalidSignature"""
from mcp.server.fastmcp.exceptions import InvalidSignature
def func_pipe_union_call_tool_result() -> str | CallToolResult: # pragma: no cover
return CallToolResult(content=[])
@ -985,9 +980,6 @@ def test_structured_output_nested_models():
def test_structured_output_unserializable_type_error():
"""Test error when structured_output=True is used with unserializable types"""
from typing import NamedTuple
from mcp.server.fastmcp.exceptions import InvalidSignature
# Test with a class that has non-serializable default values
class ConfigWithCallable:
@ -1185,8 +1177,6 @@ def test_basemodel_reserved_names_with_json_preparsing():
def test_disallowed_type_qualifier():
from mcp.server.fastmcp.exceptions import InvalidSignature
def func_disallowed_qualifier() -> Final[int]: # type: ignore
pass # pragma: no cover

View file

@ -51,8 +51,10 @@ from mcp.types import (
NotificationParams,
ProgressNotification,
ProgressNotificationParams,
PromptReference,
ReadResourceResult,
ResourceListChangedNotification,
ResourceTemplateReference,
ServerNotification,
ServerRequest,
TextContent,
@ -583,8 +585,6 @@ async def test_completion(server_transport: str, server_url: str) -> None:
assert result.capabilities.prompts is not None
# Test resource completion
from mcp.types import ResourceTemplateReference
completion_result = await session.complete(
ref=ResourceTemplateReference(type="ref/resource", uri="github://repos/{owner}/{repo}"),
argument={"name": "repo", "value": ""},
@ -600,8 +600,6 @@ async def test_completion(server_transport: str, server_url: str) -> None:
assert "specification" in completion_result.completion.values
# Test prompt completion
from mcp.types import PromptReference
completion_result = await session.complete(
ref=PromptReference(type="ref/prompt", name="review_code"),
argument={"name": "language", "value": "py"},
@ -644,8 +642,6 @@ async def test_fastmcp_quickstart(server_transport: str, server_url: str) -> Non
assert tool_result.content[0].text == "30"
# Test greeting resource directly
from pydantic import AnyUrl
resource_result = await session.read_resource(AnyUrl("greeting://Alice"))
assert len(resource_result.contents) == 1
assert isinstance(resource_result.contents[0], TextResourceContents)

View file

@ -5,9 +5,11 @@ from unittest.mock import patch
import pytest
from pydantic import BaseModel
from starlette.applications import Starlette
from starlette.routing import Mount, Route
from mcp.server.fastmcp import Context, FastMCP
from mcp.server.fastmcp.exceptions import ToolError
from mcp.server.fastmcp.prompts.base import Message, UserMessage
from mcp.server.fastmcp.resources import FileResource, FunctionResource
from mcp.server.fastmcp.utilities.types import Audio, Image
@ -51,8 +53,6 @@ class TestServer:
@pytest.mark.anyio
async def test_sse_app_returns_starlette_app(self):
"""Test that sse_app returns a Starlette application with correct routes."""
from starlette.applications import Starlette
mcp = FastMCP("test", host="0.0.0.0") # Use 0.0.0.0 to avoid auto DNS protection
app = mcp.sse_app()
@ -617,8 +617,6 @@ class TestServerTools:
@pytest.mark.anyio
async def test_remove_nonexistent_tool(self):
"""Test that removing a non-existent tool raises ToolError."""
from mcp.server.fastmcp.exceptions import ToolError
mcp = FastMCP()
with pytest.raises(ToolError, match="Unknown tool: nonexistent"):

View file

@ -2,10 +2,11 @@
import anyio
import pytest
from pydantic import BaseModel, Field
from mcp import types
from mcp.client.session import ClientSession
from mcp.server.elicitation import CancelledElicitation, DeclinedElicitation
from mcp.server.elicitation import CancelledElicitation, DeclinedElicitation, elicit_url
from mcp.server.fastmcp import Context, FastMCP
from mcp.server.session import ServerSession
from mcp.shared.context import RequestContext
@ -110,8 +111,6 @@ async def test_url_elicitation_cancel():
@pytest.mark.anyio
async def test_url_elicitation_helper_function():
"""Test the elicit_url helper function."""
from mcp.server.elicitation import elicit_url
mcp = FastMCP(name="URLElicitationHelperServer")
@mcp.tool(description="Tool using elicit_url helper")
@ -180,8 +179,6 @@ async def test_url_no_content_in_response():
@pytest.mark.anyio
async def test_form_mode_still_works():
"""Ensure form mode elicitation still works after SEP 1036."""
from pydantic import BaseModel, Field
mcp = FastMCP(name="FormModeBackwardCompatServer")
class NameSchema(BaseModel):
@ -267,8 +264,6 @@ async def test_url_elicitation_required_error_code():
@pytest.mark.anyio
async def test_elicit_url_typed_results():
"""Test that elicit_url returns properly typed result objects."""
from mcp.server.elicitation import elicit_url
mcp = FastMCP(name="TypedResultsServer")
@mcp.tool(description="Test declined result")
@ -329,8 +324,6 @@ async def test_elicit_url_typed_results():
@pytest.mark.anyio
async def test_deprecated_elicit_method():
"""Test the deprecated elicit() method for backward compatibility."""
from pydantic import BaseModel, Field
mcp = FastMCP(name="DeprecatedElicitServer")
class EmailSchema(BaseModel):