fastmcp 2.10.5__py3-none-any.whl → 2.11.0__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.
Files changed (65) hide show
  1. fastmcp/__init__.py +7 -2
  2. fastmcp/cli/cli.py +128 -33
  3. fastmcp/cli/install/__init__.py +2 -2
  4. fastmcp/cli/install/claude_code.py +42 -1
  5. fastmcp/cli/install/claude_desktop.py +42 -1
  6. fastmcp/cli/install/cursor.py +42 -1
  7. fastmcp/cli/install/{mcp_config.py → mcp_json.py} +51 -7
  8. fastmcp/cli/run.py +127 -1
  9. fastmcp/client/__init__.py +2 -0
  10. fastmcp/client/auth/oauth.py +68 -99
  11. fastmcp/client/oauth_callback.py +18 -0
  12. fastmcp/client/transports.py +69 -15
  13. fastmcp/contrib/component_manager/example.py +2 -2
  14. fastmcp/experimental/server/openapi/README.md +266 -0
  15. fastmcp/experimental/server/openapi/__init__.py +38 -0
  16. fastmcp/experimental/server/openapi/components.py +348 -0
  17. fastmcp/experimental/server/openapi/routing.py +132 -0
  18. fastmcp/experimental/server/openapi/server.py +466 -0
  19. fastmcp/experimental/utilities/openapi/README.md +239 -0
  20. fastmcp/experimental/utilities/openapi/__init__.py +68 -0
  21. fastmcp/experimental/utilities/openapi/director.py +208 -0
  22. fastmcp/experimental/utilities/openapi/formatters.py +355 -0
  23. fastmcp/experimental/utilities/openapi/json_schema_converter.py +340 -0
  24. fastmcp/experimental/utilities/openapi/models.py +85 -0
  25. fastmcp/experimental/utilities/openapi/parser.py +618 -0
  26. fastmcp/experimental/utilities/openapi/schemas.py +538 -0
  27. fastmcp/mcp_config.py +125 -88
  28. fastmcp/prompts/prompt.py +11 -1
  29. fastmcp/prompts/prompt_manager.py +1 -1
  30. fastmcp/resources/resource.py +21 -1
  31. fastmcp/resources/resource_manager.py +2 -2
  32. fastmcp/resources/template.py +20 -1
  33. fastmcp/server/auth/__init__.py +17 -2
  34. fastmcp/server/auth/auth.py +144 -7
  35. fastmcp/server/auth/providers/bearer.py +25 -473
  36. fastmcp/server/auth/providers/in_memory.py +4 -2
  37. fastmcp/server/auth/providers/jwt.py +538 -0
  38. fastmcp/server/auth/providers/workos.py +170 -0
  39. fastmcp/server/auth/registry.py +52 -0
  40. fastmcp/server/context.py +110 -26
  41. fastmcp/server/dependencies.py +9 -2
  42. fastmcp/server/http.py +62 -30
  43. fastmcp/server/middleware/middleware.py +3 -23
  44. fastmcp/server/openapi.py +26 -13
  45. fastmcp/server/proxy.py +89 -8
  46. fastmcp/server/server.py +170 -62
  47. fastmcp/settings.py +83 -18
  48. fastmcp/tools/tool.py +41 -6
  49. fastmcp/tools/tool_manager.py +39 -3
  50. fastmcp/tools/tool_transform.py +122 -6
  51. fastmcp/utilities/components.py +35 -2
  52. fastmcp/utilities/json_schema.py +136 -98
  53. fastmcp/utilities/json_schema_type.py +1 -3
  54. fastmcp/utilities/mcp_config.py +28 -0
  55. fastmcp/utilities/openapi.py +306 -30
  56. fastmcp/utilities/tests.py +54 -6
  57. fastmcp/utilities/types.py +89 -11
  58. {fastmcp-2.10.5.dist-info → fastmcp-2.11.0.dist-info}/METADATA +4 -3
  59. fastmcp-2.11.0.dist-info/RECORD +108 -0
  60. fastmcp/server/auth/providers/bearer_env.py +0 -63
  61. fastmcp/utilities/cache.py +0 -26
  62. fastmcp-2.10.5.dist-info/RECORD +0 -93
  63. {fastmcp-2.10.5.dist-info → fastmcp-2.11.0.dist-info}/WHEEL +0 -0
  64. {fastmcp-2.10.5.dist-info → fastmcp-2.11.0.dist-info}/entry_points.txt +0 -0
  65. {fastmcp-2.10.5.dist-info → fastmcp-2.11.0.dist-info}/licenses/LICENSE +0 -0
fastmcp/__init__.py CHANGED
@@ -1,10 +1,15 @@
1
1
  """FastMCP - An ergonomic MCP interface."""
2
2
 
3
3
  import warnings
4
- from importlib.metadata import version
4
+ from importlib.metadata import version as _version
5
5
  from fastmcp.settings import Settings
6
+ from fastmcp.utilities.logging import configure_logging as _configure_logging
6
7
 
7
8
  settings = Settings()
9
+ _configure_logging(
10
+ level=settings.log_level,
11
+ enable_rich_tracebacks=settings.enable_rich_tracebacks,
12
+ )
8
13
 
9
14
  from fastmcp.server.server import FastMCP
10
15
  from fastmcp.server.context import Context
@@ -13,7 +18,7 @@ import fastmcp.server
13
18
  from fastmcp.client import Client
14
19
  from . import client
15
20
 
16
- __version__ = version("fastmcp")
21
+ __version__ = _version("fastmcp")
17
22
 
18
23
 
19
24
  # ensure deprecation warnings are displayed by default
fastmcp/cli/cli.py CHANGED
@@ -62,11 +62,22 @@ def _build_uv_command(
62
62
  with_editable: Path | None = None,
63
63
  with_packages: list[str] | None = None,
64
64
  no_banner: bool = False,
65
+ python_version: str | None = None,
66
+ with_requirements: Path | None = None,
67
+ project: Path | None = None,
65
68
  ) -> list[str]:
66
69
  """Build the uv run command that runs a MCP server through mcp run."""
67
- cmd = ["uv"]
70
+ cmd = ["uv", "run"]
68
71
 
69
- cmd.extend(["run", "--with", "fastmcp"])
72
+ # Add Python version if specified
73
+ if python_version:
74
+ cmd.extend(["--python", python_version])
75
+
76
+ # Add project if specified
77
+ if project:
78
+ cmd.extend(["--project", str(project)])
79
+
80
+ cmd.extend(["--with", "fastmcp"])
70
81
 
71
82
  if with_editable:
72
83
  cmd.extend(["--with-editable", str(with_editable)])
@@ -76,6 +87,9 @@ def _build_uv_command(
76
87
  if pkg:
77
88
  cmd.extend(["--with", pkg])
78
89
 
90
+ if with_requirements:
91
+ cmd.extend(["--with-requirements", str(with_requirements)])
92
+
79
93
  # Add mcp run command
80
94
  cmd.extend(["fastmcp", "run", server_spec])
81
95
 
@@ -163,6 +177,27 @@ def dev(
163
177
  help="Port for the MCP Inspector Proxy server",
164
178
  ),
165
179
  ] = None,
180
+ python: Annotated[
181
+ str | None,
182
+ cyclopts.Parameter(
183
+ "--python",
184
+ help="Python version to use (e.g., 3.10, 3.11)",
185
+ ),
186
+ ] = None,
187
+ with_requirements: Annotated[
188
+ Path | None,
189
+ cyclopts.Parameter(
190
+ "--with-requirements",
191
+ help="Requirements file to install dependencies from",
192
+ ),
193
+ ] = None,
194
+ project: Annotated[
195
+ Path | None,
196
+ cyclopts.Parameter(
197
+ "--project",
198
+ help="Run the command within the given project directory",
199
+ ),
200
+ ] = None,
166
201
  ) -> None:
167
202
  """Run an MCP server with the MCP Inspector for development.
168
203
 
@@ -209,7 +244,13 @@ def dev(
209
244
  inspector_cmd += f"@{inspector_version}"
210
245
 
211
246
  uv_cmd = _build_uv_command(
212
- server_spec, with_editable, with_packages, no_banner=True
247
+ server_spec,
248
+ with_editable,
249
+ with_packages,
250
+ no_banner=True,
251
+ python_version=python,
252
+ with_requirements=with_requirements,
253
+ project=project,
213
254
  )
214
255
 
215
256
  # Run the MCP Inspector command with shell=True on Windows
@@ -244,7 +285,7 @@ def dev(
244
285
  @app.command
245
286
  def run(
246
287
  server_spec: str,
247
- *,
288
+ *server_args: str,
248
289
  transport: Annotated[
249
290
  run_module.TransportType | None,
250
291
  cyclopts.Parameter(
@@ -288,23 +329,50 @@ def run(
288
329
  negative=False,
289
330
  ),
290
331
  ] = False,
332
+ python: Annotated[
333
+ str | None,
334
+ cyclopts.Parameter(
335
+ "--python",
336
+ help="Python version to use (e.g., 3.10, 3.11)",
337
+ ),
338
+ ] = None,
339
+ with_packages: Annotated[
340
+ list[str],
341
+ cyclopts.Parameter(
342
+ "--with",
343
+ help="Additional packages to install (can be used multiple times)",
344
+ negative=False,
345
+ ),
346
+ ] = [],
347
+ project: Annotated[
348
+ Path | None,
349
+ cyclopts.Parameter(
350
+ "--project",
351
+ help="Run the command within the given project directory",
352
+ ),
353
+ ] = None,
354
+ with_requirements: Annotated[
355
+ Path | None,
356
+ cyclopts.Parameter(
357
+ "--with-requirements",
358
+ help="Requirements file to install dependencies from",
359
+ ),
360
+ ] = None,
291
361
  ) -> None:
292
362
  """Run an MCP server or connect to a remote one.
293
363
 
294
- The server can be specified in three ways:
295
- 1. Module approach: server.py - runs the module directly, looking for an object named 'mcp', 'server', or 'app'
296
- 2. Import approach: server.py:app - imports and runs the specified server object
297
- 3. URL approach: http://server-url - connects to a remote server and creates a proxy
364
+ The server can be specified in four ways:
365
+ 1. Module approach: "server.py" - runs the module directly, looking for an object named 'mcp', 'server', or 'app'
366
+ 2. Import approach: "server.py:app" - imports and runs the specified server object
367
+ 3. URL approach: "http://server-url" - connects to a remote server and creates a proxy
368
+ 4. MCPConfig file: "mcp.json" - runs as a proxy server for the MCP Servers in the MCPConfig file
298
369
 
299
370
  Server arguments can be passed after -- :
300
371
  fastmcp run server.py -- --config config.json --debug
301
372
 
302
373
  Args:
303
- server_spec: Python file, object specification (file:obj), or URL
374
+ server_spec: Python file, object specification (file:obj), MCPConfig file, or URL
304
375
  """
305
- # TODO: Handle server_args from extra context
306
- server_args = [] # Will need to handle this with Cyclopts context
307
-
308
376
  logger.debug(
309
377
  "Running server or client",
310
378
  extra={
@@ -314,30 +382,57 @@ def run(
314
382
  "port": port,
315
383
  "path": path,
316
384
  "log_level": log_level,
317
- "server_args": server_args,
385
+ "server_args": list(server_args),
318
386
  },
319
387
  )
320
388
 
321
- try:
322
- run_module.run_command(
323
- server_spec=server_spec,
324
- transport=transport,
325
- host=host,
326
- port=port,
327
- path=path,
328
- log_level=log_level,
329
- server_args=server_args,
330
- show_banner=not no_banner,
331
- )
332
- except Exception as e:
333
- logger.error(
334
- f"Failed to run: {e}",
335
- extra={
336
- "server_spec": server_spec,
337
- "error": str(e),
338
- },
339
- )
340
- sys.exit(1)
389
+ # If any uv-specific options are provided, use uv run
390
+ if python or with_packages or with_requirements or project:
391
+ try:
392
+ run_module.run_with_uv(
393
+ server_spec=server_spec,
394
+ python_version=python,
395
+ with_packages=with_packages,
396
+ with_requirements=with_requirements,
397
+ project=project,
398
+ transport=transport,
399
+ host=host,
400
+ port=port,
401
+ path=path,
402
+ log_level=log_level,
403
+ show_banner=not no_banner,
404
+ )
405
+ except Exception as e:
406
+ logger.error(
407
+ f"Failed to run: {e}",
408
+ extra={
409
+ "server_spec": server_spec,
410
+ "error": str(e),
411
+ },
412
+ )
413
+ sys.exit(1)
414
+ else:
415
+ # Use direct import for backwards compatibility
416
+ try:
417
+ run_module.run_command(
418
+ server_spec=server_spec,
419
+ transport=transport,
420
+ host=host,
421
+ port=port,
422
+ path=path,
423
+ log_level=log_level,
424
+ server_args=list(server_args),
425
+ show_banner=not no_banner,
426
+ )
427
+ except Exception as e:
428
+ logger.error(
429
+ f"Failed to run: {e}",
430
+ extra={
431
+ "server_spec": server_spec,
432
+ "error": str(e),
433
+ },
434
+ )
435
+ sys.exit(1)
341
436
 
342
437
 
343
438
  @app.command
@@ -5,7 +5,7 @@ import cyclopts
5
5
  from .claude_code import claude_code_command
6
6
  from .claude_desktop import claude_desktop_command
7
7
  from .cursor import cursor_command
8
- from .mcp_config import mcp_config_command
8
+ from .mcp_json import mcp_json_command
9
9
 
10
10
  # Create a cyclopts app for install subcommands
11
11
  install_app = cyclopts.App(
@@ -17,4 +17,4 @@ install_app = cyclopts.App(
17
17
  install_app.command(claude_code_command, name="claude-code")
18
18
  install_app.command(claude_desktop_command, name="claude-desktop")
19
19
  install_app.command(cursor_command, name="cursor")
20
- install_app.command(mcp_config_command, name="mcp-json")
20
+ install_app.command(mcp_json_command, name="mcp-json")
@@ -77,6 +77,9 @@ def install_claude_code(
77
77
  with_editable: Path | None = None,
78
78
  with_packages: list[str] | None = None,
79
79
  env_vars: dict[str, str] | None = None,
80
+ python_version: str | None = None,
81
+ with_requirements: Path | None = None,
82
+ project: Path | None = None,
80
83
  ) -> bool:
81
84
  """Install FastMCP server in Claude Code.
82
85
 
