mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-19 03:54:18 +02:00
Merge branch 'patch-1' of github.com:vl-kp/fastmcp into patch-1
This commit is contained in:
commit
a73e798b36
10 changed files with 128 additions and 85 deletions
|
|
@ -243,17 +243,25 @@
|
|||
"editable": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Directory to install in editable mode",
|
||||
"description": "Directories to install in editable mode",
|
||||
"examples": [
|
||||
".",
|
||||
"../my-package"
|
||||
[
|
||||
".",
|
||||
"../my-package"
|
||||
],
|
||||
[
|
||||
"/path/to/package"
|
||||
]
|
||||
],
|
||||
"title": "Editable"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,17 +243,25 @@
|
|||
"editable": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Directory to install in editable mode",
|
||||
"description": "Directories to install in editable mode",
|
||||
"examples": [
|
||||
".",
|
||||
"../my-package"
|
||||
[
|
||||
".",
|
||||
"../my-package"
|
||||
],
|
||||
[
|
||||
"/path/to/package"
|
||||
]
|
||||
],
|
||||
"title": "Editable"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ def update_claude_config(
|
|||
file_spec: str,
|
||||
server_name: str,
|
||||
*,
|
||||
with_editable: Path | None = None,
|
||||
with_editable: list[Path] | None = None,
|
||||
with_packages: list[str] | None = None,
|
||||
env_vars: dict[str, str] | None = None,
|
||||
) -> bool:
|
||||
|
|
@ -43,7 +43,7 @@ def update_claude_config(
|
|||
Args:
|
||||
file_spec: Path to the server file, optionally with :object suffix
|
||||
server_name: Name for the server in Claude's config
|
||||
with_editable: Optional directory to install in editable mode
|
||||
with_editable: Optional list of directories to install in editable mode
|
||||
with_packages: Optional list of additional packages to install
|
||||
env_vars: Optional dictionary of environment variables. These are merged with
|
||||
any existing variables, with new values taking precedence.
|
||||
|
|
@ -101,7 +101,7 @@ def update_claude_config(
|
|||
# Build uv run command using Environment.build_uv_args()
|
||||
env_config = Environment(
|
||||
dependencies=deduplicated_packages,
|
||||
editable=[str(with_editable)] if with_editable else None,
|
||||
editable=[str(p) for p in with_editable] if with_editable else None,
|
||||
)
|
||||
args = env_config.build_uv_args()
|
||||
|
||||
|
|
|
|||
|
|
@ -126,20 +126,21 @@ async def dev(
|
|||
server_spec: str | None = None,
|
||||
*,
|
||||
with_editable: Annotated[
|
||||
Path | None,
|
||||
list[Path] | None,
|
||||
cyclopts.Parameter(
|
||||
name=["--with-editable", "-e"],
|
||||
help="Directory containing pyproject.toml to install in editable mode",
|
||||
"--with-editable",
|
||||
help="Directory containing pyproject.toml to install in editable mode (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = None,
|
||||
with_packages: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--with",
|
||||
help="Additional packages to install",
|
||||
help="Additional packages to install (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
inspector_version: Annotated[
|
||||
str | None,
|
||||
cyclopts.Parameter(
|
||||
|
|
@ -188,6 +189,9 @@ async def dev(
|
|||
Args:
|
||||
server_spec: Python file to run, optionally with :object suffix, or None to auto-detect fastmcp.json
|
||||
"""
|
||||
# Convert None to empty lists for list parameters
|
||||
with_editable = with_editable or []
|
||||
with_packages = with_packages or []
|
||||
from pathlib import Path
|
||||
|
||||
from fastmcp.utilities.fastmcp_config import FastMCPConfig
|
||||
|
|
@ -229,13 +233,9 @@ async def dev(
|
|||
if config.environment.requirements
|
||||
else None
|
||||
)
|
||||
# Note: config.environment.editable is a list, but CLI only supports single path
|
||||
# Take the first editable path if available
|
||||
with_editable = with_editable or (
|
||||
Path(config.environment.editable[0])
|
||||
if config.environment.editable and config.environment.editable[0]
|
||||
else None
|
||||
)
|
||||
# Merge editable paths from config with CLI args
|
||||
if config.environment.editable and not with_editable:
|
||||
with_editable = [Path(p) for p in config.environment.editable]
|
||||
|
||||
# Merge packages from both sources
|
||||
if config.environment.dependencies:
|
||||
|
|
@ -256,7 +256,7 @@ async def dev(
|
|||
"Starting dev server",
|
||||
extra={
|
||||
"server_spec": server_spec,
|
||||
"with_editable": str(with_editable) if with_editable else None,
|
||||
"with_editable": [str(p) for p in with_editable] if with_editable else None,
|
||||
"with_packages": with_packages,
|
||||
"ui_port": ui_port,
|
||||
"server_port": server_port,
|
||||
|
|
@ -305,7 +305,7 @@ async def dev(
|
|||
dependencies=with_packages if with_packages else None,
|
||||
requirements=str(with_requirements) if with_requirements else None,
|
||||
project=str(project) if project else None,
|
||||
editable=[str(with_editable)] if with_editable else None,
|
||||
editable=[str(p) for p in with_editable] if with_editable else None,
|
||||
)
|
||||
uv_cmd = ["uv"] + env_config.build_uv_args(["fastmcp", "run", server_spec])
|
||||
|
||||
|
|
@ -396,13 +396,13 @@ async def run(
|
|||
),
|
||||
] = None,
|
||||
with_packages: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--with",
|
||||
help="Additional packages to install (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
project: Annotated[
|
||||
Path | None,
|
||||
cyclopts.Parameter(
|
||||
|
|
@ -450,6 +450,8 @@ async def run(
|
|||
Args:
|
||||
server_spec: Python file, object specification (file:obj), config file, URL, or None to auto-detect
|
||||
"""
|
||||
# Convert None to empty lists for list parameters
|
||||
with_packages = with_packages or []
|
||||
# Load configuration if needed
|
||||
from pathlib import Path
|
||||
|
||||
|
|
@ -631,13 +633,13 @@ async def inspect(
|
|||
),
|
||||
] = None,
|
||||
with_packages: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--with",
|
||||
help="Additional packages to install (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
project: Annotated[
|
||||
Path | None,
|
||||
cyclopts.Parameter(
|
||||
|
|
@ -670,6 +672,8 @@ async def inspect(
|
|||
Args:
|
||||
server_spec: Python file to inspect, optionally with :object suffix, or fastmcp.json
|
||||
"""
|
||||
# Convert None to empty lists for list parameters
|
||||
with_packages = with_packages or []
|
||||
from pathlib import Path
|
||||
|
||||
from fastmcp.utilities.fastmcp_config import FastMCPConfig
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ def install_claude_code(
|
|||
server_object: str | None,
|
||||
name: str,
|
||||
*,
|
||||
with_editable: Path | None = None,
|
||||
with_editable: list[Path] | None = None,
|
||||
with_packages: list[str] | None = None,
|
||||
env_vars: dict[str, str] | None = None,
|
||||
python_version: str | None = None,
|
||||
|
|
@ -88,7 +88,7 @@ def install_claude_code(
|
|||
file: Path to the server file
|
||||
server_object: Optional server object name (for :object suffix)
|
||||
name: Name for the server in Claude Code
|
||||
with_editable: Optional directory to install in editable mode
|
||||
with_editable: Optional list of directories to install in editable mode
|
||||
with_packages: Optional list of additional packages to install
|
||||
env_vars: Optional dictionary of environment variables
|
||||
python_version: Optional Python version to use
|
||||
|
|
@ -121,7 +121,7 @@ def install_claude_code(
|
|||
dependencies=deduplicated_packages,
|
||||
requirements=str(with_requirements) if with_requirements else None,
|
||||
project=str(project) if project else None,
|
||||
editable=[str(with_editable)] if with_editable else None,
|
||||
editable=[str(p) for p in with_editable] if with_editable else None,
|
||||
)
|
||||
args = env_config.build_uv_args()
|
||||
|
||||
|
|
@ -171,28 +171,29 @@ async def claude_code_command(
|
|||
),
|
||||
] = None,
|
||||
with_editable: Annotated[
|
||||
Path | None,
|
||||
list[Path] | None,
|
||||
cyclopts.Parameter(
|
||||
name=["--with-editable", "-e"],
|
||||
help="Directory with pyproject.toml to install in editable mode",
|
||||
"--with-editable",
|
||||
help="Directory with pyproject.toml to install in editable mode (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = None,
|
||||
with_packages: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--with",
|
||||
help="Additional packages to install",
|
||||
help="Additional packages to install (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
env_vars: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--env",
|
||||
help="Environment variables in KEY=VALUE format",
|
||||
help="Environment variables in KEY=VALUE format (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
env_file: Annotated[
|
||||
Path | None,
|
||||
cyclopts.Parameter(
|
||||
|
|
@ -227,6 +228,10 @@ async def claude_code_command(
|
|||
Args:
|
||||
server_spec: Python file to install, optionally with :object suffix
|
||||
"""
|
||||
# Convert None to empty lists for list parameters
|
||||
with_editable = with_editable or []
|
||||
with_packages = with_packages or []
|
||||
env_vars = env_vars or []
|
||||
file, server_object, name, packages, env_dict = await process_common_args(
|
||||
server_spec, server_name, with_packages, env_vars, env_file
|
||||
)
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ def install_claude_desktop(
|
|||
server_object: str | None,
|
||||
name: str,
|
||||
*,
|
||||
with_editable: Path | None = None,
|
||||
with_editable: list[Path] | None = None,
|
||||
with_packages: list[str] | None = None,
|
||||
env_vars: dict[str, str] | None = None,
|
||||
python_version: str | None = None,
|
||||
|
|
@ -53,7 +53,7 @@ def install_claude_desktop(
|
|||
file: Path to the server file
|
||||
server_object: Optional server object name (for :object suffix)
|
||||
name: Name for the server in Claude's config
|
||||
with_editable: Optional directory to install in editable mode
|
||||
with_editable: Optional list of directories to install in editable mode
|
||||
with_packages: Optional list of additional packages to install
|
||||
env_vars: Optional dictionary of environment variables
|
||||
python_version: Optional Python version to use
|
||||
|
|
@ -86,7 +86,7 @@ def install_claude_desktop(
|
|||
dependencies=deduplicated_packages,
|
||||
requirements=str(with_requirements) if with_requirements else None,
|
||||
project=str(project) if project else None,
|
||||
editable=[str(with_editable)] if with_editable else None,
|
||||
editable=[str(p) for p in with_editable] if with_editable else None,
|
||||
)
|
||||
args = env_config.build_uv_args()
|
||||
|
||||
|
|
@ -143,28 +143,29 @@ async def claude_desktop_command(
|
|||
),
|
||||
] = None,
|
||||
with_editable: Annotated[
|
||||
Path | None,
|
||||
list[Path] | None,
|
||||
cyclopts.Parameter(
|
||||
name=["--with-editable", "-e"],
|
||||
help="Directory with pyproject.toml to install in editable mode",
|
||||
"--with-editable",
|
||||
help="Directory with pyproject.toml to install in editable mode (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = None,
|
||||
with_packages: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--with",
|
||||
help="Additional packages to install",
|
||||
help="Additional packages to install (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
env_vars: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--env",
|
||||
help="Environment variables in KEY=VALUE format",
|
||||
help="Environment variables in KEY=VALUE format (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
env_file: Annotated[
|
||||
Path | None,
|
||||
cyclopts.Parameter(
|
||||
|
|
@ -199,6 +200,10 @@ async def claude_desktop_command(
|
|||
Args:
|
||||
server_spec: Python file to install, optionally with :object suffix
|
||||
"""
|
||||
# Convert None to empty lists for list parameters
|
||||
with_editable = with_editable or []
|
||||
with_packages = with_packages or []
|
||||
env_vars = env_vars or []
|
||||
file, server_object, name, with_packages, env_dict = await process_common_args(
|
||||
server_spec, server_name, with_packages, env_vars, env_file
|
||||
)
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ def install_cursor_workspace(
|
|||
name: str,
|
||||
workspace_path: Path,
|
||||
*,
|
||||
with_editable: Path | None = None,
|
||||
with_editable: list[Path] | None = None,
|
||||
with_packages: list[str] | None = None,
|
||||
env_vars: dict[str, str] | None = None,
|
||||
python_version: str | None = None,
|
||||
|
|
@ -85,7 +85,7 @@ def install_cursor_workspace(
|
|||
server_object: Optional server object name (for :object suffix)
|
||||
name: Name for the server in Cursor
|
||||
workspace_path: Path to the workspace directory
|
||||
with_editable: Optional directory to install in editable mode
|
||||
with_editable: Optional list of directories to install in editable mode
|
||||
with_packages: Optional list of additional packages to install
|
||||
env_vars: Optional dictionary of environment variables
|
||||
python_version: Optional Python version to use
|
||||
|
|
@ -120,7 +120,7 @@ def install_cursor_workspace(
|
|||
dependencies=deduplicated_packages,
|
||||
requirements=str(with_requirements.resolve()) if with_requirements else None,
|
||||
project=str(project.resolve()) if project else None,
|
||||
editable=[str(with_editable.resolve())] if with_editable else None,
|
||||
editable=[str(p.resolve()) for p in with_editable] if with_editable else None,
|
||||
)
|
||||
args = env_config.build_uv_args()
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ def install_cursor(
|
|||
server_object: str | None,
|
||||
name: str,
|
||||
*,
|
||||
with_editable: Path | None = None,
|
||||
with_editable: list[Path] | None = None,
|
||||
with_packages: list[str] | None = None,
|
||||
env_vars: dict[str, str] | None = None,
|
||||
python_version: str | None = None,
|
||||
|
|
@ -175,7 +175,7 @@ def install_cursor(
|
|||
file: Path to the server file
|
||||
server_object: Optional server object name (for :object suffix)
|
||||
name: Name for the server in Cursor
|
||||
with_editable: Optional directory to install in editable mode
|
||||
with_editable: Optional list of directories to install in editable mode
|
||||
with_packages: Optional list of additional packages to install
|
||||
env_vars: Optional dictionary of environment variables
|
||||
python_version: Optional Python version to use
|
||||
|
|
@ -200,7 +200,7 @@ def install_cursor(
|
|||
dependencies=deduplicated_packages,
|
||||
requirements=str(with_requirements.resolve()) if with_requirements else None,
|
||||
project=str(project.resolve()) if project else None,
|
||||
editable=[str(with_editable.resolve())] if with_editable else None,
|
||||
editable=[str(p.resolve()) for p in with_editable] if with_editable else None,
|
||||
)
|
||||
args = env_config.build_uv_args()
|
||||
|
||||
|
|
@ -262,28 +262,29 @@ async def cursor_command(
|
|||
),
|
||||
] = None,
|
||||
with_editable: Annotated[
|
||||
Path | None,
|
||||
list[Path] | None,
|
||||
cyclopts.Parameter(
|
||||
name=["--with-editable", "-e"],
|
||||
help="Directory with pyproject.toml to install in editable mode",
|
||||
"--with-editable",
|
||||
help="Directory with pyproject.toml to install in editable mode (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = None,
|
||||
with_packages: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--with",
|
||||
help="Additional packages to install",
|
||||
help="Additional packages to install (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
env_vars: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--env",
|
||||
help="Environment variables in KEY=VALUE format",
|
||||
help="Environment variables in KEY=VALUE format (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
env_file: Annotated[
|
||||
Path | None,
|
||||
cyclopts.Parameter(
|
||||
|
|
@ -325,6 +326,10 @@ async def cursor_command(
|
|||
Args:
|
||||
server_spec: Python file to install, optionally with :object suffix
|
||||
"""
|
||||
# Convert None to empty lists for list parameters
|
||||
with_editable = with_editable or []
|
||||
with_packages = with_packages or []
|
||||
env_vars = env_vars or []
|
||||
file, server_object, name, with_packages, env_dict = await process_common_args(
|
||||
server_spec, server_name, with_packages, env_vars, env_file
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ def install_mcp_json(
|
|||
server_object: str | None,
|
||||
name: str,
|
||||
*,
|
||||
with_editable: Path | None = None,
|
||||
with_editable: list[Path] | None = None,
|
||||
with_packages: list[str] | None = None,
|
||||
env_vars: dict[str, str] | None = None,
|
||||
copy: bool = False,
|
||||
|
|
@ -36,7 +36,7 @@ def install_mcp_json(
|
|||
file: Path to the server file
|
||||
server_object: Optional server object name (for :object suffix)
|
||||
name: Name for the server in MCP config
|
||||
with_editable: Optional directory to install in editable mode
|
||||
with_editable: Optional list of directories to install in editable mode
|
||||
with_packages: Optional list of additional packages to install
|
||||
env_vars: Optional dictionary of environment variables
|
||||
copy: If True, copy to clipboard instead of printing to stdout
|
||||
|
|
@ -61,7 +61,7 @@ def install_mcp_json(
|
|||
dependencies=deduplicated_packages,
|
||||
requirements=str(with_requirements) if with_requirements else None,
|
||||
project=str(project) if project else None,
|
||||
editable=[str(with_editable)] if with_editable else None,
|
||||
editable=[str(p) for p in with_editable] if with_editable else None,
|
||||
)
|
||||
args = env_config.build_uv_args()
|
||||
|
||||
|
|
@ -116,28 +116,29 @@ async def mcp_json_command(
|
|||
),
|
||||
] = None,
|
||||
with_editable: Annotated[
|
||||
Path | None,
|
||||
list[Path] | None,
|
||||
cyclopts.Parameter(
|
||||
name=["--with-editable", "-e"],
|
||||
help="Directory with pyproject.toml to install in editable mode",
|
||||
"--with-editable",
|
||||
help="Directory with pyproject.toml to install in editable mode (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = None,
|
||||
with_packages: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--with",
|
||||
help="Additional packages to install",
|
||||
help="Additional packages to install (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
env_vars: Annotated[
|
||||
list[str],
|
||||
list[str] | None,
|
||||
cyclopts.Parameter(
|
||||
"--env",
|
||||
help="Environment variables in KEY=VALUE format",
|
||||
help="Environment variables in KEY=VALUE format (can be used multiple times)",
|
||||
negative="",
|
||||
),
|
||||
] = [],
|
||||
] = None,
|
||||
env_file: Annotated[
|
||||
Path | None,
|
||||
cyclopts.Parameter(
|
||||
|
|
@ -180,6 +181,10 @@ async def mcp_json_command(
|
|||
Args:
|
||||
server_spec: Python file to install, optionally with :object suffix
|
||||
"""
|
||||
# Convert None to empty lists for list parameters
|
||||
with_editable = with_editable or []
|
||||
with_packages = with_packages or []
|
||||
env_vars = env_vars or []
|
||||
file, server_object, name, packages, env_dict = await process_common_args(
|
||||
server_spec, server_name, with_packages, env_vars, env_file
|
||||
)
|
||||
|
|
|
|||
|
|
@ -29,14 +29,17 @@ def parse_env_var(env_var: str) -> tuple[str, str]:
|
|||
async def process_common_args(
|
||||
server_spec: str,
|
||||
server_name: str | None,
|
||||
with_packages: list[str],
|
||||
env_vars: list[str],
|
||||
with_packages: list[str] | None,
|
||||
env_vars: list[str] | None,
|
||||
env_file: Path | None,
|
||||
) -> tuple[Path, str | None, str, list[str], dict[str, str] | None]:
|
||||
"""Process common arguments shared by all install commands.
|
||||
|
||||
Handles both fastmcp.json config files and traditional file.py:object syntax.
|
||||
"""
|
||||
# Convert None to empty lists for list parameters
|
||||
with_packages = with_packages or []
|
||||
env_vars = env_vars or []
|
||||
# Create FastMCPConfig from server_spec
|
||||
config = None
|
||||
if server_spec.endswith(".json"):
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ class TestInstallCursor:
|
|||
file=Path("/path/to/server.py"),
|
||||
server_object="custom_app",
|
||||
name="test-server",
|
||||
with_editable=editable_path,
|
||||
with_editable=[editable_path],
|
||||
)
|
||||
|
||||
assert result is True
|
||||
|
|
@ -328,7 +328,7 @@ class TestCursorCommand:
|
|||
file=Path("server.py"),
|
||||
server_object=None,
|
||||
name="test-server",
|
||||
with_editable=None,
|
||||
with_editable=[],
|
||||
with_packages=[],
|
||||
env_vars={},
|
||||
python_version=None,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue