mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
Compare commits
4 commits
main
...
codex/lazy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0a2831401 |
||
|
|
2906c74b83 |
||
|
|
0342e6cccd |
||
|
|
5c751510cc |
11 changed files with 609 additions and 93 deletions
|
|
@ -1,27 +1,55 @@
|
||||||
from fastmcp import _install_hints
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
try:
|
from fastmcp import _install_hints
|
||||||
|
from fastmcp.utilities.lazy_imports import (
|
||||||
|
list_module_attributes,
|
||||||
|
resolve_lazy_import,
|
||||||
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
from .auth import (
|
from .auth import (
|
||||||
BearerAuth,
|
BearerAuth as BearerAuth,
|
||||||
ClientCredentialsOAuthProvider,
|
|
||||||
OAuth,
|
|
||||||
PrivateKeyJWTOAuthProvider,
|
|
||||||
)
|
)
|
||||||
from .client import Client
|
from .auth import (
|
||||||
|
ClientCredentialsOAuthProvider as ClientCredentialsOAuthProvider,
|
||||||
|
)
|
||||||
|
from .auth import (
|
||||||
|
OAuth as OAuth,
|
||||||
|
)
|
||||||
|
from .auth import (
|
||||||
|
PrivateKeyJWTOAuthProvider as PrivateKeyJWTOAuthProvider,
|
||||||
|
)
|
||||||
|
from .client import Client as Client
|
||||||
from .transports import (
|
from .transports import (
|
||||||
ClientTransport,
|
ClientTransport as ClientTransport,
|
||||||
FastMCPTransport,
|
)
|
||||||
NodeStdioTransport,
|
from .transports import (
|
||||||
NpxStdioTransport,
|
FastMCPTransport as FastMCPTransport,
|
||||||
PythonStdioTransport,
|
)
|
||||||
SSETransport,
|
from .transports import (
|
||||||
StdioTransport,
|
NodeStdioTransport as NodeStdioTransport,
|
||||||
StreamableHttpTransport,
|
)
|
||||||
UvStdioTransport,
|
from .transports import (
|
||||||
UvxStdioTransport,
|
NpxStdioTransport as NpxStdioTransport,
|
||||||
|
)
|
||||||
|
from .transports import (
|
||||||
|
PythonStdioTransport as PythonStdioTransport,
|
||||||
|
)
|
||||||
|
from .transports import (
|
||||||
|
SSETransport as SSETransport,
|
||||||
|
)
|
||||||
|
from .transports import (
|
||||||
|
StdioTransport as StdioTransport,
|
||||||
|
)
|
||||||
|
from .transports import (
|
||||||
|
StreamableHttpTransport as StreamableHttpTransport,
|
||||||
|
)
|
||||||
|
from .transports import (
|
||||||
|
UvStdioTransport as UvStdioTransport,
|
||||||
|
)
|
||||||
|
from .transports import (
|
||||||
|
UvxStdioTransport as UvxStdioTransport,
|
||||||
)
|
)
|
||||||
except ImportError as exc:
|
|
||||||
raise ImportError(_install_hints.CLIENT_SUPPORT) from exc
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"BearerAuth",
|
"BearerAuth",
|
||||||
|
|
@ -40,3 +68,35 @@ __all__ = [
|
||||||
"UvStdioTransport",
|
"UvStdioTransport",
|
||||||
"UvxStdioTransport",
|
"UvxStdioTransport",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"BearerAuth": (".auth", "BearerAuth"),
|
||||||
|
"Client": (".client", "Client"),
|
||||||
|
"ClientCredentialsOAuthProvider": (
|
||||||
|
".auth",
|
||||||
|
"ClientCredentialsOAuthProvider",
|
||||||
|
),
|
||||||
|
"ClientTransport": (".transports", "ClientTransport"),
|
||||||
|
"FastMCPTransport": (".transports", "FastMCPTransport"),
|
||||||
|
"NodeStdioTransport": (".transports", "NodeStdioTransport"),
|
||||||
|
"NpxStdioTransport": (".transports", "NpxStdioTransport"),
|
||||||
|
"OAuth": (".auth", "OAuth"),
|
||||||
|
"PrivateKeyJWTOAuthProvider": (".auth", "PrivateKeyJWTOAuthProvider"),
|
||||||
|
"PythonStdioTransport": (".transports", "PythonStdioTransport"),
|
||||||
|
"SSETransport": (".transports", "SSETransport"),
|
||||||
|
"StdioTransport": (".transports", "StdioTransport"),
|
||||||
|
"StreamableHttpTransport": (".transports", "StreamableHttpTransport"),
|
||||||
|
"UvStdioTransport": (".transports", "UvStdioTransport"),
|
||||||
|
"UvxStdioTransport": (".transports", "UvxStdioTransport"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> object:
|
||||||
|
try:
|
||||||
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(_install_hints.CLIENT_SUPPORT) from exc
|
||||||
|
|
||||||
|
|
||||||
|
def __dir__() -> list[str]:
|
||||||
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,23 @@
|
||||||
from .bearer import BearerAuth
|
from typing import TYPE_CHECKING
|
||||||
from .client_credentials import (
|
|
||||||
ClientCredentialsOAuthProvider,
|
from fastmcp.utilities.lazy_imports import (
|
||||||
PrivateKeyJWTOAuthProvider,
|
list_module_attributes,
|
||||||
SignedJWTParameters,
|
resolve_lazy_import,
|
||||||
static_assertion_provider,
|
|
||||||
)
|
)
|
||||||
from .oauth import OAuth
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .bearer import BearerAuth as BearerAuth
|
||||||
|
from .client_credentials import (
|
||||||
|
ClientCredentialsOAuthProvider as ClientCredentialsOAuthProvider,
|
||||||
|
)
|
||||||
|
from .client_credentials import (
|
||||||
|
PrivateKeyJWTOAuthProvider as PrivateKeyJWTOAuthProvider,
|
||||||
|
)
|
||||||
|
from .client_credentials import SignedJWTParameters as SignedJWTParameters
|
||||||
|
from .client_credentials import (
|
||||||
|
static_assertion_provider as static_assertion_provider,
|
||||||
|
)
|
||||||
|
from .oauth import OAuth as OAuth
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"BearerAuth",
|
"BearerAuth",
|
||||||
|
|
@ -15,3 +27,29 @@ __all__ = [
|
||||||
"SignedJWTParameters",
|
"SignedJWTParameters",
|
||||||
"static_assertion_provider",
|
"static_assertion_provider",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"BearerAuth": (".bearer", "BearerAuth"),
|
||||||
|
"ClientCredentialsOAuthProvider": (
|
||||||
|
".client_credentials",
|
||||||
|
"ClientCredentialsOAuthProvider",
|
||||||
|
),
|
||||||
|
"OAuth": (".oauth", "OAuth"),
|
||||||
|
"PrivateKeyJWTOAuthProvider": (
|
||||||
|
".client_credentials",
|
||||||
|
"PrivateKeyJWTOAuthProvider",
|
||||||
|
),
|
||||||
|
"SignedJWTParameters": (".client_credentials", "SignedJWTParameters"),
|
||||||
|
"static_assertion_provider": (
|
||||||
|
".client_credentials",
|
||||||
|
"static_assertion_provider",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> object:
|
||||||
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
|
|
||||||
|
|
||||||
|
def __dir__() -> list[str]:
|
||||||
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,37 @@
|
||||||
from mcp.server.mcpserver import MCPServer as SDKServer
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from fastmcp.client.transports.base import (
|
from fastmcp.utilities.lazy_imports import (
|
||||||
ClientTransport,
|
list_module_attributes,
|
||||||
ClientTransportT,
|
resolve_lazy_import,
|
||||||
SessionKwargs,
|
|
||||||
)
|
|
||||||
from fastmcp.client.transports.config import MCPConfigTransport
|
|
||||||
from fastmcp.client.transports.http import StreamableHttpTransport
|
|
||||||
from fastmcp.client.transports.inference import infer_transport
|
|
||||||
from fastmcp.client.transports.sse import SSETransport
|
|
||||||
from fastmcp.client.transports.memory import FastMCPTransport
|
|
||||||
from fastmcp.client.transports.stdio import (
|
|
||||||
FastMCPStdioTransport,
|
|
||||||
NodeStdioTransport,
|
|
||||||
NpxStdioTransport,
|
|
||||||
PythonStdioTransport,
|
|
||||||
StdioTransport,
|
|
||||||
UvStdioTransport,
|
|
||||||
UvxStdioTransport,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from mcp.server.mcpserver import MCPServer as SDKServer
|
||||||
|
|
||||||
|
from fastmcp.client.transports.base import ClientTransport as ClientTransport
|
||||||
|
from fastmcp.client.transports.base import ClientTransportT as ClientTransportT
|
||||||
|
from fastmcp.client.transports.base import SessionKwargs as SessionKwargs
|
||||||
|
from fastmcp.client.transports.config import (
|
||||||
|
MCPConfigTransport as MCPConfigTransport,
|
||||||
|
)
|
||||||
|
from fastmcp.client.transports.http import (
|
||||||
|
StreamableHttpTransport as StreamableHttpTransport,
|
||||||
|
)
|
||||||
|
from fastmcp.client.transports.inference import infer_transport as infer_transport
|
||||||
|
from fastmcp.client.transports.memory import FastMCPTransport as FastMCPTransport
|
||||||
|
from fastmcp.client.transports.sse import SSETransport as SSETransport
|
||||||
|
from fastmcp.client.transports.stdio import (
|
||||||
|
FastMCPStdioTransport as FastMCPStdioTransport,
|
||||||
|
)
|
||||||
|
from fastmcp.client.transports.stdio import NodeStdioTransport as NodeStdioTransport
|
||||||
|
from fastmcp.client.transports.stdio import NpxStdioTransport as NpxStdioTransport
|
||||||
|
from fastmcp.client.transports.stdio import (
|
||||||
|
PythonStdioTransport as PythonStdioTransport,
|
||||||
|
)
|
||||||
|
from fastmcp.client.transports.stdio import StdioTransport as StdioTransport
|
||||||
|
from fastmcp.client.transports.stdio import UvStdioTransport as UvStdioTransport
|
||||||
|
from fastmcp.client.transports.stdio import UvxStdioTransport as UvxStdioTransport
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"ClientTransport",
|
"ClientTransport",
|
||||||
"FastMCPStdioTransport",
|
"FastMCPStdioTransport",
|
||||||
|
|
@ -34,3 +46,48 @@ __all__ = [
|
||||||
"UvxStdioTransport",
|
"UvxStdioTransport",
|
||||||
"infer_transport",
|
"infer_transport",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"ClientTransport": ("fastmcp.client.transports.base", "ClientTransport"),
|
||||||
|
"ClientTransportT": ("fastmcp.client.transports.base", "ClientTransportT"),
|
||||||
|
"FastMCPStdioTransport": (
|
||||||
|
"fastmcp.client.transports.stdio",
|
||||||
|
"FastMCPStdioTransport",
|
||||||
|
),
|
||||||
|
"FastMCPTransport": ("fastmcp.client.transports.memory", "FastMCPTransport"),
|
||||||
|
"MCPConfigTransport": (
|
||||||
|
"fastmcp.client.transports.config",
|
||||||
|
"MCPConfigTransport",
|
||||||
|
),
|
||||||
|
"NodeStdioTransport": (
|
||||||
|
"fastmcp.client.transports.stdio",
|
||||||
|
"NodeStdioTransport",
|
||||||
|
),
|
||||||
|
"NpxStdioTransport": (
|
||||||
|
"fastmcp.client.transports.stdio",
|
||||||
|
"NpxStdioTransport",
|
||||||
|
),
|
||||||
|
"PythonStdioTransport": (
|
||||||
|
"fastmcp.client.transports.stdio",
|
||||||
|
"PythonStdioTransport",
|
||||||
|
),
|
||||||
|
"SDKServer": ("mcp.server.mcpserver", "MCPServer"),
|
||||||
|
"SSETransport": ("fastmcp.client.transports.sse", "SSETransport"),
|
||||||
|
"SessionKwargs": ("fastmcp.client.transports.base", "SessionKwargs"),
|
||||||
|
"StdioTransport": ("fastmcp.client.transports.stdio", "StdioTransport"),
|
||||||
|
"StreamableHttpTransport": (
|
||||||
|
"fastmcp.client.transports.http",
|
||||||
|
"StreamableHttpTransport",
|
||||||
|
),
|
||||||
|
"UvStdioTransport": ("fastmcp.client.transports.stdio", "UvStdioTransport"),
|
||||||
|
"UvxStdioTransport": ("fastmcp.client.transports.stdio", "UvxStdioTransport"),
|
||||||
|
"infer_transport": ("fastmcp.client.transports.inference", "infer_transport"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> object:
|
||||||
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
|
|
||||||
|
|
||||||
|
def __dir__() -> list[str]:
|
||||||
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,18 @@
|
||||||
from .function_prompt import FunctionPrompt, prompt
|
from typing import TYPE_CHECKING
|
||||||
from .base import Message, Prompt, PromptArgument, PromptMessage, PromptResult
|
|
||||||
|
from fastmcp.utilities.lazy_imports import (
|
||||||
|
list_module_attributes,
|
||||||
|
resolve_lazy_import,
|
||||||
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .base import Message as Message
|
||||||
|
from .base import Prompt as Prompt
|
||||||
|
from .base import PromptArgument as PromptArgument
|
||||||
|
from .base import PromptMessage as PromptMessage
|
||||||
|
from .base import PromptResult as PromptResult
|
||||||
|
from .function_prompt import FunctionPrompt as FunctionPrompt
|
||||||
|
from .function_prompt import prompt as prompt
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"FunctionPrompt",
|
"FunctionPrompt",
|
||||||
|
|
@ -10,3 +23,21 @@ __all__ = [
|
||||||
"PromptResult",
|
"PromptResult",
|
||||||
"prompt",
|
"prompt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"FunctionPrompt": (".function_prompt", "FunctionPrompt"),
|
||||||
|
"Message": (".base", "Message"),
|
||||||
|
"Prompt": (".base", "Prompt"),
|
||||||
|
"PromptArgument": (".base", "PromptArgument"),
|
||||||
|
"PromptMessage": (".base", "PromptMessage"),
|
||||||
|
"PromptResult": (".base", "PromptResult"),
|
||||||
|
"prompt": (".function_prompt", "prompt"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> object:
|
||||||
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
|
|
||||||
|
|
||||||
|
def __dir__() -> list[str]:
|
||||||
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,24 @@
|
||||||
from .function_resource import FunctionResource, resource
|
from typing import TYPE_CHECKING
|
||||||
from .base import Resource, ResourceContent, ResourceResult
|
|
||||||
from .security import ResourceSecurity
|
from fastmcp.utilities.lazy_imports import (
|
||||||
from .template import ResourceTemplate
|
list_module_attributes,
|
||||||
from .types import (
|
resolve_lazy_import,
|
||||||
BinaryResource,
|
|
||||||
DirectoryResource,
|
|
||||||
FileResource,
|
|
||||||
HttpResource,
|
|
||||||
TextResource,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .base import Resource as Resource
|
||||||
|
from .base import ResourceContent as ResourceContent
|
||||||
|
from .base import ResourceResult as ResourceResult
|
||||||
|
from .function_resource import FunctionResource as FunctionResource
|
||||||
|
from .function_resource import resource as resource
|
||||||
|
from .security import ResourceSecurity as ResourceSecurity
|
||||||
|
from .template import ResourceTemplate as ResourceTemplate
|
||||||
|
from .types import BinaryResource as BinaryResource
|
||||||
|
from .types import DirectoryResource as DirectoryResource
|
||||||
|
from .types import FileResource as FileResource
|
||||||
|
from .types import HttpResource as HttpResource
|
||||||
|
from .types import TextResource as TextResource
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"BinaryResource",
|
"BinaryResource",
|
||||||
"DirectoryResource",
|
"DirectoryResource",
|
||||||
|
|
@ -24,3 +33,26 @@ __all__ = [
|
||||||
"TextResource",
|
"TextResource",
|
||||||
"resource",
|
"resource",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"BinaryResource": (".types", "BinaryResource"),
|
||||||
|
"DirectoryResource": (".types", "DirectoryResource"),
|
||||||
|
"FileResource": (".types", "FileResource"),
|
||||||
|
"FunctionResource": (".function_resource", "FunctionResource"),
|
||||||
|
"HttpResource": (".types", "HttpResource"),
|
||||||
|
"Resource": (".base", "Resource"),
|
||||||
|
"ResourceContent": (".base", "ResourceContent"),
|
||||||
|
"ResourceResult": (".base", "ResourceResult"),
|
||||||
|
"ResourceSecurity": (".security", "ResourceSecurity"),
|
||||||
|
"ResourceTemplate": (".template", "ResourceTemplate"),
|
||||||
|
"TextResource": (".types", "TextResource"),
|
||||||
|
"resource": (".function_resource", "resource"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> object:
|
||||||
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
|
|
||||||
|
|
||||||
|
def __dir__() -> list[str]:
|
||||||
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
from .authorization import AuthMiddleware
|
from typing import TYPE_CHECKING
|
||||||
from .middleware import (
|
|
||||||
CallNext,
|
from fastmcp.utilities.lazy_imports import (
|
||||||
Middleware,
|
list_module_attributes,
|
||||||
MiddlewareContext,
|
resolve_lazy_import,
|
||||||
)
|
)
|
||||||
from .ping import PingMiddleware
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .authorization import AuthMiddleware as AuthMiddleware
|
||||||
|
from .middleware import CallNext as CallNext
|
||||||
|
from .middleware import Middleware as Middleware
|
||||||
|
from .middleware import MiddlewareContext as MiddlewareContext
|
||||||
|
from .ping import PingMiddleware as PingMiddleware
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"AuthMiddleware",
|
"AuthMiddleware",
|
||||||
|
|
@ -13,3 +19,19 @@ __all__ = [
|
||||||
"MiddlewareContext",
|
"MiddlewareContext",
|
||||||
"PingMiddleware",
|
"PingMiddleware",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"AuthMiddleware": (".authorization", "AuthMiddleware"),
|
||||||
|
"CallNext": (".middleware", "CallNext"),
|
||||||
|
"Middleware": (".middleware", "Middleware"),
|
||||||
|
"MiddlewareContext": (".middleware", "MiddlewareContext"),
|
||||||
|
"PingMiddleware": (".ping", "PingMiddleware"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> object:
|
||||||
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
|
|
||||||
|
|
||||||
|
def __dir__() -> list[str]:
|
||||||
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
|
|
@ -27,20 +27,32 @@ Example:
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from fastmcp.server.providers.aggregate import AggregateProvider
|
from fastmcp.utilities.lazy_imports import (
|
||||||
from fastmcp.server.providers.base import Provider
|
list_module_attributes,
|
||||||
from fastmcp.server.providers.fastmcp_provider import FastMCPProvider
|
resolve_lazy_import,
|
||||||
from fastmcp.server.providers.filesystem import FileSystemProvider
|
|
||||||
from fastmcp.server.providers.local_provider import LocalProvider
|
|
||||||
from fastmcp.server.providers.skills import (
|
|
||||||
ClaudeSkillsProvider,
|
|
||||||
SkillProvider,
|
|
||||||
SkillsDirectoryProvider,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
from fastmcp.server.providers.aggregate import (
|
||||||
|
AggregateProvider as AggregateProvider,
|
||||||
|
)
|
||||||
|
from fastmcp.server.providers.base import Provider as Provider
|
||||||
|
from fastmcp.server.providers.fastmcp_provider import (
|
||||||
|
FastMCPProvider as FastMCPProvider,
|
||||||
|
)
|
||||||
|
from fastmcp.server.providers.filesystem import (
|
||||||
|
FileSystemProvider as FileSystemProvider,
|
||||||
|
)
|
||||||
|
from fastmcp.server.providers.local_provider import LocalProvider as LocalProvider
|
||||||
from fastmcp.server.providers.openapi import OpenAPIProvider as OpenAPIProvider
|
from fastmcp.server.providers.openapi import OpenAPIProvider as OpenAPIProvider
|
||||||
from fastmcp.server.providers.proxy import ProxyProvider as ProxyProvider
|
from fastmcp.server.providers.proxy import ProxyProvider as ProxyProvider
|
||||||
|
from fastmcp.server.providers.skills import (
|
||||||
|
ClaudeSkillsProvider as ClaudeSkillsProvider,
|
||||||
|
)
|
||||||
|
from fastmcp.server.providers.skills import SkillProvider as SkillProvider
|
||||||
|
from fastmcp.server.providers.skills import (
|
||||||
|
SkillsDirectoryProvider as SkillsDirectoryProvider,
|
||||||
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"AggregateProvider",
|
"AggregateProvider",
|
||||||
|
|
@ -55,15 +67,35 @@ __all__ = [
|
||||||
"SkillsDirectoryProvider",
|
"SkillsDirectoryProvider",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"AggregateProvider": ("fastmcp.server.providers.aggregate", "AggregateProvider"),
|
||||||
|
"ClaudeSkillsProvider": (
|
||||||
|
"fastmcp.server.providers.skills",
|
||||||
|
"ClaudeSkillsProvider",
|
||||||
|
),
|
||||||
|
"FastMCPProvider": (
|
||||||
|
"fastmcp.server.providers.fastmcp_provider",
|
||||||
|
"FastMCPProvider",
|
||||||
|
),
|
||||||
|
"FileSystemProvider": (
|
||||||
|
"fastmcp.server.providers.filesystem",
|
||||||
|
"FileSystemProvider",
|
||||||
|
),
|
||||||
|
"LocalProvider": ("fastmcp.server.providers.local_provider", "LocalProvider"),
|
||||||
|
"OpenAPIProvider": ("fastmcp.server.providers.openapi", "OpenAPIProvider"),
|
||||||
|
"Provider": ("fastmcp.server.providers.base", "Provider"),
|
||||||
|
"ProxyProvider": ("fastmcp.server.providers.proxy", "ProxyProvider"),
|
||||||
|
"SkillProvider": ("fastmcp.server.providers.skills", "SkillProvider"),
|
||||||
|
"SkillsDirectoryProvider": (
|
||||||
|
"fastmcp.server.providers.skills",
|
||||||
|
"SkillsDirectoryProvider",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def __getattr__(name: str) -> object:
|
def __getattr__(name: str) -> object:
|
||||||
"""Lazy import for providers to avoid circular imports."""
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
if name == "ProxyProvider":
|
|
||||||
from fastmcp.server.providers.proxy import ProxyProvider
|
|
||||||
|
|
||||||
return ProxyProvider
|
|
||||||
if name == "OpenAPIProvider":
|
|
||||||
from fastmcp.server.providers.openapi import OpenAPIProvider
|
|
||||||
|
|
||||||
return OpenAPIProvider
|
def __dir__() -> list[str]:
|
||||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
|
|
@ -23,12 +23,31 @@ from __future__ import annotations
|
||||||
from collections.abc import Awaitable, Sequence
|
from collections.abc import Awaitable, Sequence
|
||||||
from typing import TYPE_CHECKING, Protocol
|
from typing import TYPE_CHECKING, Protocol
|
||||||
|
|
||||||
|
from fastmcp.utilities.lazy_imports import (
|
||||||
|
list_module_attributes,
|
||||||
|
resolve_lazy_import,
|
||||||
|
)
|
||||||
from fastmcp.utilities.versions import VersionSpec
|
from fastmcp.utilities.versions import VersionSpec
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from fastmcp.prompts.base import Prompt
|
from fastmcp.prompts.base import Prompt
|
||||||
from fastmcp.resources.base import Resource
|
from fastmcp.resources.base import Resource
|
||||||
from fastmcp.resources.template import ResourceTemplate
|
from fastmcp.resources.template import ResourceTemplate
|
||||||
|
from fastmcp.server.transforms.namespace import Namespace as Namespace
|
||||||
|
from fastmcp.server.transforms.prompts_as_tools import (
|
||||||
|
PromptsAsTools as PromptsAsTools,
|
||||||
|
)
|
||||||
|
from fastmcp.server.transforms.resources_as_tools import (
|
||||||
|
ResourcesAsTools as ResourcesAsTools,
|
||||||
|
)
|
||||||
|
from fastmcp.server.transforms.tool_transform import (
|
||||||
|
ToolTransform as ToolTransform,
|
||||||
|
)
|
||||||
|
from fastmcp.server.transforms.version_filter import (
|
||||||
|
VersionFilter as VersionFilter,
|
||||||
|
)
|
||||||
|
from fastmcp.server.transforms.visibility import Visibility as Visibility
|
||||||
|
from fastmcp.server.transforms.visibility import is_enabled as is_enabled
|
||||||
from fastmcp.tools.base import Tool
|
from fastmcp.tools.base import Tool
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -219,14 +238,6 @@ class Transform:
|
||||||
return await call_next(name, version=version)
|
return await call_next(name, version=version)
|
||||||
|
|
||||||
|
|
||||||
# Re-export built-in transforms (must be after Transform class to avoid circular imports)
|
|
||||||
from fastmcp.server.transforms.visibility import Visibility, is_enabled # noqa: E402
|
|
||||||
from fastmcp.server.transforms.namespace import Namespace # noqa: E402
|
|
||||||
from fastmcp.server.transforms.prompts_as_tools import PromptsAsTools # noqa: E402
|
|
||||||
from fastmcp.server.transforms.resources_as_tools import ResourcesAsTools # noqa: E402
|
|
||||||
from fastmcp.server.transforms.tool_transform import ToolTransform # noqa: E402
|
|
||||||
from fastmcp.server.transforms.version_filter import VersionFilter # noqa: E402
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Namespace",
|
"Namespace",
|
||||||
"PromptsAsTools",
|
"PromptsAsTools",
|
||||||
|
|
@ -238,3 +249,33 @@ __all__ = [
|
||||||
"Visibility",
|
"Visibility",
|
||||||
"is_enabled",
|
"is_enabled",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"Namespace": ("fastmcp.server.transforms.namespace", "Namespace"),
|
||||||
|
"PromptsAsTools": (
|
||||||
|
"fastmcp.server.transforms.prompts_as_tools",
|
||||||
|
"PromptsAsTools",
|
||||||
|
),
|
||||||
|
"ResourcesAsTools": (
|
||||||
|
"fastmcp.server.transforms.resources_as_tools",
|
||||||
|
"ResourcesAsTools",
|
||||||
|
),
|
||||||
|
"ToolTransform": (
|
||||||
|
"fastmcp.server.transforms.tool_transform",
|
||||||
|
"ToolTransform",
|
||||||
|
),
|
||||||
|
"VersionFilter": (
|
||||||
|
"fastmcp.server.transforms.version_filter",
|
||||||
|
"VersionFilter",
|
||||||
|
),
|
||||||
|
"Visibility": ("fastmcp.server.transforms.visibility", "Visibility"),
|
||||||
|
"is_enabled": ("fastmcp.server.transforms.visibility", "is_enabled"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> object:
|
||||||
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
|
|
||||||
|
|
||||||
|
def __dir__() -> list[str]:
|
||||||
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,18 @@
|
||||||
from .function_tool import FunctionTool, tool
|
from typing import TYPE_CHECKING
|
||||||
from .base import InputRequiredToolResult, Tool, ToolResult
|
|
||||||
from .tool_transform import forward, forward_raw
|
from fastmcp.utilities.lazy_imports import (
|
||||||
|
list_module_attributes,
|
||||||
|
resolve_lazy_import,
|
||||||
|
)
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .base import InputRequiredToolResult as InputRequiredToolResult
|
||||||
|
from .base import Tool as Tool
|
||||||
|
from .base import ToolResult as ToolResult
|
||||||
|
from .function_tool import FunctionTool as FunctionTool
|
||||||
|
from .function_tool import tool as tool
|
||||||
|
from .tool_transform import forward as forward
|
||||||
|
from .tool_transform import forward_raw as forward_raw
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"FunctionTool",
|
"FunctionTool",
|
||||||
|
|
@ -11,3 +23,21 @@ __all__ = [
|
||||||
"forward_raw",
|
"forward_raw",
|
||||||
"tool",
|
"tool",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
_LAZY_IMPORTS = {
|
||||||
|
"FunctionTool": (".function_tool", "FunctionTool"),
|
||||||
|
"InputRequiredToolResult": (".base", "InputRequiredToolResult"),
|
||||||
|
"Tool": (".base", "Tool"),
|
||||||
|
"ToolResult": (".base", "ToolResult"),
|
||||||
|
"forward": (".tool_transform", "forward"),
|
||||||
|
"forward_raw": (".tool_transform", "forward_raw"),
|
||||||
|
"tool": (".function_tool", "tool"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def __getattr__(name: str) -> object:
|
||||||
|
return resolve_lazy_import(name, __name__, globals(), _LAZY_IMPORTS)
|
||||||
|
|
||||||
|
|
||||||
|
def __dir__() -> list[str]:
|
||||||
|
return list_module_attributes(globals(), _LAZY_IMPORTS)
|
||||||
|
|
|
||||||
31
fastmcp_slim/fastmcp/utilities/lazy_imports.py
Normal file
31
fastmcp_slim/fastmcp/utilities/lazy_imports.py
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
"""Helpers for exposing public names without eagerly importing their modules."""
|
||||||
|
|
||||||
|
from collections.abc import Mapping
|
||||||
|
from importlib import import_module
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
LazyImports = Mapping[str, tuple[str, str]]
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_lazy_import(
|
||||||
|
name: str,
|
||||||
|
package: str,
|
||||||
|
namespace: dict[str, Any],
|
||||||
|
lazy_imports: LazyImports,
|
||||||
|
) -> object:
|
||||||
|
"""Resolve and cache a lazily exported module attribute."""
|
||||||
|
try:
|
||||||
|
module_name, attr_name = lazy_imports[name]
|
||||||
|
except KeyError:
|
||||||
|
raise AttributeError(f"module {package!r} has no attribute {name!r}") from None
|
||||||
|
|
||||||
|
value = getattr(import_module(module_name, package), attr_name)
|
||||||
|
namespace[name] = value
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def list_module_attributes(
|
||||||
|
namespace: dict[str, Any], lazy_imports: LazyImports
|
||||||
|
) -> list[str]:
|
||||||
|
"""Include unresolved lazy exports in module introspection."""
|
||||||
|
return sorted(namespace.keys() | lazy_imports.keys())
|
||||||
142
tests/test_lazy_package_imports.py
Normal file
142
tests/test_lazy_package_imports.py
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
"""Fresh-interpreter guards for lazy public package exports."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("statement", "excluded_modules"),
|
||||||
|
[
|
||||||
|
(
|
||||||
|
"from fastmcp.client import BearerAuth",
|
||||||
|
(
|
||||||
|
"fastmcp.client.auth.client_credentials",
|
||||||
|
"fastmcp.client.auth.oauth",
|
||||||
|
"fastmcp.client.client",
|
||||||
|
"fastmcp.client.transports",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"from fastmcp.client.transports import ClientTransport",
|
||||||
|
(
|
||||||
|
"fastmcp.client.transports.config",
|
||||||
|
"fastmcp.client.transports.http",
|
||||||
|
"fastmcp.client.transports.inference",
|
||||||
|
"fastmcp.client.transports.memory",
|
||||||
|
"fastmcp.client.transports.sse",
|
||||||
|
"fastmcp.client.transports.stdio",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"from fastmcp.tools import Tool",
|
||||||
|
("fastmcp.tools.function_tool", "fastmcp.tools.tool_transform"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"from fastmcp.resources import Resource",
|
||||||
|
(
|
||||||
|
"fastmcp.resources.function_resource",
|
||||||
|
"fastmcp.resources.security",
|
||||||
|
"fastmcp.resources.template",
|
||||||
|
"fastmcp.resources.types",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"from fastmcp.prompts import Prompt",
|
||||||
|
("fastmcp.prompts.function_prompt",),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"from fastmcp.server.providers import Provider",
|
||||||
|
(
|
||||||
|
"fastmcp.server.providers.aggregate",
|
||||||
|
"fastmcp.server.providers.fastmcp_provider",
|
||||||
|
"fastmcp.server.providers.filesystem",
|
||||||
|
"fastmcp.server.providers.local_provider",
|
||||||
|
"fastmcp.server.providers.skills",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"from fastmcp.server.middleware import Middleware",
|
||||||
|
(
|
||||||
|
"fastmcp.server.middleware.authorization",
|
||||||
|
"fastmcp.server.middleware.ping",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"from fastmcp.server.transforms import Transform",
|
||||||
|
(
|
||||||
|
"fastmcp.server.transforms.namespace",
|
||||||
|
"fastmcp.server.transforms.prompts_as_tools",
|
||||||
|
"fastmcp.server.transforms.resources_as_tools",
|
||||||
|
"fastmcp.server.transforms.tool_transform",
|
||||||
|
"fastmcp.server.transforms.version_filter",
|
||||||
|
"fastmcp.server.transforms.visibility",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.subprocess_heavy
|
||||||
|
def test_narrow_import_does_not_load_sibling_implementations(
|
||||||
|
statement: str, excluded_modules: tuple[str, ...]
|
||||||
|
) -> None:
|
||||||
|
script = textwrap.dedent(
|
||||||
|
f"""
|
||||||
|
import sys
|
||||||
|
|
||||||
|
{statement}
|
||||||
|
|
||||||
|
excluded = {excluded_modules!r}
|
||||||
|
loaded = [
|
||||||
|
name
|
||||||
|
for name in sys.modules
|
||||||
|
if any(name == root or name.startswith(f"{{root}}.") for root in excluded)
|
||||||
|
]
|
||||||
|
assert not loaded, loaded
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
[sys.executable, "-c", script],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result.returncode == 0, result.stderr
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.subprocess_heavy
|
||||||
|
def test_all_public_package_exports_resolve() -> None:
|
||||||
|
script = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
import importlib
|
||||||
|
|
||||||
|
packages = (
|
||||||
|
"fastmcp.client",
|
||||||
|
"fastmcp.client.auth",
|
||||||
|
"fastmcp.client.transports",
|
||||||
|
"fastmcp.prompts",
|
||||||
|
"fastmcp.resources",
|
||||||
|
"fastmcp.server.middleware",
|
||||||
|
"fastmcp.server.providers",
|
||||||
|
"fastmcp.server.transforms",
|
||||||
|
"fastmcp.tools",
|
||||||
|
)
|
||||||
|
for package_name in packages:
|
||||||
|
package = importlib.import_module(package_name)
|
||||||
|
assert set(package.__all__) <= set(dir(package))
|
||||||
|
for export in package.__all__:
|
||||||
|
assert getattr(package, export) is not None, (package_name, export)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
[sys.executable, "-c", script],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result.returncode == 0, result.stderr
|
||||||
Loading…
Add table
Add a link
Reference in a new issue