feat(server): restore dependencies parameter on MCPServer#2358
feat(server): restore dependencies parameter on MCPServer#2358
dependencies parameter on MCPServer#2358Conversation
Restores the `dependencies` parameter that was removed in #1877. The parameter is read by the `mcp dev` and `mcp install` CLI commands to auto-populate `uv run --with <pkg>` flags. Removal without a working replacement breaks high-profile consumers (awslabs/mcp uses it in 47 servers, mindsdb, redis/mcp-redis). While PEP 723 inline script metadata is the intended replacement, the CLI doesn't currently parse it — `uv` only reads PEP 723 when the script is the direct target, not when wrapped in `mcp run <file>`. Long-term design (deprecate vs. keep vs. config file) is tracked in the linked issue. Github-Issue:#2354
There was a problem hiding this comment.
This reverses the deliberate removal from #1877 and is a design decision that a maintainer should confirm, even though the code change itself is small and correct. The nit about Collection[str] accepting bare strings is worth addressing too.
Extended reasoning...
Overview
This PR restores the dependencies parameter on MCPServer that was removed in #1877. It adds a dependencies: list[str] field to Settings, a dependencies: Collection[str] = () constructor parameter, and a simple test. The CLI consumer code in cli.py already reads server.dependencies via hasattr/getattr, so this restoration makes those checks functional again.
Security risks
No direct security risks. The dependencies values are passed as --with flags to uv run, which installs packages from PyPI. This is existing behavior in the CLI and not introduced by this PR.
Level of scrutiny
This deserves maintainer-level scrutiny despite being small. The parameter was deliberately removed in #1877, and restoring it is a design decision about the SDK's API surface. The PR description acknowledges this is a stopgap pending a design discussion in #2354. A maintainer should confirm they want to take this approach rather than one of the alternatives outlined in that issue.
Other factors
The bug report about Collection[str] accepting bare strings is a valid nit — MCPServer("test", dependencies="pandas") would silently produce ["p", "a", "n", "d", "a", "s"]. Changing to list[str] (consistent with other parameters in the same constructor) or adding a runtime guard would prevent this footgun. The test coverage is adequate for the happy path but does not cover this edge case.
| warn_on_duplicate_resources: bool = True, | ||
| warn_on_duplicate_tools: bool = True, | ||
| warn_on_duplicate_prompts: bool = True, | ||
| dependencies: Collection[str] = (), |
There was a problem hiding this comment.
🟡 Collection[str] accepts a bare str (since str is itself a collection of single-char strings), so MCPServer("test", dependencies="pandas") silently produces ["p", "a", "n", "d", "a", "s"] via the list(dependencies) call. Consider changing to list[str] or adding if isinstance(dependencies, str): raise TypeError(...) to catch this footgun.
Extended reasoning...
The Bug
The dependencies parameter on line 148 is typed as Collection[str], but Python's str type satisfies Collection[str] — a string is iterable and yields single-character strings. This means MCPServer("test", dependencies="pandas") passes type checking (mypy/pyright will not flag it) and also passes pydantic validation at runtime.
How It Manifests
On line 158, list(dependencies) is called to convert the collection to a list. When dependencies is the string "pandas", this produces ["p", "a", "n", "d", "a", "s"] instead of the intended ["pandas"]. The value is then stored in self.settings.dependencies and self.dependencies.
Downstream Impact
The CLI consumer code in cli.py:262 and cli.py:451-453 reads server.dependencies and passes the values as --with package names to uv. With the character-split list, uv would attempt to install packages named p, a, n, d, a, s — which would either fail with confusing errors or, worse, install unintended packages if single-letter package names happen to exist on PyPI.
Step-by-Step Proof
- User writes:
mcp = MCPServer("my-server", dependencies="pandas") __init__receivesdependencies = "pandas"(astr, which is a validCollection[str])- Line 158 executes
list("pandas")→["p", "a", "n", "d", "a", "s"] self.dependenciesis set to["p", "a", "n", "d", "a", "s"]mcp devormcp installreadsserver.dependenciesand buildsuv run --with p --with a --with n --with d --with a --with s
Fix
The simplest fix is to change Collection[str] to list[str] on line 148 (and update the default from () to []). This would cause type checkers to flag dependencies="pandas" as an error. Alternatively, keep Collection[str] for flexibility but add a runtime guard: if isinstance(dependencies, str): raise TypeError("dependencies must be a list of strings, not a bare string").
Note that every other list parameter in the same constructor (e.g., tools: list[Tool] | None, icons: list[Icon] | None) already uses list[T] directly, so using list[str] would be consistent with the existing API style.
Restores the
dependenciesparameter that was removed in #1877, pending a proper design decision on its future (tracked in #2354).Motivation and Context
The
dependenciesparameter is consumed bymcp devandmcp installto auto-populateuv run --with <pkg>flags when launching servers or writing Claude Desktop config. Removing it without a working replacement creates two problems:Breaks high-profile users — awslabs/mcp (8.5k★, 47 server files), mindsdb (38.8k★), redis/mcp-redis all use this parameter. When jlowin's
fastmcppackage removed the same parameter, it triggered 8+ breakage issues across the ecosystem.No working replacement — the examples were migrated to PEP 723 inline script metadata, but
mcp install/mcp devcan't read it.uvonly parses PEP 723 when the script is the direct target; the CLI wraps it inmcp run <file>, so the metadata is ignored.The CLI consumer code at cli.py#L261 and cli.py#L451 still checks for
server.dependenciesviahasattr/getattr— it was never removed, so this restoration makes those checks functional again.Long-term options (deprecate → PEP 723, adopt a config file like FastMCP 2.0, or keep as-is) are laid out in #2354.
How Has This Been Tested?
Added
test_dependenciesverifying the parameter round-trips through bothmcp.dependenciesandmcp.settings.dependencies, and defaults to[]when omitted. All 88 tests intests/server/mcpserver/test_server.pypass.Breaking Changes
None — this restores previously-removed API.
Types of changes
Checklist
Additional context
Closes the gap left by #1877. See #2354 for the design discussion.
AI Disclaimer