Skip to content

Commit e989e6e

Browse files
committed
Stop advertising MCP_* env vars for MCPServer settings; drop pydantic-settings
The Settings docstring and the installation docs claimed MCPServer could be configured through MCP_* environment variables and a .env file, but MCPServer always passes explicit constructor arguments to Settings, and those outrank the environment in pydantic-settings, so e.g. MCP_DEBUG=true has never taken effect. Make Settings a plain pydantic BaseModel and remove pydantic-settings from the runtime dependencies (it moves to the dev group, where the examples still use it). The migration guide explains how to feed environment variables into the constructor for anyone who wants that behaviour.
1 parent 0cb920f commit e989e6e

5 files changed

Lines changed: 24 additions & 19 deletions

File tree

docs/get-started/installation.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ You don't need to know any of this to use the SDK, but if you're wondering what
3434
* `mcp-types`: every protocol type (requests, results, content blocks) as its own package, versioned in lockstep with the SDK. Every `from mcp_types import ...` in these docs is this package.
3535
* [`anyio`](https://anyio.readthedocs.io/): the async runtime. The whole SDK is written against anyio, so it runs on either `asyncio` or `trio`.
3636
* [`pydantic`](https://docs.pydantic.dev/): what every `mcp_types` model is built on, plus all schema generation and validation.
37-
* [`pydantic-settings`](https://docs.pydantic.dev/latest/concepts/pydantic_settings/): server configuration via `MCP_*` environment variables and `.env` files.
3837
* [`httpx2`](https://pypi.org/project/httpx2/): the HTTP client behind the Streamable HTTP and SSE *client* transports, with server-sent events support built in.
3938
* [`starlette`](https://www.starlette.io/), [`uvicorn`](https://www.uvicorn.org/), [`sse-starlette`](https://pypi.org/project/sse-starlette/), and [`python-multipart`](https://pypi.org/project/python-multipart/): the HTTP *server* transports.
4039
* [`jsonschema`](https://pypi.org/project/jsonschema/): validates a tool's structured output against its declared output schema.

docs/migration.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,22 @@ app = Starlette(routes=[Mount("/", app=mcp.streamable_http_app(json_response=Tru
684684

685685
If you were mutating these via `mcp.settings` after construction (e.g., `mcp.settings.port = 9000`), pass them to `run()` / `sse_app()` / `streamable_http_app()` instead — these fields no longer exist on `Settings`. The `debug` and `log_level` parameters remain on the constructor.
686686

687+
### `MCP_*` environment variables and `.env` files are no longer read
688+
689+
The `Settings` docstring advertised configuration via `MCP_*` environment variables and a `.env` file (e.g. `MCP_DEBUG=true`), but constructor arguments have always taken precedence, so those environment variables never took effect. `Settings` is now a plain Pydantic model rather than a `pydantic-settings` `BaseSettings`, and `pydantic-settings` is no longer a dependency of the SDK.
690+
691+
If you want environment-driven configuration, read the environment yourself and pass the values to the constructor:
692+
693+
```python
694+
import os
695+
696+
from mcp.server.mcpserver import MCPServer
697+
698+
mcp = MCPServer("Demo", debug=os.environ.get("MCP_DEBUG") == "true")
699+
```
700+
701+
If your own code uses `pydantic-settings`, add it to your project's dependencies directly.
702+
687703
### Streamable HTTP request bodies are limited to 4 MiB
688704

689705
V2 applies a 4 MiB default limit to Streamable HTTP POST bodies and returns HTTP 413 before parsing

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ dev = [
5858
# We add mcp[cli] so `uv sync` considers the extras.
5959
"mcp[cli]",
6060
"mcp-example-stories",
61+
# pydantic-settings is used only by examples (simple-auth, mcpserver/text_me);
62+
# keep it reachable for pyright, which covers examples/servers.
63+
"pydantic-settings>=2.5.2",
6164
"tomli>=2.0; python_version < '3.11'",
6265
"pyright>=1.1.400",
6366
"pytest>=8.4.0",
@@ -128,7 +131,6 @@ dependencies = [
128131
"starlette>=0.27; python_version < '3.14'",
129132
"python-multipart>=0.0.9",
130133
"sse-starlette>=3.0.0",
131-
"pydantic-settings>=2.5.2",
132134
"uvicorn>=0.31.1; sys_platform != 'emscripten'",
133135
"jsonschema>=4.20.0",
134136
"pywin32>=311; sys_platform == 'win32'",

src/mcp/server/mcpserver/server.py

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
from mcp_types import Resource as MCPResource
4545
from mcp_types import ResourceTemplate as MCPResourceTemplate
4646
from mcp_types import Tool as MCPTool
47+
from pydantic import BaseModel
4748
from pydantic.networks import AnyUrl
48-
from pydantic_settings import BaseSettings, SettingsConfigDict
4949
from starlette.applications import Starlette
5050
from starlette.middleware import Middleware
5151
from starlette.middleware.authentication import AuthenticationMiddleware
@@ -98,20 +98,8 @@
9898
_CallableT = TypeVar("_CallableT", bound=Callable[..., Any])
9999

100100

101-
class Settings(BaseSettings, Generic[LifespanResultT]):
102-
"""MCPServer settings.
103-
104-
All settings can be configured via environment variables with the prefix MCP_.
105-
For example, MCP_DEBUG=true will set debug=True.
106-
"""
107-
108-
model_config = SettingsConfigDict(
109-
env_prefix="MCP_",
110-
env_file=".env",
111-
env_nested_delimiter="__",
112-
nested_model_default_partial_update=True,
113-
extra="ignore",
114-
)
101+
class Settings(BaseModel, Generic[LifespanResultT]):
102+
"""MCPServer settings, as passed to the `MCPServer` constructor."""
115103

116104
# Server settings
117105
debug: bool

uv.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)