@@ -87,6 +90,9 @@ def install_claude_code(
87
90
  with_editable: Optional directory to install in editable mode
88
91
  with_packages: Optional list of additional packages to install
89
92
  env_vars: Optional dictionary of environment variables
93
+ python_version: Optional Python version to use
94
+ with_requirements: Optional requirements file to install from
95
+ project: Optional project directory to run within
90
96
 
91
97
  Returns:
92
98
  True if installation was successful, False otherwise
@@ -103,6 +109,14 @@ def install_claude_code(
103
109
  # Build uv run command
104
110
  args = ["run"]
105
111
 
112
+ # Add Python version if specified
113
+ if python_version:
114
+ args.extend(["--python", python_version])
115
+
116
+ # Add project if specified
117
+ if project:
118
+ args.extend(["--project", str(project)])
119
+
106
120
  # Collect all packages in a set to deduplicate
107
121
  packages = {"fastmcp"}
108
122
  if with_packages:
@@ -115,6 +129,9 @@ def install_claude_code(
115
129
  if with_editable:
116
130
  args.extend(["--with-editable", str(with_editable)])
117
131
 
132
+ if with_requirements:
133
+ args.extend(["--with-requirements", str(with_requirements)])
134
+
118
135
  # Build server spec from parsed components
119
136
  if server_object:
120
137
  server_spec = f"{file.resolve()}:{server_object}"
@@ -156,7 +173,7 @@ def claude_code_command(
156
173
  server_name: Annotated[
157
174
  str | None,
158
175
  cyclopts.Parameter(
159
- name=["--server-name", "-n"],
176
+ name=["--name", "-n"],
160
177
  help="Custom name for the server in Claude Code",
161
178
  ),
162
179
  ] = None,
@@ -190,6 +207,27 @@ def claude_code_command(
190
207
  help="Load environment variables from .env file",
191
208
  ),
192
209
  ] = None,
210
+ python: Annotated[
211
+ str | None,
212
+ cyclopts.Parameter(
213
+ "--python",
214
+ help="Python version to use (e.g., 3.10, 3.11)",
215
+ ),
216
+ ] = None,
217
+ with_requirements: Annotated[
218
+ Path | None,
219
+ cyclopts.Parameter(
220
+ "--with-requirements",
221
+ help="Requirements file to install dependencies from",
222
+ ),
223
+ ] = None,
224
+ project: Annotated[
225
+ Path | None,
226
+ cyclopts.Parameter(
227
+ "--project",
228
+ help="Run the command within the given project directory",
229
+ ),
230
+ ] = None,
193
231
  ) -> None:
194
232
  """Install an MCP server in Claude Code.
195
233
 
@@ -207,6 +245,9 @@ def claude_code_command(
207
245
  with_editable=with_editable,
208
246
  with_packages=packages,
209
247
  env_vars=env_dict,
248
+ python_version=python,
249
+ with_requirements=with_requirements,
250
+ project=project,
210
251
  )
211
252
 
212
253
  if success:
@@ -42,6 +42,9 @@ def install_claude_desktop(
42
42
  with_editable: Path | None = None,
43
43
  with_packages: list[str] | None = None,
44
44
  env_vars: dict[str, str] | None = None,
45
+ python_version: str | None = None,
46
+ with_requirements: Path | None = None,
47
+ project: Path | None = None,
45
48
  ) -> bool:
46
49
  """Install FastMCP server in Claude Desktop.
47
50
 
@@ -52,6 +55,9 @@ def install_claude_desktop(
52
55
  with_editable: Optional directory to install in editable mode
53
56
  with_packages: Optional list of additional packages to install
54
57
  env_vars: Optional dictionary of environment variables
58
+ python_version: Optional Python version to use
59
+ with_requirements: Optional requirements file to install from
60
+ project: Optional project directory to run within
55
61
 
56
62
  Returns:
57
63
  True if installation was successful, False otherwise
@@ -69,6 +75,14 @@ def install_claude_desktop(
69
75
  # Build uv run command
70
76
  args = ["run"]
71
77
 
78
+ # Add Python version if specified
79
+ if python_version:
80
+ args.extend(["--python", python_version])
81
+
82
+ # Add project if specified
83
+ if project:
84
+ args.extend(["--project", str(project)])
85
+
72
86
  # Collect all packages in a set to deduplicate
73
87
  packages = {"fastmcp"}
74
88
  if with_packages:
@@ -81,6 +95,9 @@ def install_claude_desktop(
81
95
  if with_editable:
82
96
  args.extend(["--with-editable", str(with_editable)])
83
97
 
98
+ if with_requirements:
99
+ args.extend(["--with-requirements", str(with_requirements)])
100
+
84
101
  # Build server spec from parsed components
85
102
  if server_object:
86
103
  server_spec = f"{file.resolve()}:{server_object}"
@@ -129,7 +146,7 @@ def claude_desktop_command(
129
146
  server_name: Annotated[
130
147
  str | None,
131
148
  cyclopts.Parameter(
132
- name=["--server-name", "-n"],
149
+ name=["--name", "-n"],
133
150
  help="Custom name for the server in Claude Desktop's config",
134
151
  ),
135
152
  ] = None,
@@ -163,6 +180,27 @@ def claude_desktop_command(
163
180
  help="Load environment variables from .env file",
164
181
  ),
165
182
  ] = None,
183
+ python: Annotated[
184
+ str | None,
185
+ cyclopts.Parameter(
186
+ "--python",
187
+ help="Python version to use (e.g., 3.10, 3.11)",
188
+ ),
189
+ ] = None,
190
+ with_requirements: Annotated[
191
+ Path | None,
192
+ cyclopts.Parameter(
193
+ "--with-requirements",
194
+ help="Requirements file to install dependencies from",
195
+ ),
196
+ ] = None,
197
+ project: Annotated[
198
+ Path | None,
199
+ cyclopts.Parameter(
200
+ "--project",
201
+ help="Run the command within the given project directory",
202
+ ),
203
+ ] = None,
166
204
  ) -> None:
167
205
  """Install an MCP server in Claude Desktop.
168
206
 
@@ -180,6 +218,9 @@ def claude_desktop_command(
180
218
  with_editable=with_editable,
181
219
  with_packages=with_packages,
182
220
  env_vars=env_dict,
221
+ python_version=python,
222
+ with_requirements=with_requirements,
223
+ project=project,
183
224
  )
184
225
 
185
226
  if not success:
@@ -72,6 +72,9 @@ def install_cursor(
72
72
  with_editable: Path | None = None,
73
73
  with_packages: list[str] | None = None,
74
74
  env_vars: dict[str, str] | None = None,
75
+ python_version: str | None = None,
76
+ with_requirements: Path | None = None,
77
+ project: Path | None = None,
75
78
  ) -> bool:
76
79
  """Install FastMCP server in Cursor.
77
80
 
@@ -82,6 +85,9 @@ def install_cursor(
82
85
  with_editable: Optional directory to install in editable mode
83
86
  with_packages: Optional list of additional packages to install
84
87
  env_vars: Optional dictionary of environment variables
88
+ python_version: Optional Python version to use
89
+ with_requirements: Optional requirements file to install from
90
+ project: Optional project directory to run within
85
91
 
86
92
  Returns:
87
93
  True if installation was successful, False otherwise
@@ -89,6 +95,14 @@ def install_cursor(
89
95
  # Build uv run command
90
96
  args = ["run"]
91
97
 
98
+ # Add Python version if specified
99
+ if python_version:
100
+ args.extend(["--python", python_version])
101
+
102
+ # Add project if specified
103
+ if project:
104
+ args.extend(["--project", str(project)])
105
+
92
106
  # Collect all packages in a set to deduplicate
93
107
  packages = {"fastmcp"}
94
108
  if with_packages:
@@ -101,6 +115,9 @@ def install_cursor(
101
115
  if with_editable:
102
116
  args.extend(["--with-editable", str(with_editable)])
103
117
 
118
+ if with_requirements:
119
+ args.extend(["--with-requirements", str(with_requirements)])
120
+
104
121
  # Build server spec from parsed components
105
122
  if server_object:
106
123
  server_spec = f"{file.resolve()}:{server_object}"
@@ -139,7 +156,7 @@ def cursor_command(
139
156
  server_name: Annotated[
140
157
  str | None,
141
158
  cyclopts.Parameter(
142
- name=["--server-name", "-n"],
159
+ name=["--name", "-n"],
143
160
  help="Custom name for the server in Cursor",
144
161
  ),
145
162
  ] = None,
@@ -173,6 +190,27 @@ def cursor_command(
173
190
  help="Load environment variables from .env file",
174
191
  ),
175
192
  ] = None,
193
+ python: Annotated[
194
+ str | None,
195
+ cyclopts.Parameter(
196
+ "--python",
197
+ help="Python version to use (e.g., 3.10, 3.11)",
198
+ ),
199
+ ] = None,
200
+ with_requirements: Annotated[
201
+ Path | None,
202
+ cyclopts.Parameter(
203
+ "--with-requirements",
204
+ help="Requirements file to install dependencies from",
205
+ ),
206
+ ] = None,
207
+ project: Annotated[
208
+ Path | None,
209
+ cyclopts.Parameter(
210
+ "--project",
211
+ help="Run the command within the given project directory",
212
+ ),
213
+ ] = None,
176
214
  ) -> None:
177
215
  """Install an MCP server in Cursor.
178
216
 
@@ -190,6 +228,9 @@ def cursor_command(
190
228
  with_editable=with_editable,
191
229
  with_packages=with_packages,
192
230
  env_vars=env_dict,
231
+ python_version=python,
232
+ with_requirements=with_requirements,
233
+ project=project,
193
234
  )
194
235
 
195
236
  if not success:
@@ -16,7 +16,7 @@ from .shared import process_common_args
16
16
  logger = get_logger(__name__)
17
17
 
18
18
 
19
- def install_mcp_config(
19
+ def install_mcp_json(
20
20
  file: Path,
21
21
  server_object: str | None,
22
22
  name: str,
@@ -25,6 +25,9 @@ def install_mcp_config(
25
25
  with_packages: list[str] | None = None,
26
26
  env_vars: dict[str, str] | None = None,
27
27
  copy: bool = False,
28
+ python_version: str | None = None,
29
+ with_requirements: Path | None = None,
30
+ project: Path | None = None,
28
31
  ) -> bool:
29
32
  """Generate MCP configuration JSON for manual installation.
30
33
 
@@ -36,6 +39,9 @@ def install_mcp_config(
36
39
  with_packages: Optional list of additional packages to install
37
40
  env_vars: Optional dictionary of environment variables
38
41
  copy: If True, copy to clipboard instead of printing to stdout
42
+ python_version: Optional Python version to use
43
+ with_requirements: Optional requirements file to install from
44
+ project: Optional project directory to run within
39
45
 
40
46
  Returns:
41
47
  True if generation was successful, False otherwise
@@ -44,6 +50,14 @@ def install_mcp_config(
44
50
  # Build uv run command
45
51
  args = ["run"]
46
52
 
53
+ # Add Python version if specified
54
+ if python_version:
55
+ args.extend(["--python", python_version])
56
+
57
+ # Add project if specified
58
+ if project:
59
+ args.extend(["--project", str(project)])
60
+
47
61
  # Collect all packages in a set to deduplicate
48
62
  packages = {"fastmcp"}
49
63
  if with_packages:
@@ -56,6 +70,9 @@ def install_mcp_config(
56
70
  if with_editable:
57
71
  args.extend(["--with-editable", str(with_editable)])
58
72
 
73
+ if with_requirements:
74
+ args.extend(["--with-requirements", str(with_requirements)])
75
+
59
76
  # Build server spec from parsed components
60
77
  if server_object:
61
78
  server_spec = f"{file.resolve()}:{server_object}"
@@ -65,15 +82,18 @@ def install_mcp_config(
65
82
  # Add fastmcp run command
66
83
  args.extend(["fastmcp", "run", server_spec])
67
84
 
68
- # Build MCP server configuration (just the server object, not the wrapper)
69
- config = {
85
+ # Build MCP server configuration
86
+ server_config = {
70
87
  "command": "uv",
71
88
  "args": args,
72
89
  }
73
90
 
74
91
  # Add environment variables if provided
75
92
  if env_vars:
76
- config["env"] = env_vars
93
+ server_config["env"] = env_vars
94
+
95
+ # Wrap with server name as root key
96
+ config = {name: server_config}
77
97
 
78
98
  # Convert to JSON
79
99
  json_output = json.dumps(config, indent=2)
@@ -93,13 +113,13 @@ def install_mcp_config(
93
113
  return False
94
114
 
95
115
 
96
- def mcp_config_command(
116
+ def mcp_json_command(
97
117
  server_spec: str,
98
118
  *,
99
119
  server_name: Annotated[
100
120
  str | None,
101
121
  cyclopts.Parameter(
102
- name=["--server-name", "-n"],
122
+ name=["--name", "-n"],
103
123
  help="Custom name for the server in MCP config",
104
124
  ),
105
125
  ] = None,
@@ -141,6 +161,27 @@ def mcp_config_command(
141
161
  negative=False,
142
162
  ),
143
163
  ] = False,
164
+ python: Annotated[
165
+ str | None,
166
+ cyclopts.Parameter(
167
+ "--python",
168
+ help="Python version to use (e.g., 3.10, 3.11)",
169
+ ),
170
+ ] = None,
171
+ with_requirements: Annotated[
172
+ Path | None,
173
+ cyclopts.Parameter(
174
+ "--with-requirements",
175
+ help="Requirements file to install dependencies from",
176
+ ),
177
+ ] = None,
178
+ project: Annotated[
179
+ Path | None,
180
+ cyclopts.Parameter(
181
+ "--project",
182
+ help="Run the command within the given project directory",
183
+ ),
184
+ ] = None,
144
185
  ) -> None:
145
186
  """Generate MCP configuration JSON for manual installation.
146
187
 
@@ -151,7 +192,7 @@ def mcp_config_command(
151
192
  server_spec, server_name, with_packages, env_vars, env_file
152
193
  )
153
194
 
154
- success = install_mcp_config(
195
+ success = install_mcp_json(
155
196
  file=file,
156
197
  server_object=server_object,
157
198
  name=name,
@@ -159,6 +200,9 @@ def mcp_config_command(
159
200
  with_packages=packages,
160
201
  env_vars=env_dict,
161
202
  copy=copy,
203
+ python_version=python,
204
+ with_requirements=with_requirements,
205
+ project=project,
162
206
  )
163
207
 
164
208
  if not success: