Skip to content

Commit cb7c68c

Browse files
committed
Resolve attribute chains through the four leaf sub-packages too
Every package init in the SDK resolves its submodules on attribute access except four docstring-only leaves - mcp.os.posix, mcp.os.win32, mcp.server.auth.handlers and mcp.server.auth.middleware - so a chain like `import mcp; mcp.server.auth.handlers.token` stopped resolving even though `mcp.client.stdio` and friends do. Give them the same lazy fallback, so "attribute chains still resolve" is true without a footnote (explicit imports remain the supported form), and pin one chain through each in the ratchet.
1 parent 008c74e commit cb7c68c

5 files changed

Lines changed: 47 additions & 4 deletions

File tree

src/mcp/os/posix/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
11
"""POSIX-specific utilities for MCP."""
2+
3+
from typing import TYPE_CHECKING
4+
5+
from mcp.shared._lazy import lazy_module_attrs as _lazy_module_attrs
6+
7+
# `mcp.os.posix.utilities` resolves by attribute access even before it was
8+
# imported explicitly, like the other packages. Runtime only, so a type
9+
# checker still flags a typo.
10+
if not TYPE_CHECKING:
11+
__getattr__, __dir__ = _lazy_module_attrs(__name__, globals())

src/mcp/os/win32/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
11
"""Windows-specific utilities for MCP."""
2+
3+
from typing import TYPE_CHECKING
4+
5+
from mcp.shared._lazy import lazy_module_attrs as _lazy_module_attrs
6+
7+
# `mcp.os.win32.utilities` resolves by attribute access even before it was
8+
# imported explicitly, like the other packages. Runtime only, so a type
9+
# checker still flags a typo.
10+
if not TYPE_CHECKING:
11+
__getattr__, __dir__ = _lazy_module_attrs(__name__, globals())
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
11
"""Request handlers for MCP authorization endpoints."""
2+
3+
from typing import TYPE_CHECKING
4+
5+
from mcp.shared._lazy import lazy_module_attrs as _lazy_module_attrs
6+
7+
# `mcp.server.auth.handlers.<handler>` resolves by attribute access even
8+
# before that submodule was imported explicitly, like the other packages.
9+
# Runtime only, so a type checker still flags a typo.
10+
if not TYPE_CHECKING:
11+
__getattr__, __dir__ = _lazy_module_attrs(__name__, globals())
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,11 @@
11
"""Middleware for MCP authorization."""
2+
3+
from typing import TYPE_CHECKING
4+
5+
from mcp.shared._lazy import lazy_module_attrs as _lazy_module_attrs
6+
7+
# `mcp.server.auth.middleware.<module>` resolves by attribute access even
8+
# before that submodule was imported explicitly, like the other packages.
9+
# Runtime only, so a type checker still flags a typo.
10+
if not TYPE_CHECKING:
11+
__getattr__, __dir__ = _lazy_module_attrs(__name__, globals())

tests/shared/test_lazy.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,14 @@ def test_bare_import_mcp_still_resolves_deep_submodule_chains():
6565
probe = (
6666
"import mcp\n"
6767
"print([mcp.client.stdio.stdio_client.__name__, mcp.server.stdio.stdio_server.__name__,\n"
68-
" mcp.shared.memory.__name__, mcp.os.posix.__name__,\n"
68+
" mcp.shared.memory.__name__, mcp.os.posix.utilities.__name__,\n"
69+
" mcp.os.win32.utilities.__name__, mcp.server.auth.handlers.token.__name__,\n"
70+
" mcp.server.auth.middleware.auth_context.__name__,\n"
6971
" 'stdio' in dir(mcp.client), 'stdio' in dir(mcp.server), 'exceptions' in dir(mcp.shared)])\n"
7072
)
7173
result = subprocess.run([sys.executable, "-c", probe], capture_output=True, text=True, check=False, timeout=20)
7274
assert result.returncode == 0, result.stderr
73-
assert result.stdout == snapshot(
74-
"['stdio_client', 'stdio_server', 'mcp.shared.memory', 'mcp.os.posix', True, True, True]\n"
75-
)
75+
assert result.stdout == snapshot("""\
76+
['stdio_client', 'stdio_server', 'mcp.shared.memory', 'mcp.os.posix.utilities', 'mcp.os.win32.utilities', \
77+
'mcp.server.auth.handlers.token', 'mcp.server.auth.middleware.auth_context', True, True, True]
78+
""")

0 commit comments

Comments
 (0)