Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/mcp/cli/claude.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import shutil
import sys
from pathlib import Path
from typing import Any
from typing import Any, Final

from mcp.server.fastmcp.utilities.logging import get_logger

logger = get_logger(__name__)

MCP_PACKAGE = "mcp[cli]"
MCP_PACKAGE: Final = "mcp[cli]"


def get_claude_config_path() -> Path | None:
Expand Down
19 changes: 13 additions & 6 deletions src/mcp/client/stdio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import sys
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Literal, TextIO
from typing import Final, Literal, TextIO

import anyio
import anyio.lowlevel
Expand All @@ -25,8 +25,8 @@
logger = logging.getLogger(__name__)

# Environment variables to inherit by default
DEFAULT_INHERITED_ENV_VARS = (
[
DEFAULT_INHERITED_ENV_VARS: Final = (
(
"APPDATA",
"HOMEDRIVE",
"HOMEPATH",
Expand All @@ -39,13 +39,20 @@
"TEMP",
"USERNAME",
"USERPROFILE",
]
)
if sys.platform == "win32"
else ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"]
else (
"HOME",
"LOGNAME",
"PATH",
"SHELL",
"TERM",
"USER",
)
)

# Timeout for process termination before falling back to force kill
PROCESS_TERMINATION_TIMEOUT = 2.0
PROCESS_TERMINATION_TIMEOUT: Final = 2.0


def get_default_environment() -> dict[str, str]:
Expand Down
15 changes: 8 additions & 7 deletions src/mcp/client/streamable_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from contextlib import asynccontextmanager
from dataclasses import dataclass
from datetime import timedelta
from typing import Final

import anyio
import httpx
Expand Down Expand Up @@ -39,15 +40,15 @@
StreamReader = MemoryObjectReceiveStream[SessionMessage]
GetSessionIdCallback = Callable[[], str | None]

MCP_SESSION_ID = "mcp-session-id"
MCP_PROTOCOL_VERSION = "mcp-protocol-version"
LAST_EVENT_ID = "last-event-id"
CONTENT_TYPE = "content-type"
ACCEPT = "accept"
MCP_SESSION_ID: Final = "mcp-session-id"
MCP_PROTOCOL_VERSION: Final = "mcp-protocol-version"
LAST_EVENT_ID: Final = "last-event-id"
CONTENT_TYPE: Final = "content-type"
ACCEPT: Final = "accept"


JSON = "application/json"
SSE = "text/event-stream"
JSON: Final = "application/json"
SSE: Final = "text/event-stream"


class StreamableHTTPError(Exception):
Expand Down
10 changes: 5 additions & 5 deletions src/mcp/server/auth/routes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections.abc import Awaitable, Callable
from typing import Any
from typing import Any, Final

from pydantic import AnyHttpUrl
from starlette.middleware.cors import CORSMiddleware
Expand Down Expand Up @@ -46,10 +46,10 @@ def validate_issuer_url(url: AnyHttpUrl):
raise ValueError("Issuer URL must not have a query string")


AUTHORIZATION_PATH = "/authorize"
TOKEN_PATH = "/token"
REGISTRATION_PATH = "/register"
REVOCATION_PATH = "/revoke"
AUTHORIZATION_PATH: Final = "/authorize"
TOKEN_PATH: Final = "/token"
REGISTRATION_PATH: Final = "/register"
REVOCATION_PATH: Final = "/revoke"


def cors_middleware(
Expand Down
15 changes: 8 additions & 7 deletions src/mcp/server/streamable_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from contextlib import asynccontextmanager
from dataclasses import dataclass
from http import HTTPStatus
from typing import Final

import anyio
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
Expand Down Expand Up @@ -48,20 +49,20 @@


# Header names
MCP_SESSION_ID_HEADER = "mcp-session-id"
MCP_PROTOCOL_VERSION_HEADER = "mcp-protocol-version"
LAST_EVENT_ID_HEADER = "last-event-id"
MCP_SESSION_ID_HEADER: Final = "mcp-session-id"
MCP_PROTOCOL_VERSION_HEADER: Final = "mcp-protocol-version"
LAST_EVENT_ID_HEADER: Final = "last-event-id"

# Content types
CONTENT_TYPE_JSON = "application/json"
CONTENT_TYPE_SSE = "text/event-stream"
CONTENT_TYPE_JSON: Final = "application/json"
CONTENT_TYPE_SSE: Final = "text/event-stream"

# Special key for the standalone GET stream
GET_STREAM_KEY = "_GET_stream"
GET_STREAM_KEY: Final = "_GET_stream"

# Session ID validation pattern (visible ASCII characters ranging from 0x21 to 0x7E)
# Pattern ensures entire string contains only valid characters by using ^ and $ anchors
SESSION_ID_PATTERN = re.compile(r"^[\x21-\x7E]+$")
SESSION_ID_PATTERN: Final = re.compile(r"^[\x21-\x7E]+$")

# Type aliases
StreamId = str
Expand Down
4 changes: 3 additions & 1 deletion src/mcp/shared/version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Final

from mcp.types import LATEST_PROTOCOL_VERSION

SUPPORTED_PROTOCOL_VERSIONS: list[str] = ["2024-11-05", "2025-03-26", LATEST_PROTOCOL_VERSION]
SUPPORTED_PROTOCOL_VERSIONS: Final = ("2024-11-05", "2025-03-26", LATEST_PROTOCOL_VERSION)
19 changes: 9 additions & 10 deletions src/mcp/types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections.abc import Callable
from typing import Annotated, Any, Generic, Literal, TypeAlias, TypeVar
from typing import Annotated, Any, Final, Generic, Literal, TypeAlias, TypeVar

from pydantic import BaseModel, ConfigDict, Field, FileUrl, RootModel
from pydantic.networks import AnyUrl, UrlConstraints
Expand All @@ -23,15 +23,15 @@
not separate types in the schema.
"""

LATEST_PROTOCOL_VERSION = "2025-06-18"
LATEST_PROTOCOL_VERSION: Final = "2025-06-18"

"""
The default negotiated version of the Model Context Protocol when no version is specified.
We need this to satisfy the MCP specification, which requires the server to assume a
specific version if none is provided by the client. See section "Protocol Version Header" at
https://modelcontextprotocol.io/specification
"""
DEFAULT_NEGOTIATED_VERSION = "2025-03-26"
DEFAULT_NEGOTIATED_VERSION: Final = "2025-03-26"

ProgressToken = str | int
Cursor = str
Expand Down Expand Up @@ -147,15 +147,14 @@ class JSONRPCResponse(BaseModel):


# SDK error codes
CONNECTION_CLOSED = -32000
CONNECTION_CLOSED: Final = -32000
# REQUEST_TIMEOUT = -32001 # the typescript sdk uses this

# Standard JSON-RPC error codes
PARSE_ERROR = -32700
INVALID_REQUEST = -32600
METHOD_NOT_FOUND = -32601
INVALID_PARAMS = -32602
INTERNAL_ERROR = -32603
PARSE_ERROR: Final = -32700
INVALID_REQUEST: Final = -32600
METHOD_NOT_FOUND: Final = -32601
INVALID_PARAMS: Final = -32602
INTERNAL_ERROR: Final = -32603


class ErrorData(BaseModel):
Expand Down
Loading