Skip to content

fix(cli): register module in sys.module during _import_server so it can find itself - #3374

Closed
sahabaj-alam wants to merge 1 commit into
modelcontextprotocol:mainfrom
sahabaj-alam:fix/cli-sys-modules-registration
Closed

fix(cli): register module in sys.module during _import_server so it can find itself#3374
sahabaj-alam wants to merge 1 commit into
modelcontextprotocol:mainfrom
sahabaj-alam:fix/cli-sys-modules-registration

Conversation

@sahabaj-alam

Copy link
Copy Markdown

Bug

_import_server() loads a server file via importlib.util.module_from_spec()

  • exec_module(), but never registers the resulting module in sys.modules
    before executing it:

https://github.com/modelcontextprotocol/python-sdk/blob/main/src/mcp/cli/cli.py#L140-L141

Python's own import machinery always inserts a module into sys.modules
before running its code, specifically so the module can look itself up via
sys.modules[__name__] while it's still executing. The official importlib
docs include exactly this step in their reference recipe for loading a file
directly: https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly

_import_server skips it, which breaks anything that relies on
sys.modules[cls.__module__] at class-definition time — most notably
@dataclass resolving string type annotations (via from __future__ import annotations, or even just a manually-quoted forward reference).

Repro

# server.py
from __future__ import annotations
from dataclasses import dataclass
from mcp.server import MCPServer

@dataclass
class AppContext:
    value: str

mcp = MCPServer("repro")

-----------------------------------------------------------------------------
$ mcp dev server.py
...
  File ".../dataclasses.py", line 757, in _is_type
    ns = sys.modules.get(cls.__module__).__dict__
AttributeError: 'NoneType' object has no attribute '__dict__'

----------------------------------------------------------------------------
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module   # so the module can find itself (dataclasses, pickle, etc.)
spec.loader.exec_module(module)

@github-actions github-actions Bot added the missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md) label Aug 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for the contribution. This repository only keeps pull requests open when they're linked to an issue that a maintainer has assigned to the author — CONTRIBUTING.md explains why and how we work. This PR has been closed for now because its description doesn't yet link an open issue in this repository (with Fixes #123 or similar).

If there isn't an issue for this yet, please open one — a clear description of the problem is genuinely the most useful thing for us. Then add Fixes #<number> to this PR's description. If a maintainer would like the change as a PR from you, they'll assign you to the issue and this PR will reopen automatically.

There's no need to open a new PR — this one will be reopened. While it's closed, please push any updates as new commits rather than force-pushing, since GitHub can't reopen a PR whose branch has been rewritten.

Maintainers: reopening this PR, removing the missing-issue-link label, or adding bypass-issue-check bypasses the check.

@github-actions github-actions Bot closed this Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

missing-issue-link Auto-closed: PR needs a linked issue assigned to its author (see CONTRIBUTING.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant