fastmcp 2.12.5__py3-none-any.whl → 2.13.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastmcp/__init__.py +2 -2
- fastmcp/cli/cli.py +11 -11
- fastmcp/cli/install/claude_code.py +6 -6
- fastmcp/cli/install/claude_desktop.py +3 -3
- fastmcp/cli/install/cursor.py +18 -12
- fastmcp/cli/install/gemini_cli.py +3 -3
- fastmcp/cli/install/mcp_json.py +3 -3
- fastmcp/cli/run.py +13 -8
- fastmcp/client/__init__.py +9 -9
- fastmcp/client/auth/oauth.py +115 -217
- fastmcp/client/client.py +105 -39
- fastmcp/client/logging.py +18 -14
- fastmcp/client/oauth_callback.py +85 -171
- fastmcp/client/sampling.py +1 -1
- fastmcp/client/transports.py +80 -25
- fastmcp/contrib/component_manager/__init__.py +1 -1
- fastmcp/contrib/component_manager/component_manager.py +2 -2
- fastmcp/contrib/component_manager/component_service.py +6 -6
- fastmcp/contrib/mcp_mixin/README.md +32 -1
- fastmcp/contrib/mcp_mixin/__init__.py +2 -2
- fastmcp/contrib/mcp_mixin/mcp_mixin.py +14 -2
- fastmcp/experimental/sampling/handlers/openai.py +2 -2
- fastmcp/experimental/server/openapi/__init__.py +5 -8
- fastmcp/experimental/server/openapi/components.py +11 -7
- fastmcp/experimental/server/openapi/routing.py +2 -2
- fastmcp/experimental/utilities/openapi/__init__.py +10 -15
- fastmcp/experimental/utilities/openapi/director.py +14 -15
- fastmcp/experimental/utilities/openapi/json_schema_converter.py +6 -2
- fastmcp/experimental/utilities/openapi/models.py +3 -3
- fastmcp/experimental/utilities/openapi/parser.py +37 -16
- fastmcp/experimental/utilities/openapi/schemas.py +2 -2
- fastmcp/mcp_config.py +3 -4
- fastmcp/prompts/__init__.py +1 -1
- fastmcp/prompts/prompt.py +22 -19
- fastmcp/prompts/prompt_manager.py +16 -101
- fastmcp/resources/__init__.py +5 -5
- fastmcp/resources/resource.py +14 -9
- fastmcp/resources/resource_manager.py +9 -168
- fastmcp/resources/template.py +107 -17
- fastmcp/resources/types.py +30 -24
- fastmcp/server/__init__.py +1 -1
- fastmcp/server/auth/__init__.py +9 -5
- fastmcp/server/auth/auth.py +70 -43
- fastmcp/server/auth/handlers/authorize.py +326 -0
- fastmcp/server/auth/jwt_issuer.py +236 -0
- fastmcp/server/auth/middleware.py +96 -0
- fastmcp/server/auth/oauth_proxy.py +1510 -289
- fastmcp/server/auth/oidc_proxy.py +84 -20
- fastmcp/server/auth/providers/auth0.py +40 -21
- fastmcp/server/auth/providers/aws.py +29 -3
- fastmcp/server/auth/providers/azure.py +312 -131
- fastmcp/server/auth/providers/bearer.py +1 -1
- fastmcp/server/auth/providers/debug.py +114 -0
- fastmcp/server/auth/providers/descope.py +86 -29
- fastmcp/server/auth/providers/discord.py +308 -0
- fastmcp/server/auth/providers/github.py +29 -8
- fastmcp/server/auth/providers/google.py +48 -9
- fastmcp/server/auth/providers/in_memory.py +27 -3
- fastmcp/server/auth/providers/introspection.py +281 -0
- fastmcp/server/auth/providers/jwt.py +48 -31
- fastmcp/server/auth/providers/oci.py +233 -0
- fastmcp/server/auth/providers/scalekit.py +238 -0
- fastmcp/server/auth/providers/supabase.py +188 -0
- fastmcp/server/auth/providers/workos.py +35 -17
- fastmcp/server/context.py +177 -51
- fastmcp/server/dependencies.py +39 -12
- fastmcp/server/elicitation.py +1 -1
- fastmcp/server/http.py +56 -17
- fastmcp/server/low_level.py +121 -2
- fastmcp/server/middleware/__init__.py +1 -1
- fastmcp/server/middleware/caching.py +476 -0
- fastmcp/server/middleware/error_handling.py +14 -10
- fastmcp/server/middleware/logging.py +50 -39
- fastmcp/server/middleware/middleware.py +29 -16
- fastmcp/server/middleware/rate_limiting.py +3 -3
- fastmcp/server/middleware/tool_injection.py +116 -0
- fastmcp/server/openapi.py +10 -6
- fastmcp/server/proxy.py +22 -11
- fastmcp/server/server.py +725 -242
- fastmcp/settings.py +24 -10
- fastmcp/tools/__init__.py +1 -1
- fastmcp/tools/tool.py +70 -23
- fastmcp/tools/tool_manager.py +30 -112
- fastmcp/tools/tool_transform.py +12 -10
- fastmcp/utilities/cli.py +67 -28
- fastmcp/utilities/components.py +7 -2
- fastmcp/utilities/inspect.py +79 -23
- fastmcp/utilities/json_schema.py +4 -4
- fastmcp/utilities/json_schema_type.py +4 -4
- fastmcp/utilities/logging.py +118 -8
- fastmcp/utilities/mcp_server_config/__init__.py +3 -3
- fastmcp/utilities/mcp_server_config/v1/environments/base.py +1 -2
- fastmcp/utilities/mcp_server_config/v1/environments/uv.py +6 -6
- fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py +4 -4
- fastmcp/utilities/mcp_server_config/v1/schema.json +3 -0
- fastmcp/utilities/mcp_server_config/v1/sources/base.py +0 -1
- fastmcp/utilities/openapi.py +11 -11
- fastmcp/utilities/tests.py +85 -4
- fastmcp/utilities/types.py +78 -16
- fastmcp/utilities/ui.py +626 -0
- {fastmcp-2.12.5.dist-info → fastmcp-2.13.2.dist-info}/METADATA +22 -14
- fastmcp-2.13.2.dist-info/RECORD +144 -0
- {fastmcp-2.12.5.dist-info → fastmcp-2.13.2.dist-info}/WHEEL +1 -1
- fastmcp/cli/claude.py +0 -135
- fastmcp/utilities/storage.py +0 -204
- fastmcp-2.12.5.dist-info/RECORD +0 -134
- {fastmcp-2.12.5.dist-info → fastmcp-2.13.2.dist-info}/entry_points.txt +0 -0
- {fastmcp-2.12.5.dist-info → fastmcp-2.13.2.dist-info}/licenses/LICENSE +0 -0
fastmcp/__init__.py
CHANGED
fastmcp/cli/cli.py
CHANGED
|
@@ -46,9 +46,7 @@ def _get_npx_command():
|
|
|
46
46
|
# Try both npx.cmd and npx.exe on Windows
|
|
47
47
|
for cmd in ["npx.cmd", "npx.exe", "npx"]:
|
|
48
48
|
try:
|
|
49
|
-
subprocess.run(
|
|
50
|
-
[cmd, "--version"], check=True, capture_output=True, shell=True
|
|
51
|
-
)
|
|
49
|
+
subprocess.run([cmd, "--version"], check=True, capture_output=True)
|
|
52
50
|
return cmd
|
|
53
51
|
except subprocess.CalledProcessError:
|
|
54
52
|
continue
|
|
@@ -80,7 +78,7 @@ def with_argv(args: list[str] | None):
|
|
|
80
78
|
original = sys.argv[:]
|
|
81
79
|
try:
|
|
82
80
|
# Preserve the script name (sys.argv[0]) and replace the rest
|
|
83
|
-
sys.argv = [sys.argv[0]
|
|
81
|
+
sys.argv = [sys.argv[0], *args]
|
|
84
82
|
yield
|
|
85
83
|
finally:
|
|
86
84
|
sys.argv = original
|
|
@@ -277,12 +275,10 @@ async def dev(
|
|
|
277
275
|
# Set marker to prevent infinite loops when subprocess calls FastMCP
|
|
278
276
|
env = dict(os.environ.items()) | env_vars | {"FASTMCP_UV_SPAWNED": "1"}
|
|
279
277
|
|
|
280
|
-
# Run the MCP Inspector command
|
|
281
|
-
shell = sys.platform == "win32"
|
|
278
|
+
# Run the MCP Inspector command
|
|
282
279
|
process = subprocess.run(
|
|
283
|
-
[npx_cmd, inspector_cmd
|
|
280
|
+
[npx_cmd, inspector_cmd, *uv_cmd],
|
|
284
281
|
check=True,
|
|
285
|
-
shell=shell,
|
|
286
282
|
env=env,
|
|
287
283
|
)
|
|
288
284
|
sys.exit(process.returncode)
|
|
@@ -506,7 +502,7 @@ async def run(
|
|
|
506
502
|
process = subprocess.run(cmd, check=True, env=env)
|
|
507
503
|
sys.exit(process.returncode)
|
|
508
504
|
except subprocess.CalledProcessError as e:
|
|
509
|
-
logger.
|
|
505
|
+
logger.exception(
|
|
510
506
|
f"Failed to run: {e}",
|
|
511
507
|
extra={
|
|
512
508
|
"server_spec": server_spec,
|
|
@@ -530,7 +526,7 @@ async def run(
|
|
|
530
526
|
skip_source=skip_source,
|
|
531
527
|
)
|
|
532
528
|
except Exception as e:
|
|
533
|
-
logger.
|
|
529
|
+
logger.exception(
|
|
534
530
|
f"Failed to run: {e}",
|
|
535
531
|
extra={
|
|
536
532
|
"server_spec": server_spec,
|
|
@@ -717,6 +713,10 @@ async def inspect(
|
|
|
717
713
|
console.print(f" Name: {info.name}")
|
|
718
714
|
if info.version:
|
|
719
715
|
console.print(f" Version: {info.version}")
|
|
716
|
+
if info.website_url:
|
|
717
|
+
console.print(f" Website: {info.website_url}")
|
|
718
|
+
if info.icons:
|
|
719
|
+
console.print(f" Icons: {len(info.icons)}")
|
|
720
720
|
console.print(f" Generation: {info.server_generation}")
|
|
721
721
|
if info.instructions:
|
|
722
722
|
console.print(f" Instructions: {info.instructions}")
|
|
@@ -766,7 +766,7 @@ async def inspect(
|
|
|
766
766
|
console.print(formatted_json.decode("utf-8"))
|
|
767
767
|
|
|
768
768
|
except Exception as e:
|
|
769
|
-
logger.
|
|
769
|
+
logger.exception(
|
|
770
770
|
f"Failed to inspect server: {e}",
|
|
771
771
|
extra={
|
|
772
772
|
"server_spec": server_spec,
|
|
@@ -110,9 +110,9 @@ def install_claude_code(
|
|
|
110
110
|
env_config = UVEnvironment(
|
|
111
111
|
python=python_version,
|
|
112
112
|
dependencies=(with_packages or []) + ["fastmcp"],
|
|
113
|
-
requirements=
|
|
114
|
-
project=
|
|
115
|
-
editable=
|
|
113
|
+
requirements=with_requirements,
|
|
114
|
+
project=project,
|
|
115
|
+
editable=with_editable,
|
|
116
116
|
)
|
|
117
117
|
|
|
118
118
|
# Build server spec from parsed components
|
|
@@ -125,15 +125,15 @@ def install_claude_code(
|
|
|
125
125
|
full_command = env_config.build_command(["fastmcp", "run", server_spec])
|
|
126
126
|
|
|
127
127
|
# Build claude mcp add command
|
|
128
|
-
cmd_parts = [claude_cmd, "mcp", "add"]
|
|
128
|
+
cmd_parts = [claude_cmd, "mcp", "add", name]
|
|
129
129
|
|
|
130
|
-
# Add environment variables if specified
|
|
130
|
+
# Add environment variables if specified
|
|
131
131
|
if env_vars:
|
|
132
132
|
for key, value in env_vars.items():
|
|
133
133
|
cmd_parts.extend(["-e", f"{key}={value}"])
|
|
134
134
|
|
|
135
135
|
# Add server name and command
|
|
136
|
-
cmd_parts.
|
|
136
|
+
cmd_parts.append("--")
|
|
137
137
|
cmd_parts.extend(full_command)
|
|
138
138
|
|
|
139
139
|
try:
|
|
@@ -76,9 +76,9 @@ def install_claude_desktop(
|
|
|
76
76
|
env_config = UVEnvironment(
|
|
77
77
|
python=python_version,
|
|
78
78
|
dependencies=(with_packages or []) + ["fastmcp"],
|
|
79
|
-
requirements=
|
|
80
|
-
project=
|
|
81
|
-
editable=
|
|
79
|
+
requirements=with_requirements,
|
|
80
|
+
project=project,
|
|
81
|
+
editable=with_editable,
|
|
82
82
|
)
|
|
83
83
|
# Build server spec from parsed components
|
|
84
84
|
if server_object:
|
fastmcp/cli/install/cursor.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"""Cursor integration for FastMCP install using Cyclopts."""
|
|
2
2
|
|
|
3
3
|
import base64
|
|
4
|
+
import os
|
|
4
5
|
import subprocess
|
|
5
6
|
import sys
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from typing import Annotated
|
|
9
|
+
from urllib.parse import quote, urlparse
|
|
8
10
|
|
|
9
11
|
import cyclopts
|
|
10
12
|
from rich import print
|
|
@@ -36,8 +38,9 @@ def generate_cursor_deeplink(
|
|
|
36
38
|
config_json = server_config.model_dump_json(exclude_none=True)
|
|
37
39
|
config_b64 = base64.urlsafe_b64encode(config_json.encode()).decode()
|
|
38
40
|
|
|
39
|
-
# Generate the deeplink URL
|
|
40
|
-
|
|
41
|
+
# Generate the deeplink URL with properly encoded server name
|
|
42
|
+
encoded_name = quote(server_name, safe="")
|
|
43
|
+
deeplink = f"cursor://anysphere.cursor-deeplink/mcp/install?name={encoded_name}&config={config_b64}"
|
|
41
44
|
|
|
42
45
|
return deeplink
|
|
43
46
|
|
|
@@ -51,17 +54,20 @@ def open_deeplink(deeplink: str) -> bool:
|
|
|
51
54
|
Returns:
|
|
52
55
|
True if the command succeeded, False otherwise
|
|
53
56
|
"""
|
|
57
|
+
parsed = urlparse(deeplink)
|
|
58
|
+
if parsed.scheme != "cursor":
|
|
59
|
+
logger.warning(f"Invalid deeplink scheme: {parsed.scheme}")
|
|
60
|
+
return False
|
|
61
|
+
|
|
54
62
|
try:
|
|
55
63
|
if sys.platform == "darwin": # macOS
|
|
56
64
|
subprocess.run(["open", deeplink], check=True, capture_output=True)
|
|
57
65
|
elif sys.platform == "win32": # Windows
|
|
58
|
-
|
|
59
|
-
["start", deeplink], shell=True, check=True, capture_output=True
|
|
60
|
-
)
|
|
66
|
+
os.startfile(deeplink)
|
|
61
67
|
else: # Linux and others
|
|
62
68
|
subprocess.run(["xdg-open", deeplink], check=True, capture_output=True)
|
|
63
69
|
return True
|
|
64
|
-
except (subprocess.CalledProcessError, FileNotFoundError):
|
|
70
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
65
71
|
return False
|
|
66
72
|
|
|
67
73
|
|
|
@@ -110,9 +116,9 @@ def install_cursor_workspace(
|
|
|
110
116
|
env_config = UVEnvironment(
|
|
111
117
|
python=python_version,
|
|
112
118
|
dependencies=(with_packages or []) + ["fastmcp"],
|
|
113
|
-
requirements=
|
|
114
|
-
project=
|
|
115
|
-
editable=
|
|
119
|
+
requirements=with_requirements,
|
|
120
|
+
project=project,
|
|
121
|
+
editable=with_editable,
|
|
116
122
|
)
|
|
117
123
|
# Build server spec from parsed components
|
|
118
124
|
if server_object:
|
|
@@ -180,9 +186,9 @@ def install_cursor(
|
|
|
180
186
|
env_config = UVEnvironment(
|
|
181
187
|
python=python_version,
|
|
182
188
|
dependencies=(with_packages or []) + ["fastmcp"],
|
|
183
|
-
requirements=
|
|
184
|
-
project=
|
|
185
|
-
editable=
|
|
189
|
+
requirements=with_requirements,
|
|
190
|
+
project=project,
|
|
191
|
+
editable=with_editable,
|
|
186
192
|
)
|
|
187
193
|
# Build server spec from parsed components
|
|
188
194
|
if server_object:
|
|
@@ -107,9 +107,9 @@ def install_gemini_cli(
|
|
|
107
107
|
env_config = UVEnvironment(
|
|
108
108
|
python=python_version,
|
|
109
109
|
dependencies=(with_packages or []) + ["fastmcp"],
|
|
110
|
-
requirements=
|
|
111
|
-
project=
|
|
112
|
-
editable=
|
|
110
|
+
requirements=with_requirements,
|
|
111
|
+
project=project,
|
|
112
|
+
editable=with_editable,
|
|
113
113
|
)
|
|
114
114
|
|
|
115
115
|
# Build server spec from parsed components
|
fastmcp/cli/install/mcp_json.py
CHANGED
|
@@ -51,9 +51,9 @@ def install_mcp_json(
|
|
|
51
51
|
env_config = UVEnvironment(
|
|
52
52
|
python=python_version,
|
|
53
53
|
dependencies=(with_packages or []) + ["fastmcp"],
|
|
54
|
-
requirements=
|
|
55
|
-
project=
|
|
56
|
-
editable=
|
|
54
|
+
requirements=with_requirements,
|
|
55
|
+
project=project,
|
|
56
|
+
editable=with_editable,
|
|
57
57
|
)
|
|
58
58
|
# Build server spec from parsed components
|
|
59
59
|
if server_object:
|
fastmcp/cli/run.py
CHANGED
|
@@ -172,7 +172,7 @@ async def run_command(
|
|
|
172
172
|
|
|
173
173
|
# handle v1 servers
|
|
174
174
|
if isinstance(server, FastMCP1x):
|
|
175
|
-
|
|
175
|
+
await run_v1_server_async(server, host=host, port=port, transport=transport)
|
|
176
176
|
return
|
|
177
177
|
|
|
178
178
|
kwargs = {}
|
|
@@ -197,24 +197,29 @@ async def run_command(
|
|
|
197
197
|
sys.exit(1)
|
|
198
198
|
|
|
199
199
|
|
|
200
|
-
def
|
|
200
|
+
async def run_v1_server_async(
|
|
201
201
|
server: FastMCP1x,
|
|
202
202
|
host: str | None = None,
|
|
203
203
|
port: int | None = None,
|
|
204
204
|
transport: TransportType | None = None,
|
|
205
205
|
) -> None:
|
|
206
|
-
|
|
206
|
+
"""Run a FastMCP 1.x server using async methods.
|
|
207
207
|
|
|
208
|
+
Args:
|
|
209
|
+
server: FastMCP 1.x server instance
|
|
210
|
+
host: Host to bind to
|
|
211
|
+
port: Port to bind to
|
|
212
|
+
transport: Transport protocol to use
|
|
213
|
+
"""
|
|
208
214
|
if host:
|
|
209
215
|
server.settings.host = host
|
|
210
216
|
if port:
|
|
211
217
|
server.settings.port = port
|
|
218
|
+
|
|
212
219
|
match transport:
|
|
213
220
|
case "stdio":
|
|
214
|
-
|
|
221
|
+
await server.run_stdio_async()
|
|
215
222
|
case "http" | "streamable-http" | None:
|
|
216
|
-
|
|
223
|
+
await server.run_streamable_http_async()
|
|
217
224
|
case "sse":
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
runner()
|
|
225
|
+
await server.run_sse_async()
|
fastmcp/client/__init__.py
CHANGED
|
@@ -15,18 +15,18 @@ from .transports import (
|
|
|
15
15
|
from .auth import OAuth, BearerAuth
|
|
16
16
|
|
|
17
17
|
__all__ = [
|
|
18
|
+
"BearerAuth",
|
|
18
19
|
"Client",
|
|
19
20
|
"ClientTransport",
|
|
20
|
-
"
|
|
21
|
-
"SSETransport",
|
|
22
|
-
"StdioTransport",
|
|
23
|
-
"PythonStdioTransport",
|
|
21
|
+
"FastMCPTransport",
|
|
24
22
|
"NodeStdioTransport",
|
|
25
|
-
"UvxStdioTransport",
|
|
26
|
-
"UvStdioTransport",
|
|
27
23
|
"NpxStdioTransport",
|
|
28
|
-
"FastMCPTransport",
|
|
29
|
-
"StreamableHttpTransport",
|
|
30
24
|
"OAuth",
|
|
31
|
-
"
|
|
25
|
+
"PythonStdioTransport",
|
|
26
|
+
"SSETransport",
|
|
27
|
+
"StdioTransport",
|
|
28
|
+
"StreamableHttpTransport",
|
|
29
|
+
"UvStdioTransport",
|
|
30
|
+
"UvxStdioTransport",
|
|
31
|
+
"WSTransport",
|
|
32
32
|
]
|