Internal refactor: fastmcp config to mcp server config (#1672)

This commit is contained in:
Jeremiah Lowin 2025-08-29 21:37:39 -04:00 committed by GitHub
commit 6d46192659
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 354 additions and 300 deletions

View file

@ -1,4 +1,4 @@
name: Update FastMCPConfig Schema
name: Update MCPServerConfig Schema
# This workflow runs on merges to main to automatically update the config schema
# by creating a PR when changes are needed.
@ -7,8 +7,8 @@ on:
push:
branches: ["main"]
paths:
- "src/fastmcp/utilities/fastmcp_config/**"
- "!src/fastmcp/utilities/fastmcp_config/v1/schema.json" # Exclude the local schema file
- "src/fastmcp/utilities/mcp_server_config/**"
- "!src/fastmcp/utilities/mcp_server_config/v1/schema.json" # Exclude the local schema file
workflow_dispatch:
permissions:
@ -45,23 +45,23 @@ jobs:
# Generate schema in docs/public for web access
uv run python -c "
from fastmcp.utilities.fastmcp_config import generate_schema
from fastmcp.utilities.mcp_server_config import generate_schema
generate_schema('docs/public/schemas/fastmcp.json/latest.json')
print('✅ Latest schema generated in docs/public')
"
# Also update the v1 schema in docs/public
uv run python -c "
from fastmcp.utilities.fastmcp_config import generate_schema
from fastmcp.utilities.mcp_server_config import generate_schema
generate_schema('docs/public/schemas/fastmcp.json/v1.json')
print('✅ v1 schema generated in docs/public')
"
# Generate schema in the source directory for local development
uv run python -c "
from fastmcp.utilities.fastmcp_config import generate_schema
generate_schema('src/fastmcp/utilities/fastmcp_config/v1/schema.json')
print('✅ Schema generated in utilities/fastmcp_config/v1/')
from fastmcp.utilities.mcp_server_config import generate_schema
generate_schema('src/fastmcp/utilities/mcp_server_config/v1/schema.json')
print('✅ Schema generated in utilities/mcp_server_config/v1/')
"
- name: Create Pull Request
@ -73,7 +73,7 @@ jobs:
body: |
This PR updates the fastmcp.json schema files to match the current source code.
The schema is automatically generated from `src/fastmcp/utilities/fastmcp_config/` to ensure consistency.
The schema is automatically generated from `src/fastmcp/utilities/mcp_server_config/` to ensure consistency.
**Note:** This PR is fully automated and will update itself with any subsequent changes to the schema, or close automatically if the schema becomes up-to-date through other means. Feel free to leave it open until you're ready to merge.

View file

@ -380,33 +380,33 @@
"python-sdk/fastmcp-utilities-cli",
"python-sdk/fastmcp-utilities-components",
"python-sdk/fastmcp-utilities-exceptions",
{
"group": "fastmcp_config",
"pages": [
"python-sdk/fastmcp-utilities-fastmcp_config-__init__",
{
"group": "v1",
"pages": [
"python-sdk/fastmcp-utilities-fastmcp_config-v1-__init__",
"python-sdk/fastmcp-utilities-fastmcp_config-v1-fastmcp_config",
{
"group": "sources",
"pages": [
"python-sdk/fastmcp-utilities-fastmcp_config-v1-sources-__init__",
"python-sdk/fastmcp-utilities-fastmcp_config-v1-sources-base",
"python-sdk/fastmcp-utilities-fastmcp_config-v1-sources-filesystem"
]
}
]
}
]
},
"python-sdk/fastmcp-utilities-http",
"python-sdk/fastmcp-utilities-inspect",
"python-sdk/fastmcp-utilities-json_schema",
"python-sdk/fastmcp-utilities-json_schema_type",
"python-sdk/fastmcp-utilities-logging",
"python-sdk/fastmcp-utilities-mcp_config",
{
"group": "mcp_server_config",
"pages": [
"python-sdk/fastmcp-utilities-mcp_server_config-__init__",
{
"group": "v1",
"pages": [
"python-sdk/fastmcp-utilities-mcp_server_config-v1-__init__",
"python-sdk/fastmcp-utilities-mcp_server_config-v1-mcp_server_config",
{
"group": "sources",
"pages": [
"python-sdk/fastmcp-utilities-mcp_server_config-v1-sources-__init__",
"python-sdk/fastmcp-utilities-mcp_server_config-v1-sources-base",
"python-sdk/fastmcp-utilities-mcp_server_config-v1-sources-filesystem"
]
}
]
}
]
},
"python-sdk/fastmcp-utilities-openapi",
"python-sdk/fastmcp-utilities-tests",
"python-sdk/fastmcp-utilities-types"

View file

@ -10,7 +10,7 @@ FastMCP CLI tools using Cyclopts.
## Functions
### `with_argv` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L70" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `with_argv` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L67" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
with_argv(args: list[str] | None)
@ -27,7 +27,7 @@ Args are provided without the script name, so we preserve sys.argv[0]
and replace the rest.
### `version` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L93" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `version` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L90" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
version()
@ -37,7 +37,7 @@ version()
Display version information and platform details.
### `dev` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L131" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `dev` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L128" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
dev(server_spec: str | None = None) -> None
@ -50,7 +50,7 @@ Run an MCP server with the MCP Inspector for development.
- `server_spec`: Python file to run, optionally with \:object suffix, or None to auto-detect fastmcp.json
### `run` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L349" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L309" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run(server_spec: str | None = None, *server_args: str) -> None
@ -74,7 +74,7 @@ fastmcp run server.py -- --config config.json --debug
- `server_spec`: Python file, object specification (file\:obj), config file, URL, or None to auto-detect
### `inspect` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L622" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `inspect` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L521" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
inspect(server_spec: str | None = None) -> None
@ -105,7 +105,7 @@ fastmcp inspect # auto-detect fastmcp.json
- `server_spec`: Python file to inspect, optionally with \:object suffix, or fastmcp.json
### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L904" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/cli.py#L754" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prepare(config_path: Annotated[str | None, cyclopts.Parameter(help='Path to fastmcp.json configuration file')] = None, output_dir: Annotated[str | None, cyclopts.Parameter(help='Directory to create the persistent environment in')] = None, skip_source: Annotated[bool, cyclopts.Parameter(help='Skip source preparation (e.g., git clone)')] = False) -> None

View file

@ -57,7 +57,7 @@ Install FastMCP server in Claude Code.
- True if installation was successful, False otherwise
### `claude_code_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/claude_code.py#L163" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `claude_code_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/claude_code.py#L162" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
claude_code_command(server_spec: str) -> None

View file

@ -44,7 +44,7 @@ Install FastMCP server in Claude Desktop.
- True if installation was successful, False otherwise
### `claude_desktop_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/claude_desktop.py#L135" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `claude_desktop_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/claude_desktop.py#L133" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
claude_desktop_command(server_spec: str) -> None

View file

@ -68,7 +68,7 @@ Install FastMCP server to workspace-specific Cursor configuration.
- True if installation was successful, False otherwise
### `install_cursor` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/cursor.py#L159" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `install_cursor` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/cursor.py#L157" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
install_cursor(file: Path, server_object: str | None, name: str) -> bool
@ -93,7 +93,7 @@ Install FastMCP server in Cursor.
- True if installation was successful, False otherwise
### `cursor_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/cursor.py#L254" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `cursor_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/cursor.py#L250" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
cursor_command(server_spec: str) -> None

View file

@ -35,7 +35,7 @@ Generate MCP configuration JSON for manual installation.
- True if generation was successful, False otherwise
### `mcp_json_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/mcp_json.py#L108" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `mcp_json_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/install/mcp_json.py#L106" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
mcp_json_command(server_spec: str) -> None

View file

@ -10,7 +10,7 @@ FastMCP run command implementation with enhanced type hints.
## Functions
### `is_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L29" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `is_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L28" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
is_url(path: str) -> bool
@ -20,7 +20,7 @@ is_url(path: str) -> bool
Check if a string is a URL.
### `run_with_uv` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L35" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run_with_uv` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L34" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_with_uv(server_spec: str, python_version: str | None = None, with_packages: list[str] | None = None, with_requirements: Path | None = None, project: Path | None = None, transport: TransportType | None = None, host: str | None = None, port: int | None = None, path: str | None = None, log_level: LogLevelType | None = None, show_banner: bool = True, editable: str | list[str] | None = None) -> None
@ -29,6 +29,10 @@ run_with_uv(server_spec: str, python_version: str | None = None, with_packages:
Run a MCP server using uv run subprocess.
This function is called when we need to set up a Python environment with specific
dependencies before running the server. The config parsing and merging should already
be done by the caller.
**Args:**
- `server_spec`: Python file, object specification (file\:obj), config file, or URL
- `python_version`: Python version to use (e.g. "3.10")
@ -41,9 +45,10 @@ Run a MCP server using uv run subprocess.
- `path`: Path to bind to when using http transport
- `log_level`: Log level
- `show_banner`: Whether to show the server banner
- `editable`: Editable package paths
### `create_client_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L170" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `create_client_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L115" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_client_server(url: str) -> Any
@ -59,7 +64,7 @@ Create a FastMCP server from a client URL.
- A FastMCP server instance
### `create_mcp_config_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L190" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `create_mcp_config_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L135" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None]
@ -69,10 +74,10 @@ create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None]
Create a FastMCP server from a MCPConfig.
### `load_fastmcp_config` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L201" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `load_mcp_server_config` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L146" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_fastmcp_config(config_path: Path) -> FastMCPConfig
load_mcp_server_config(config_path: Path) -> MCPServerConfig
```
@ -82,10 +87,10 @@ Load a FastMCP configuration from a fastmcp.json file.
- `config_path`: Path to fastmcp.json file
**Returns:**
- FastMCPConfig object
- MCPServerConfig object
### `run_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L219" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L163" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_command(server_spec: str, transport: TransportType | None = None, host: str | None = None, port: int | None = None, path: str | None = None, log_level: LogLevelType | None = None, server_args: list[str] | None = None, show_banner: bool = True, use_direct_import: bool = False, skip_source: bool = False) -> None
@ -107,7 +112,7 @@ Run a MCP server or connect to a remote one.
- `skip_source`: Whether to skip source preparation step
### `run_v1_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L341" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `run_v1_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/cli/run.py#L284" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_v1_server(server: FastMCP1x, host: str | None = None, port: int | None = None, transport: TransportType | None = None) -> None

View file

@ -7,13 +7,13 @@ sidebarTitle: oauth
## Functions
### `default_cache_dir` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L36" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `default_cache_dir` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L48" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_cache_dir() -> Path
```
### `check_if_auth_required` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L154" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `check_if_auth_required` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L192" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
check_if_auth_required(mcp_url: str, httpx_kwargs: dict[str, Any] | None = None) -> bool
@ -28,7 +28,13 @@ Check if the MCP endpoint requires authentication by making a test request.
## Classes
### `FileTokenStorage` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L40" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `StoredToken` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L37" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Token storage format with absolute expiry time.
### `FileTokenStorage` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L52" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
File-based token storage implementation for OAuth credentials and tokens.
@ -39,7 +45,7 @@ Each instance is tied to a specific server URL for proper token isolation.
**Methods:**
#### `get_base_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L55" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_base_url` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L67" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_base_url(url: str) -> str
@ -48,7 +54,7 @@ get_base_url(url: str) -> str
Extract the base URL (scheme + host) from a URL.
#### `get_cache_key` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L60" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_cache_key` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L72" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_cache_key(self) -> str
@ -57,7 +63,7 @@ get_cache_key(self) -> str
Generate a safe filesystem key from the server's base URL.
#### `get_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L75" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L87" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_tokens(self) -> OAuthToken | None
@ -66,7 +72,7 @@ get_tokens(self) -> OAuthToken | None
Load tokens from file storage.
#### `set_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L92" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_tokens` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L119" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_tokens(self, tokens: OAuthToken) -> None
@ -75,7 +81,7 @@ set_tokens(self, tokens: OAuthToken) -> None
Save tokens to file storage.
#### `get_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L98" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L136" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_client_info(self) -> OAuthClientInformationFull | None
@ -84,7 +90,7 @@ get_client_info(self) -> OAuthClientInformationFull | None
Load client information from file storage.
#### `set_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L126" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_client_info` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L164" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_client_info(self, client_info: OAuthClientInformationFull) -> None
@ -93,7 +99,7 @@ set_client_info(self, client_info: OAuthClientInformationFull) -> None
Save client information to file storage.
#### `clear` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L132" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `clear` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L170" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
clear(self) -> None
@ -102,7 +108,7 @@ clear(self) -> None
Clear all cached data for this server.
#### `clear_all` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L141" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `clear_all` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L179" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
clear_all(cls, cache_dir: Path | None = None) -> None
@ -111,7 +117,7 @@ clear_all(cls, cache_dir: Path | None = None) -> None
Clear all cached data for all servers.
### `OAuth` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L184" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `OAuth` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L222" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
OAuth client provider for MCP servers with browser-based authentication.
@ -122,7 +128,7 @@ a browser for user authorization and running a local callback server.
**Methods:**
#### `redirect_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L255" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `redirect_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L302" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
redirect_handler(self, authorization_url: str) -> None
@ -131,7 +137,7 @@ redirect_handler(self, authorization_url: str) -> None
Open browser for authorization.
#### `callback_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L260" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `callback_handler` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/auth/oauth.py#L307" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
callback_handler(self) -> tuple[str, str | None]

View file

@ -7,7 +7,7 @@ sidebarTitle: client
## Classes
### `ClientSessionState` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L80" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `ClientSessionState` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L81" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Holds all session-related state for a Client instance.
@ -16,7 +16,7 @@ This allows clean separation of configuration (which is copied) from
session state (which should be fresh for each new client instance).
### `Client` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L96" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `Client` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L97" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
MCP client that delegates connection management to a Transport instance.
@ -79,7 +79,7 @@ async with client:
**Methods:**
#### `session` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L282" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `session` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L283" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
session(self) -> ClientSession
@ -88,7 +88,7 @@ session(self) -> ClientSession
Get the current active session. Raises RuntimeError if not connected.
#### `initialize_result` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L292" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `initialize_result` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L293" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
initialize_result(self) -> mcp.types.InitializeResult
@ -97,7 +97,7 @@ initialize_result(self) -> mcp.types.InitializeResult
Get the result of the initialization request.
#### `set_roots` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L300" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_roots` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L301" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_roots(self, roots: RootsList | RootsHandler) -> None
@ -106,7 +106,7 @@ set_roots(self, roots: RootsList | RootsHandler) -> None
Set the roots for the client. This does not automatically call `send_roots_list_changed`.
#### `set_sampling_callback` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L304" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_sampling_callback` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L305" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_sampling_callback(self, sampling_callback: ClientSamplingHandler) -> None
@ -115,7 +115,7 @@ set_sampling_callback(self, sampling_callback: ClientSamplingHandler) -> None
Set the sampling callback for the client.
#### `set_elicitation_callback` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L310" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_elicitation_callback` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L311" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_elicitation_callback(self, elicitation_callback: ElicitationHandler) -> None
@ -124,7 +124,7 @@ set_elicitation_callback(self, elicitation_callback: ElicitationHandler) -> None
Set the elicitation callback for the client.
#### `is_connected` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L318" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `is_connected` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L319" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
is_connected(self) -> bool
@ -133,7 +133,7 @@ is_connected(self) -> bool
Check if the client is currently connected.
#### `new` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L322" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `new` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L323" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
new(self) -> Client[ClientTransportT]
@ -149,13 +149,13 @@ share state with the original client.
- A new Client instance with the same configuration but disconnected state.
#### `close` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L487" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `close` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L490" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
close(self)
```
#### `ping` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L493" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `ping` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L496" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
ping(self) -> bool
@ -164,7 +164,7 @@ ping(self) -> bool
Send a ping request.
#### `cancel` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L498" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `cancel` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L501" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
cancel(self, request_id: str | int, reason: str | None = None) -> None
@ -173,7 +173,7 @@ cancel(self, request_id: str | int, reason: str | None = None) -> None
Send a cancellation notification for an in-progress request.
#### `progress` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L515" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `progress` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L518" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
progress(self, progress_token: str | int, progress: float, total: float | None = None, message: str | None = None) -> None
@ -182,7 +182,7 @@ progress(self, progress_token: str | int, progress: float, total: float | None =
Send a progress notification.
#### `set_logging_level` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L527" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `set_logging_level` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L530" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
set_logging_level(self, level: mcp.types.LoggingLevel) -> None
@ -191,7 +191,7 @@ set_logging_level(self, level: mcp.types.LoggingLevel) -> None
Send a logging/setLevel request.
#### `send_roots_list_changed` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L531" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `send_roots_list_changed` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L534" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
send_roots_list_changed(self) -> None
@ -200,7 +200,7 @@ send_roots_list_changed(self) -> None
Send a roots/list_changed notification.
#### `list_resources_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L537" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resources_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L540" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resources_mcp(self) -> mcp.types.ListResourcesResult
@ -216,7 +216,7 @@ containing the list of resources and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `list_resources` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L552" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resources` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L555" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resources(self) -> list[mcp.types.Resource]
@ -231,7 +231,7 @@ Retrieve a list of resources available on the server.
- `RuntimeError`: If called while the client is not connected.
#### `list_resource_templates_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L564" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resource_templates_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L567" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resource_templates_mcp(self) -> mcp.types.ListResourceTemplatesResult
@ -247,7 +247,7 @@ containing the list of resource templates and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `list_resource_templates` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L581" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_resource_templates` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L584" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_resource_templates(self) -> list[mcp.types.ResourceTemplate]
@ -262,7 +262,7 @@ Retrieve a list of resource templates available on the server.
- `RuntimeError`: If called while the client is not connected.
#### `read_resource_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L595" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L598" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource_mcp(self, uri: AnyUrl | str) -> mcp.types.ReadResourceResult
@ -281,7 +281,7 @@ containing the resource contents and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `read_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L617" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `read_resource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L620" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
read_resource(self, uri: AnyUrl | str) -> list[mcp.types.TextResourceContents | mcp.types.BlobResourceContents]
@ -300,7 +300,7 @@ objects, typically containing either text or binary data.
- `RuntimeError`: If called while the client is not connected.
#### `list_prompts_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L656" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_prompts_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L659" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_prompts_mcp(self) -> mcp.types.ListPromptsResult
@ -316,7 +316,7 @@ containing the list of prompts and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `list_prompts` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L671" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_prompts` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L674" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_prompts(self) -> list[mcp.types.Prompt]
@ -331,7 +331,7 @@ Retrieve a list of prompts available on the server.
- `RuntimeError`: If called while the client is not connected.
#### `get_prompt_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L684" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_prompt_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L687" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_prompt_mcp(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.GetPromptResult
@ -351,7 +351,7 @@ containing the prompt messages and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `get_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L720" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_prompt` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L723" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> mcp.types.GetPromptResult
@ -371,7 +371,7 @@ containing the prompt messages and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `complete_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L741" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `complete_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L744" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
complete_mcp(self, ref: mcp.types.ResourceReference | mcp.types.PromptReference, argument: dict[str, str]) -> mcp.types.CompleteResult
@ -391,7 +391,7 @@ containing the completion and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `complete` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L764" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `complete` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L767" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
complete(self, ref: mcp.types.ResourceReference | mcp.types.PromptReference, argument: dict[str, str]) -> mcp.types.Completion
@ -410,7 +410,7 @@ Send a completion request to the server.
- `RuntimeError`: If called while the client is not connected.
#### `list_tools_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L786" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_tools_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L789" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_tools_mcp(self) -> mcp.types.ListToolsResult
@ -426,7 +426,7 @@ containing the list of tools and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `list_tools` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L801" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `list_tools` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L804" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
list_tools(self) -> list[mcp.types.Tool]
@ -441,7 +441,7 @@ Retrieve a list of tools available on the server.
- `RuntimeError`: If called while the client is not connected.
#### `call_tool_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L815" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `call_tool_mcp` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L818" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_tool_mcp(self, name: str, arguments: dict[str, Any], progress_handler: ProgressHandler | None = None, timeout: datetime.timedelta | float | int | None = None) -> mcp.types.CallToolResult
@ -466,7 +466,7 @@ containing the tool result and any additional metadata.
- `RuntimeError`: If called while the client is not connected.
#### `call_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L852" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `call_tool` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L855" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
call_tool(self, name: str, arguments: dict[str, Any] | None = None, timeout: datetime.timedelta | float | int | None = None, progress_handler: ProgressHandler | None = None, raise_on_error: bool = True) -> CallToolResult
@ -496,10 +496,10 @@ raw result object.
- `RuntimeError`: If called while the client is not connected.
#### `generate_name` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L923" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `generate_name` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L926" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
generate_name(cls, name: str | None = None) -> str
```
### `CallToolResult` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L932" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `CallToolResult` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/client/client.py#L935" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>

View file

@ -182,7 +182,7 @@ Handles provider-specific requirements:
**Methods:**
#### `get_client` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L354" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_client` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L355" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_client(self, client_id: str) -> OAuthClientInformationFull | None
@ -199,7 +199,7 @@ handles the case where a client with cached tokens reconnects
on a different port.
#### `register_client` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L386" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `register_client` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L388" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
register_client(self, client_info: OAuthClientInformationFull) -> None
@ -226,7 +226,7 @@ The flow:
4. When client reconnects with a different port, ProxyDCRClient accepts it
#### `authorize` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L435" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `authorize` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L447" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
authorize(self, client: OAuthClientInformationFull, params: AuthorizationParams) -> str
@ -240,7 +240,7 @@ This implements the DCR-compliant proxy pattern:
3. Redirect to IdP with our fixed callback URL
#### `load_authorization_code` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L491" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `load_authorization_code` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L503" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_authorization_code(self, client: OAuthClientInformationFull, authorization_code: str) -> AuthorizationCode | None
@ -252,7 +252,7 @@ Look up our client code and return authorization code object
with PKCE challenge for validation.
#### `exchange_authorization_code` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L533" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `exchange_authorization_code` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L545" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
exchange_authorization_code(self, client: OAuthClientInformationFull, authorization_code: AuthorizationCode) -> OAuthToken
@ -264,7 +264,7 @@ For the DCR-compliant proxy flow, we return the IdP tokens that were obtained
during the IdP callback exchange. PKCE validation is handled by the MCP framework.
#### `load_refresh_token` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L600" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `load_refresh_token` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L612" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str) -> RefreshToken | None
@ -273,7 +273,7 @@ load_refresh_token(self, client: OAuthClientInformationFull, refresh_token: str)
Load refresh token from local storage.
#### `exchange_refresh_token` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L608" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `exchange_refresh_token` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L620" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
exchange_refresh_token(self, client: OAuthClientInformationFull, refresh_token: RefreshToken, scopes: list[str]) -> OAuthToken
@ -282,7 +282,7 @@ exchange_refresh_token(self, client: OAuthClientInformationFull, refresh_token:
Exchange refresh token for new access token using authlib.
#### `load_access_token` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L683" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `load_access_token` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L695" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_access_token(self, token: str) -> AccessToken | None
@ -294,7 +294,7 @@ Delegates to the JWT verifier which handles signature validation,
expiration checking, and claims validation using the upstream JWKS.
#### `revoke_token` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L700" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `revoke_token` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L712" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
revoke_token(self, token: AccessToken | RefreshToken) -> None
@ -306,7 +306,7 @@ Removes tokens from local storage and attempts to revoke them with
the upstream server if a revocation endpoint is configured.
#### `get_routes` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L893" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_routes` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/oauth_proxy.py#L905" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_routes(self) -> list[Route]

View file

@ -65,9 +65,9 @@ Setup Requirements:
4. Note your Client ID and Client Secret
### `AuthKitProviderSettings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L253" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `AuthKitProviderSettings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L257" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `AuthKitProvider` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L271" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `AuthKitProvider` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L275" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
AuthKit metadata provider for DCR (Dynamic Client Registration).
@ -93,7 +93,7 @@ https://workos.com/docs/authkit/mcp/integrating/token-verification
**Methods:**
#### `get_routes` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L354" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `get_routes` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/auth/providers/workos.py#L358" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
get_routes(self) -> list[Route]

View file

@ -44,8 +44,9 @@ Validate a redirect URI against allowed patterns.
**Args:**
- `redirect_uri`: The redirect URI to validate
- `allowed_patterns`: List of allowed patterns. If None, defaults to localhost.
If empty list, all URIs are allowed.
- `allowed_patterns`: List of allowed patterns. If None, all URIs are allowed (for DCR compatibility).
If empty list, no URIs are allowed.
To restrict to localhost only, explicitly pass DEFAULT_LOCALHOST_PATTERNS.
**Returns:**
- True if the redirect URI is allowed

View file

@ -8,9 +8,21 @@ sidebarTitle: logging
Comprehensive logging middleware for FastMCP servers.
## Functions
### `default_serializer` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L14" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
default_serializer(data: Any) -> str
```
The default serializer for Payloads in the logging middleware.
## Classes
### `LoggingMiddleware` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L10" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `LoggingMiddleware` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L19" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Middleware that provides comprehensive request and response logging.
@ -21,16 +33,16 @@ monitoring, and understanding server usage patterns.
**Methods:**
#### `on_message` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L71" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `on_message` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L91" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
on_message(self, context: MiddlewareContext, call_next: CallNext) -> Any
on_message(self, context: MiddlewareContext[Any], call_next: CallNext[Any, Any]) -> Any
```
Log all messages.
### `StructuredLoggingMiddleware` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L92" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `StructuredLoggingMiddleware` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L114" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Middleware that provides structured JSON logging for better log analysis.
@ -41,10 +53,10 @@ aggregation tools like ELK stack, Splunk, or cloud logging services.
**Methods:**
#### `on_message` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L149" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `on_message` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/server/middleware/logging.py#L185" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
on_message(self, context: MiddlewareContext, call_next: CallNext) -> Any
on_message(self, context: MiddlewareContext[Any], call_next: CallNext[Any, Any]) -> Any
```
Log structured message information.

View file

@ -7,7 +7,37 @@ sidebarTitle: cli
## Functions
### `log_server_banner` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/cli.py#L27" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `is_already_in_uv_subprocess` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/cli.py#L28" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
is_already_in_uv_subprocess() -> bool
```
Check if we're already running in a FastMCP uv subprocess.
### `load_and_merge_config` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/cli.py#L33" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_and_merge_config(server_spec: str | None, **cli_overrides) -> tuple[MCPServerConfig, str]
```
Load config from server_spec and apply CLI overrides.
This consolidates the config parsing logic that was duplicated across
run, inspect, and dev commands.
**Args:**
- `server_spec`: Python file, config file, URL, or None to auto-detect
- `cli_overrides`: CLI arguments that override config values
**Returns:**
- Tuple of (MCPServerConfig, resolved_server_spec)
### `log_server_banner` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/cli.py#L151" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
log_server_banner(server: FastMCP[Any], transport: Literal['stdio', 'http', 'sse', 'streamable-http']) -> None

View file

@ -3,7 +3,7 @@ title: __init__
sidebarTitle: __init__
---
# `fastmcp.utilities.fastmcp_config`
# `fastmcp.utilities.mcp_server_config`
FastMCP Configuration module.

View file

@ -3,6 +3,6 @@ title: __init__
sidebarTitle: __init__
---
# `fastmcp.utilities.fastmcp_config.v1`
# `fastmcp.utilities.mcp_server_config.v1`
*This module is empty or contains only private/internal implementations.*

View file

@ -1,9 +1,9 @@
---
title: fastmcp_config
sidebarTitle: fastmcp_config
title: mcp_server_config
sidebarTitle: mcp_server_config
---
# `fastmcp.utilities.fastmcp_config.v1.fastmcp_config`
# `fastmcp.utilities.mcp_server_config.v1.mcp_server_config`
FastMCP Configuration File Support.
@ -15,7 +15,7 @@ command-line arguments.
## Functions
### `generate_schema` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L707" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `generate_schema` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L705" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
generate_schema(output_path: Path | str | None = None) -> dict[str, Any] | None
@ -38,7 +38,7 @@ validation and auto-completion.
## Classes
### `Environment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L33" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `Environment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L33" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Configuration for Python environment setup.
@ -46,22 +46,22 @@ Configuration for Python environment setup.
**Methods:**
#### `build_uv_args` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L66" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `build_uv_run_command` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L66" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
build_uv_args(self, command: str | list[str] | None = None) -> list[str]
build_uv_run_command(self, command: list[str]) -> list[str]
```
Build uv run arguments from this environment configuration.
Build complete uv run command with environment args and command to execute.
**Args:**
- `command`: Optional command to append (string or list of args)
- `command`: Command to execute (e.g., ["fastmcp", "run", "server.py"])
**Returns:**
- List of arguments for uv run command
- Complete command ready for subprocess.run, including "uv" prefix
#### `run_with_uv` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L109" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `run_with_uv` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L105" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_with_uv(self, command: list[str]) -> None
@ -73,7 +73,7 @@ Execute a command using uv run with this environment configuration.
- `command`: Command and arguments to execute (e.g., ["fastmcp", "run", "server.py"])
#### `needs_uv` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L132" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `needs_uv` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L130" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
needs_uv(self) -> bool
@ -85,7 +85,7 @@ Check if this environment config requires uv to set up.
- True if any environment settings require uv run
#### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L148" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L146" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prepare(self, output_dir: Path | None = None) -> None
@ -98,7 +98,7 @@ Prepare the Python environment using uv.
If None, creates a temporary directory for ephemeral use.
### `Deployment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L313" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `Deployment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L311" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Configuration for server deployment and runtime settings.
@ -106,7 +106,7 @@ Configuration for server deployment and runtime settings.
**Methods:**
#### `apply_runtime_settings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L362" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `apply_runtime_settings` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L360" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
apply_runtime_settings(self, config_path: Path | None = None) -> None
@ -122,7 +122,7 @@ For example: "API_URL": "https://api.${ENVIRONMENT}.example.com"
will substitute the value of the ENVIRONMENT variable at runtime.
### `FastMCPConfig` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L411" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `MCPServerConfig` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L409" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Configuration for a FastMCP server.
@ -133,7 +133,7 @@ a FastMCP server in a declarative format.
**Methods:**
#### `validate_source` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L460" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `validate_source` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L458" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
validate_source(cls, v: dict | FileSystemSource) -> FileSystemSource
@ -146,10 +146,10 @@ Supports:
- FileSystemSource instance (passed through)
No string parsing happens here - that's only at CLI boundaries.
FastMCPConfig works only with properly typed objects.
MCPServerConfig works only with properly typed objects.
#### `validate_environment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L483" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `validate_environment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L481" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
validate_environment(cls, v: dict | Environment) -> Environment
@ -162,7 +162,7 @@ Accepts:
- dict that can be converted to Environment
#### `validate_deployment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L499" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `validate_deployment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L497" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
validate_deployment(cls, v: dict | Deployment) -> Deployment
@ -175,10 +175,10 @@ Accepts:
- dict that can be converted to Deployment
#### `from_file` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L515" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_file` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L513" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_file(cls, file_path: Path) -> FastMCPConfig
from_file(cls, file_path: Path) -> MCPServerConfig
```
Load configuration from a JSON file.
@ -187,7 +187,7 @@ Load configuration from a JSON file.
- `file_path`: Path to the configuration file
**Returns:**
- FastMCPConfig instance
- MCPServerConfig instance
**Raises:**
- `FileNotFoundError`: If the file doesn't exist
@ -195,10 +195,10 @@ Load configuration from a JSON file.
- `pydantic.ValidationError`: If the configuration is invalid
#### `from_cli_args` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L538" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `from_cli_args` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L536" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
from_cli_args(cls, source: FileSystemSource, transport: Literal['stdio', 'http', 'sse', 'streamable-http'] | None = None, host: str | None = None, port: int | None = None, path: str | None = None, log_level: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] | None = None, python: str | None = None, dependencies: list[str] | None = None, requirements: str | None = None, project: str | None = None, editable: str | None = None, env: dict[str, str] | None = None, cwd: str | None = None, args: list[str] | None = None) -> FastMCPConfig
from_cli_args(cls, source: FileSystemSource, transport: Literal['stdio', 'http', 'sse', 'streamable-http'] | None = None, host: str | None = None, port: int | None = None, path: str | None = None, log_level: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] | None = None, python: str | None = None, dependencies: list[str] | None = None, requirements: str | None = None, project: str | None = None, editable: str | None = None, env: dict[str, str] | None = None, cwd: str | None = None, args: list[str] | None = None) -> MCPServerConfig
```
Create a config from CLI arguments.
@ -223,10 +223,10 @@ goes through a config object.
- `args`: Server arguments
**Returns:**
- FastMCPConfig instance
- MCPServerConfig instance
#### `find_config` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L615" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `find_config` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L613" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
find_config(cls, start_path: Path | None = None) -> Path | None
@ -241,7 +241,7 @@ Find a fastmcp.json file in the specified directory.
- Path to the configuration file, or None if not found
#### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L634" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L632" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prepare(self, skip_source: bool = False, output_dir: Path | None = None) -> None
@ -257,7 +257,7 @@ When output_dir is None, does ephemeral caching (for backwards compatibility).
- `output_dir`: Directory to create the persistent uv project in (optional)
#### `prepare_environment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L655" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prepare_environment` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L653" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prepare_environment(self, output_dir: Path | None = None) -> None
@ -272,7 +272,7 @@ Prepare the Python environment.
Delegates to the environment's prepare() method
#### `prepare_source` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L666" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prepare_source` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L664" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prepare_source(self) -> None
@ -283,7 +283,7 @@ Prepare the source for loading.
Delegates to the source's prepare() method.
#### `run_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/fastmcp_config.py#L673" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `run_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/mcp_server_config.py#L671" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
run_server(self, **kwargs: Any) -> None

View file

@ -3,6 +3,6 @@ title: __init__
sidebarTitle: __init__
---
# `fastmcp.utilities.fastmcp_config.v1.sources`
# `fastmcp.utilities.mcp_server_config.v1.sources`
*This module is empty or contains only private/internal implementations.*

View file

@ -3,11 +3,11 @@ title: base
sidebarTitle: base
---
# `fastmcp.utilities.fastmcp_config.v1.sources.base`
# `fastmcp.utilities.mcp_server_config.v1.sources.base`
## Classes
### `BaseSource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/sources/base.py#L7" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `BaseSource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/sources/base.py#L7" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Abstract base class for all source types.
@ -15,7 +15,7 @@ Abstract base class for all source types.
**Methods:**
#### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/sources/base.py#L12" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `prepare` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/sources/base.py#L12" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
prepare(self) -> None
@ -28,7 +28,7 @@ this method performs that preparation. For sources that don't
need preparation (e.g., local files), this is a no-op.
#### `load_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/sources/base.py#L23" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `load_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/sources/base.py#L23" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_server(self) -> Any

View file

@ -3,11 +3,11 @@ title: filesystem
sidebarTitle: filesystem
---
# `fastmcp.utilities.fastmcp_config.v1.sources.filesystem`
# `fastmcp.utilities.mcp_server_config.v1.sources.filesystem`
## Classes
### `FileSystemSource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/sources/filesystem.py#L15" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
### `FileSystemSource` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py#L15" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
Source for local Python files.
@ -15,7 +15,7 @@ Source for local Python files.
**Methods:**
#### `parse_path_with_object` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/sources/filesystem.py#L27" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `parse_path_with_object` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py#L27" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
parse_path_with_object(cls, v: str) -> str
@ -27,7 +27,7 @@ This validator runs before the model is created, allowing us to
handle the "file.py:object" syntax at the model boundary.
#### `load_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/fastmcp_config/v1/sources/filesystem.py#L62" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
#### `load_server` <sup><a href="https://github.com/jlowin/fastmcp/blob/main/src/fastmcp/utilities/mcp_server_config/v1/sources/filesystem.py#L62" target="_blank"><Icon icon="github" style="width: 14px; height: 14px;" /></a></sup>
```python
load_server(self) -> Any

View file

@ -26,14 +26,14 @@ With the configuration file in place, you can run the server in several ways:
```bash
# Auto-detect fastmcp.json in current directory
cd examples/fastmcp_config_demo
cd examples/mcp_server_config_demo
fastmcp run
# Or specify the config file explicitly
fastmcp run examples/fastmcp_config_demo/fastmcp.json
fastmcp run examples/mcp_server_config_demo/fastmcp.json
# Or use development mode with the Inspector UI
fastmcp dev examples/fastmcp_config_demo/fastmcp.json
fastmcp dev examples/mcp_server_config_demo/fastmcp.json
```
## Benefits

View file

@ -6,8 +6,8 @@ import sys
from pathlib import Path
from typing import Any
from fastmcp.utilities.fastmcp_config import Environment
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import Environment
logger = get_logger(__name__)

View file

@ -20,13 +20,13 @@ import fastmcp
from fastmcp.cli import run as run_module
from fastmcp.cli.install import install_app
from fastmcp.server.server import FastMCP
from fastmcp.utilities.fastmcp_config import Environment, FastMCPConfig
from fastmcp.utilities.inspect import (
InspectFormat,
format_info,
inspect_fastmcp,
)
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import Environment, MCPServerConfig
logger = get_logger("cli")
console = Console()
@ -796,7 +796,7 @@ async def prepare(
# Auto-detect fastmcp.json if not provided
if config_path is None:
found_config = FastMCPConfig.find_config()
found_config = MCPServerConfig.find_config()
if found_config:
config_path = str(found_config)
logger.info(f"Using configuration from {config_path}")
@ -816,7 +816,7 @@ async def prepare(
try:
# Load the configuration
config = FastMCPConfig.from_file(config_file)
config = MCPServerConfig.from_file(config_file)
# Prepare environment and source
await config.prepare(

View file

@ -9,8 +9,8 @@ from typing import Annotated
import cyclopts
from rich import print
from fastmcp.utilities.fastmcp_config import Environment
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import Environment
from .shared import process_common_args

View file

@ -9,8 +9,8 @@ import cyclopts
from rich import print
from fastmcp.mcp_config import StdioMCPServer, update_config_file
from fastmcp.utilities.fastmcp_config import Environment
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import Environment
from .shared import process_common_args

View file

@ -10,8 +10,8 @@ import cyclopts
from rich import print
from fastmcp.mcp_config import StdioMCPServer, update_config_file
from fastmcp.utilities.fastmcp_config import Environment
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import Environment
from .shared import process_common_args

View file

@ -9,8 +9,8 @@ import cyclopts
import pyperclip
from rich import print
from fastmcp.utilities.fastmcp_config import Environment
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import Environment
from .shared import process_common_args

View file

@ -8,9 +8,9 @@ from dotenv import dotenv_values
from pydantic import ValidationError
from rich import print
from fastmcp.utilities.fastmcp_config import FastMCPConfig
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import MCPServerConfig
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
logger = get_logger(__name__)
@ -40,7 +40,7 @@ async def process_common_args(
# Convert None to empty lists for list parameters
with_packages = with_packages or []
env_vars = env_vars or []
# Create FastMCPConfig from server_spec
# Create MCPServerConfig from server_spec
config = None
if server_spec.endswith(".json"):
config_path = Path(server_spec).resolve()
@ -58,8 +58,8 @@ async def process_common_args(
print("[red]MCPConfig files are not supported for installation[/red]")
sys.exit(1)
else:
# It's a FastMCPConfig
config = FastMCPConfig.from_file(config_path)
# It's a MCPServerConfig
config = MCPServerConfig.from_file(config_path)
# Merge packages from config if not overridden
if config.environment.dependencies:
@ -72,7 +72,7 @@ async def process_common_args(
else:
# Create config from file path
source = FileSystemSource(path=server_spec)
config = FastMCPConfig(source=source)
config = MCPServerConfig(source=source)
# Extract file and server_object from the source
# The FileSystemSource handles parsing path:object syntax

View file

@ -11,12 +11,12 @@ from typing import Any, Literal
from mcp.server.fastmcp import FastMCP as FastMCP1x
from fastmcp.server.server import FastMCP
from fastmcp.utilities.fastmcp_config import (
Environment,
FastMCPConfig,
)
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import (
Environment,
MCPServerConfig,
)
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
logger = get_logger("cli.run")
@ -143,16 +143,16 @@ def create_mcp_config_server(mcp_config_path: Path) -> FastMCP[None]:
return server
def load_fastmcp_config(config_path: Path) -> FastMCPConfig:
def load_mcp_server_config(config_path: Path) -> MCPServerConfig:
"""Load a FastMCP configuration from a fastmcp.json file.
Args:
config_path: Path to fastmcp.json file
Returns:
FastMCPConfig object
MCPServerConfig object
"""
config = FastMCPConfig.from_file(config_path)
config = MCPServerConfig.from_file(config_path)
# Apply runtime settings from deployment config
config.deployment.apply_runtime_settings(config_path)
@ -204,7 +204,7 @@ async def run_command(
server = create_mcp_config_server(config_path)
else:
# It's a FastMCP config - load it properly
config = load_fastmcp_config(config_path)
config = load_mcp_server_config(config_path)
# Merge deployment config with CLI arguments (CLI takes precedence)
transport = transport or config.deployment.transport
@ -232,9 +232,9 @@ async def run_command(
logger.debug(f'Found server "{server.name}" from config {config_path}')
else:
# Regular file case - create a FastMCPConfig with FileSystemSource
# Regular file case - create a MCPServerConfig with FileSystemSource
source = FileSystemSource(path=server_spec)
config = FastMCPConfig(source=source)
config = MCPServerConfig(source=source)
# Prepare source only (environment is handled by uv run)
await config.prepare_source() if not skip_source else None

View file

@ -36,8 +36,8 @@ from fastmcp.client.auth.oauth import OAuth
from fastmcp.mcp_config import MCPConfig, infer_transport_type_from_url
from fastmcp.server.dependencies import get_http_headers
from fastmcp.server.server import FastMCP
from fastmcp.utilities.fastmcp_config.v1.fastmcp_config import Environment
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config.v1.mcp_server_config import Environment
logger = get_logger(__name__)

View file

@ -14,9 +14,9 @@ from rich.table import Table
from rich.text import Text
import fastmcp
from fastmcp.utilities.fastmcp_config import FastMCPConfig
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config import MCPServerConfig
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.types import get_cached_typeadapter
if TYPE_CHECKING:
@ -33,7 +33,7 @@ def is_already_in_uv_subprocess() -> bool:
def load_and_merge_config(
server_spec: str | None,
**cli_overrides,
) -> tuple[FastMCPConfig, str]:
) -> tuple[MCPServerConfig, str]:
"""Load config from server_spec and apply CLI overrides.
This consolidates the config parsing logic that was duplicated across
@ -44,7 +44,7 @@ def load_and_merge_config(
cli_overrides: CLI arguments that override config values
Returns:
Tuple of (FastMCPConfig, resolved_server_spec)
Tuple of (MCPServerConfig, resolved_server_spec)
"""
config = None
config_path = None
@ -53,7 +53,7 @@ def load_and_merge_config(
if server_spec is None:
config_path = Path("fastmcp.json")
if not config_path.exists():
found_config = FastMCPConfig.find_config()
found_config = MCPServerConfig.find_config()
if found_config:
config_path = found_config
else:
@ -81,9 +81,9 @@ def load_and_merge_config(
# MCPConfig - we don't process these here, just pass through
pass
else:
# Try to parse as FastMCPConfig
# Try to parse as MCPServerConfig
try:
adapter = get_cached_typeadapter(FastMCPConfig)
adapter = get_cached_typeadapter(MCPServerConfig)
config = adapter.validate_python(data)
# Apply deployment settings
@ -91,7 +91,7 @@ def load_and_merge_config(
config.deployment.apply_runtime_settings(config_path)
except ValidationError:
# Not a valid FastMCPConfig, just pass through
# Not a valid MCPServerConfig, just pass through
pass
except (json.JSONDecodeError, FileNotFoundError):
# Not a valid JSON file, just pass through
@ -100,7 +100,7 @@ def load_and_merge_config(
# If we don't have a config object yet, create one from filesystem source
if config is None:
source = FileSystemSource(path=resolved_spec)
config = FastMCPConfig(source=source)
config = MCPServerConfig(source=source)
# Convert to dict for immutable transformation
config_dict = config.model_dump()
@ -134,7 +134,7 @@ def load_and_merge_config(
config_dict["deployment"]["args"] = server_args_override
# Create new config from modified dict
new_config = FastMCPConfig(**config_dict)
new_config = MCPServerConfig(**config_dict)
return new_config, resolved_spec

View file

@ -4,20 +4,20 @@ This module provides versioned configuration support for FastMCP servers.
The current version is v1, which is re-exported here for convenience.
"""
from fastmcp.utilities.fastmcp_config.v1.fastmcp_config import (
from fastmcp.utilities.mcp_server_config.v1.mcp_server_config import (
Deployment,
Environment,
FastMCPConfig,
MCPServerConfig,
generate_schema,
)
from fastmcp.utilities.fastmcp_config.v1.sources.base import BaseSource
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.mcp_server_config.v1.sources.base import BaseSource
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
__all__ = [
"BaseSource",
"Deployment",
"Environment",
"FastMCPConfig",
"MCPServerConfig",
"FileSystemSource",
"generate_schema",
]

View file

@ -17,8 +17,8 @@ from typing import TYPE_CHECKING, Any, Literal, overload
from pydantic import BaseModel, Field, field_validator
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
logger = get_logger("cli.config")
@ -406,7 +406,7 @@ class Deployment(BaseModel):
return re.sub(r"\$\{([^}]+)\}", replace_var, value)
class FastMCPConfig(BaseModel):
class MCPServerConfig(BaseModel):
"""Configuration for a FastMCP server.
This configuration file allows you to specify all settings needed to run
@ -463,7 +463,7 @@ class FastMCPConfig(BaseModel):
- FileSystemSource instance (passed through)
No string parsing happens here - that's only at CLI boundaries.
FastMCPConfig works only with properly typed objects.
MCPServerConfig works only with properly typed objects.
"""
if isinstance(v, FileSystemSource):
# Already a FileSystemSource instance, return as-is
@ -510,14 +510,14 @@ class FastMCPConfig(BaseModel):
raise ValueError("deployment must be a dict, Deployment instance")
@classmethod
def from_file(cls, file_path: Path) -> FastMCPConfig:
def from_file(cls, file_path: Path) -> MCPServerConfig:
"""Load configuration from a JSON file.
Args:
file_path: Path to the configuration file
Returns:
FastMCPConfig instance
MCPServerConfig instance
Raises:
FileNotFoundError: If the file doesn't exist
@ -550,7 +550,7 @@ class FastMCPConfig(BaseModel):
env: dict[str, str] | None = None,
cwd: str | None = None,
args: list[str] | None = None,
) -> FastMCPConfig:
) -> MCPServerConfig:
"""Create a config from CLI arguments.
This allows us to have a single code path where everything
@ -573,7 +573,7 @@ class FastMCPConfig(BaseModel):
args: Server arguments
Returns:
FastMCPConfig instance
MCPServerConfig instance
"""
# Build environment config if any env args provided
environment = None
@ -716,7 +716,7 @@ def generate_schema(output_path: Path | str | None = None) -> dict[str, Any] | N
Returns:
JSON schema as a dictionary if output_path is None, otherwise None
"""
schema = FastMCPConfig.model_json_schema()
schema = MCPServerConfig.model_json_schema()
# Add some metadata
schema["$id"] = FASTMCP_JSON_SCHEMA

View file

@ -6,8 +6,8 @@ from typing import Any, Literal
from pydantic import Field, field_validator
from fastmcp.utilities.fastmcp_config.v1.sources.base import BaseSource
from fastmcp.utilities.logging import get_logger
from fastmcp.utilities.mcp_server_config.v1.sources.base import BaseSource
logger = get_logger(__name__)

View file

@ -458,7 +458,7 @@ class TestWindowsSpecific:
"""Test parsing Windows paths with drive letters and colons."""
from pathlib import Path
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import (
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import (
FileSystemSource,
)

View file

@ -7,12 +7,12 @@ from pathlib import Path
import pytest
from pydantic import ValidationError
from fastmcp.utilities.fastmcp_config import (
from fastmcp.utilities.mcp_server_config import (
Deployment,
Environment,
FastMCPConfig,
MCPServerConfig,
)
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
class TestFileSystemSource:
@ -20,7 +20,7 @@ class TestFileSystemSource:
def test_dict_source_minimal(self):
"""Test that dict source is converted to FileSystemSource."""
config = FastMCPConfig(source={"path": "server.py"})
config = MCPServerConfig(source={"path": "server.py"})
# Dict is converted to FileSystemSource
assert isinstance(config.source, FileSystemSource)
assert config.source.path == "server.py"
@ -29,7 +29,7 @@ class TestFileSystemSource:
def test_dict_source_with_entrypoint(self):
"""Test dict source with entrypoint field."""
config = FastMCPConfig(source={"path": "server.py", "entrypoint": "app"})
config = MCPServerConfig(source={"path": "server.py", "entrypoint": "app"})
# Dict with entrypoint is converted to FileSystemSource
assert isinstance(config.source, FileSystemSource)
assert config.source.path == "server.py"
@ -38,7 +38,7 @@ class TestFileSystemSource:
def test_filesystem_source_entrypoint(self):
"""Test FileSystemSource entrypoint format."""
config = FastMCPConfig(
config = MCPServerConfig(
source=FileSystemSource(path="src/server.py", entrypoint="mcp")
)
assert isinstance(config.source, FileSystemSource)
@ -52,7 +52,7 @@ class TestEnvironment:
def test_environment_config_fields(self):
"""Test all Environment fields."""
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
environment={
"python": "3.12",
@ -73,28 +73,28 @@ class TestEnvironment:
def test_needs_uv(self):
"""Test needs_uv() method."""
# No environment config - doesn't need UV
config = FastMCPConfig(source={"path": "server.py"})
config = MCPServerConfig(source={"path": "server.py"})
assert not config.environment.needs_uv()
# Empty environment - doesn't need UV
config = FastMCPConfig(source={"path": "server.py"}, environment={})
config = MCPServerConfig(source={"path": "server.py"}, environment={})
assert not config.environment.needs_uv()
# With dependencies - needs UV
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"}, environment={"dependencies": ["requests"]}
)
assert config.environment.needs_uv()
# With Python version - needs UV
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"}, environment={"python": "3.12"}
)
assert config.environment.needs_uv()
def test_build_uv_run_command(self):
"""Test build_uv_run_command() method."""
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
environment={
"python": "3.12",
@ -125,7 +125,7 @@ class TestEnvironment:
def test_run_with_uv(self):
"""Test run_with_uv() subprocess execution."""
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"}, environment={"dependencies": ["requests"]}
)
@ -144,7 +144,7 @@ class TestDeployment:
def test_deployment_config_fields(self):
"""Test all Deployment fields."""
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
deployment={
"transport": "http",
@ -176,7 +176,7 @@ class TestDeployment:
work_dir = tmp_path / "work"
work_dir.mkdir()
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
deployment={
"env": {"TEST_VAR": "test_value"},
@ -212,7 +212,7 @@ class TestDeployment:
os.environ["BASE_URL"] = "example.com"
os.environ["ENV_NAME"] = "production"
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
deployment={
"env": {
@ -253,12 +253,12 @@ class TestDeployment:
os.environ[key] = value
class TestFastMCPConfig:
"""Test FastMCPConfig root configuration."""
class TestMCPServerConfig:
"""Test MCPServerConfig root configuration."""
def test_minimal_config(self):
"""Test creating a config with only required fields."""
config = FastMCPConfig(source={"path": "server.py"})
config = MCPServerConfig(source={"path": "server.py"})
assert isinstance(config.source, FileSystemSource)
assert config.source.path == "server.py"
assert config.source.entrypoint is None
@ -274,7 +274,7 @@ class TestFastMCPConfig:
def test_nested_structure(self):
"""Test the nested configuration structure."""
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
environment={
"python": "3.12",
@ -304,7 +304,7 @@ class TestFastMCPConfig:
config_file = tmp_path / "fastmcp.json"
config_file.write_text(json.dumps(config_data))
config = FastMCPConfig.from_file(config_file)
config = MCPServerConfig.from_file(config_file)
# When loaded from JSON with entrypoint format, it becomes EntrypointConfig
assert isinstance(config.source, FileSystemSource)
@ -325,7 +325,7 @@ class TestFastMCPConfig:
config_file = tmp_path / "fastmcp.json"
config_file.write_text(json.dumps(config_data))
config = FastMCPConfig.from_file(config_file)
config = MCPServerConfig.from_file(config_file)
# String entrypoint with : should be converted to EntrypointConfig
assert isinstance(config.source, FileSystemSource)
assert config.source.path == "server.py"
@ -342,7 +342,7 @@ class TestFastMCPConfig:
config_file = tmp_path / "fastmcp.json"
config_file.write_text(json.dumps(config_data))
config = FastMCPConfig.from_file(config_file)
config = MCPServerConfig.from_file(config_file)
# Should be parsed into EntrypointConfig
assert isinstance(config.source, FileSystemSource)
@ -365,7 +365,7 @@ class TestFastMCPConfig:
original_cwd = os.getcwd()
try:
os.chdir(tmp_path)
found = FastMCPConfig.find_config()
found = MCPServerConfig.find_config()
assert found == config_file
finally:
os.chdir(original_cwd)
@ -379,7 +379,7 @@ class TestFastMCPConfig:
subdir.mkdir()
# Should NOT find config in parent directory
found = FastMCPConfig.find_config(subdir)
found = MCPServerConfig.find_config(subdir)
assert found is None
def test_find_config_in_specified_dir(self, tmp_path):
@ -388,12 +388,12 @@ class TestFastMCPConfig:
config_file.write_text(json.dumps({"source": {"path": "server.py"}}))
# Should find config when looking in the directory that contains it
found = FastMCPConfig.find_config(tmp_path)
found = MCPServerConfig.find_config(tmp_path)
assert found == config_file
def test_find_config_not_found(self, tmp_path):
"""Test when config is not found."""
found = FastMCPConfig.find_config(tmp_path)
found = MCPServerConfig.find_config(tmp_path)
assert found is None
def test_invalid_transport(self, tmp_path):
@ -407,12 +407,12 @@ class TestFastMCPConfig:
config_file.write_text(json.dumps(config_data))
with pytest.raises(ValidationError):
FastMCPConfig.from_file(config_file)
MCPServerConfig.from_file(config_file)
def test_optional_sections(self):
"""Test that all config sections are optional except source."""
# Only source is required
config = FastMCPConfig(source={"path": "server.py"})
config = MCPServerConfig(source={"path": "server.py"})
assert isinstance(config.source, FileSystemSource)
assert config.source.path == "server.py"
# Environment and deployment are now always present but may be empty
@ -420,7 +420,7 @@ class TestFastMCPConfig:
assert isinstance(config.deployment, Deployment)
# Only environment with values
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"}, environment={"python": "3.12"}
)
assert config.environment.python == "3.12"
@ -431,7 +431,7 @@ class TestFastMCPConfig:
)
# Only deployment with values
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"}, deployment={"transport": "http"}
)
assert isinstance(config.environment, Environment)

View file

@ -7,7 +7,7 @@ from pathlib import Path
import pytest
from fastmcp.client import Client
from fastmcp.utilities.fastmcp_config import FastMCPConfig
from fastmcp.utilities.mcp_server_config import MCPServerConfig
@pytest.fixture
@ -89,7 +89,7 @@ class TestConfigWithClient:
"""Test that a server loaded from config works with a client."""
# Load the config
config_file = server_with_config / "fastmcp.json"
config = FastMCPConfig.from_file(config_file)
config = MCPServerConfig.from_file(config_file)
# Import the server using the source
import importlib.util
@ -132,7 +132,7 @@ class TestEnvironmentExecution:
def test_needs_uv_with_dependencies(self):
"""Test that environment with dependencies needs UV."""
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
environment={"dependencies": ["requests", "numpy"]}, # type: ignore[arg-type]
)
@ -142,7 +142,7 @@ class TestEnvironmentExecution:
def test_needs_uv_with_python_version(self):
"""Test that environment with Python version needs UV."""
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
environment={"python": "3.12"}, # type: ignore[arg-type]
)
@ -152,7 +152,7 @@ class TestEnvironmentExecution:
def test_no_uv_needed_without_environment(self):
"""Test that no UV is needed without environment config."""
config = FastMCPConfig(source={"path": "server.py"})
config = MCPServerConfig(source={"path": "server.py"})
# Environment is now always present but may be empty
assert config.environment is not None
@ -160,7 +160,7 @@ class TestEnvironmentExecution:
def test_no_uv_needed_with_empty_environment(self):
"""Test that no UV is needed with empty environment config."""
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
environment={}, # type: ignore[arg-type]
)
@ -184,7 +184,7 @@ class TestPathResolution:
server_file = src_dir / "server.py"
server_file.write_text("# Server")
config = FastMCPConfig(source={"path": "../src/server.py"})
config = MCPServerConfig(source={"path": "../src/server.py"})
# The source path is resolved during load_server
# For now, just check that the source is created correctly
@ -198,7 +198,7 @@ class TestPathResolution:
work_dir = tmp_path / "work"
work_dir.mkdir()
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
deployment={"cwd": "work"}, # type: ignore[arg-type]
)
@ -222,7 +222,7 @@ class TestPathResolution:
reqs_file = tmp_path / "requirements.txt"
reqs_file.write_text("fastmcp>=2.0")
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
environment={"requirements": "requirements.txt"}, # type: ignore[arg-type]
)
@ -243,7 +243,7 @@ class TestConfigValidation:
def test_invalid_transport_rejected(self):
"""Test that invalid transport values are rejected."""
with pytest.raises(ValueError):
FastMCPConfig(
MCPServerConfig(
source={"path": "server.py"},
deployment={"transport": "invalid_transport"}, # type: ignore[arg-type]
)
@ -251,7 +251,7 @@ class TestConfigValidation:
def test_streamable_http_transport_rejected(self):
"""Test that streamable-http transport is rejected in fastmcp.json config."""
with pytest.raises(ValueError):
FastMCPConfig(
MCPServerConfig(
source={"path": "server.py"},
deployment={"transport": "streamable-http"}, # type: ignore[arg-type]
)
@ -259,7 +259,7 @@ class TestConfigValidation:
def test_invalid_log_level_rejected(self):
"""Test that invalid log level values are rejected."""
with pytest.raises(ValueError):
FastMCPConfig(
MCPServerConfig(
source={"path": "server.py"},
deployment={"log_level": "INVALID"}, # type: ignore[arg-type]
)
@ -267,12 +267,12 @@ class TestConfigValidation:
def test_missing_source_rejected(self):
"""Test that config without source is rejected."""
with pytest.raises(ValueError):
FastMCPConfig() # type: ignore[call-arg]
MCPServerConfig() # type: ignore[call-arg]
def test_valid_transport_values(self):
"""Test that all valid transport values are accepted."""
for transport in ["stdio", "http", "sse"]:
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
deployment={"transport": transport}, # type: ignore[arg-type]
)
@ -282,7 +282,7 @@ class TestConfigValidation:
def test_valid_log_levels(self):
"""Test that all valid log levels are accepted."""
for level in ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]:
config = FastMCPConfig(
config = MCPServerConfig(
source={"path": "server.py"},
deployment={"log_level": level}, # type: ignore[arg-type]
)

View file

@ -3,7 +3,7 @@
import json
from pathlib import Path
from fastmcp.utilities.fastmcp_config.v1.fastmcp_config import generate_schema
from fastmcp.utilities.mcp_server_config.v1.mcp_server_config import generate_schema
def test_schema_file_matches_pydantic_model():
@ -14,7 +14,7 @@ def test_schema_file_matches_pydantic_model():
/ "src"
/ "fastmcp"
/ "utilities"
/ "fastmcp_config"
/ "mcp_server_config"
/ "v1"
/ "schema.json"
)
@ -30,7 +30,7 @@ def test_schema_file_matches_pydantic_model():
assert file_schema == generated_schema, (
"The schema.json file does not match the Pydantic model schema. "
"Please regenerate the schema file by running:\n"
'uv run python -c "from fastmcp.utilities.fastmcp_config.v1.fastmcp_config import generate_schema; '
'uv run python -c "from fastmcp.utilities.mcp_server_config.v1.mcp_server_config import generate_schema; '
'import json; print(json.dumps(generate_schema(), indent=2))" > '
f"{schema_file}"
)

View file

@ -6,24 +6,24 @@ from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from fastmcp.utilities.fastmcp_config import Environment, FastMCPConfig
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.mcp_server_config import Environment, MCPServerConfig
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
class TestFastMCPConfigPrepare:
"""Test the FastMCPConfig.prepare() method."""
class TestMCPServerConfigPrepare:
"""Test the MCPServerConfig.prepare() method."""
@patch(
"fastmcp.utilities.fastmcp_config.v1.fastmcp_config.FastMCPConfig.prepare_source",
"fastmcp.utilities.mcp_server_config.v1.mcp_server_config.MCPServerConfig.prepare_source",
new_callable=AsyncMock,
)
@patch(
"fastmcp.utilities.fastmcp_config.v1.fastmcp_config.FastMCPConfig.prepare_environment",
"fastmcp.utilities.mcp_server_config.v1.mcp_server_config.MCPServerConfig.prepare_environment",
new_callable=AsyncMock,
)
async def test_prepare_calls_both_methods(self, mock_env, mock_src):
"""Test that prepare() calls both prepare_environment and prepare_source."""
config = FastMCPConfig(
config = MCPServerConfig(
source=FileSystemSource(path="server.py"),
environment=Environment(python="3.10"),
)
@ -34,16 +34,16 @@ class TestFastMCPConfigPrepare:
mock_src.assert_called_once()
@patch(
"fastmcp.utilities.fastmcp_config.v1.fastmcp_config.FastMCPConfig.prepare_source",
"fastmcp.utilities.mcp_server_config.v1.mcp_server_config.MCPServerConfig.prepare_source",
new_callable=AsyncMock,
)
@patch(
"fastmcp.utilities.fastmcp_config.v1.fastmcp_config.FastMCPConfig.prepare_environment",
"fastmcp.utilities.mcp_server_config.v1.mcp_server_config.MCPServerConfig.prepare_environment",
new_callable=AsyncMock,
)
async def test_prepare_with_output_dir(self, mock_env, mock_src):
"""Test that prepare() with output_dir calls prepare_environment with it."""
config = FastMCPConfig(
config = MCPServerConfig(
source=FileSystemSource(path="server.py"),
environment=Environment(python="3.10"),
)
@ -55,16 +55,16 @@ class TestFastMCPConfigPrepare:
mock_src.assert_called_once()
@patch(
"fastmcp.utilities.fastmcp_config.v1.fastmcp_config.FastMCPConfig.prepare_source",
"fastmcp.utilities.mcp_server_config.v1.mcp_server_config.MCPServerConfig.prepare_source",
new_callable=AsyncMock,
)
@patch(
"fastmcp.utilities.fastmcp_config.v1.fastmcp_config.FastMCPConfig.prepare_environment",
"fastmcp.utilities.mcp_server_config.v1.mcp_server_config.MCPServerConfig.prepare_environment",
new_callable=AsyncMock,
)
async def test_prepare_skip_source(self, mock_env, mock_src):
"""Test that prepare() skips source when skip_source=True."""
config = FastMCPConfig(
config = MCPServerConfig(
source=FileSystemSource(path="server.py"),
environment=Environment(python="3.10"),
)
@ -75,16 +75,16 @@ class TestFastMCPConfigPrepare:
mock_src.assert_not_called()
@patch(
"fastmcp.utilities.fastmcp_config.v1.fastmcp_config.FastMCPConfig.prepare_source",
"fastmcp.utilities.mcp_server_config.v1.mcp_server_config.MCPServerConfig.prepare_source",
new_callable=AsyncMock,
)
@patch(
"fastmcp.utilities.fastmcp_config.v1.fastmcp_config.Environment.prepare",
"fastmcp.utilities.mcp_server_config.v1.mcp_server_config.Environment.prepare",
new_callable=AsyncMock,
)
async def test_prepare_no_environment_settings(self, mock_env_prepare, mock_src):
"""Test that prepare() works with default empty environment config."""
config = FastMCPConfig(
config = MCPServerConfig(
source=FileSystemSource(path="server.py"),
# environment defaults to empty Environment()
)
@ -188,8 +188,8 @@ class TestEnvironmentPrepare:
class TestProjectPrepareCommand:
"""Test the CLI project prepare command."""
@patch("fastmcp.utilities.fastmcp_config.FastMCPConfig.from_file")
@patch("fastmcp.utilities.fastmcp_config.FastMCPConfig.find_config")
@patch("fastmcp.utilities.mcp_server_config.MCPServerConfig.from_file")
@patch("fastmcp.utilities.mcp_server_config.MCPServerConfig.find_config")
async def test_project_prepare_auto_detect(self, mock_find, mock_from_file):
"""Test project prepare with auto-detected config."""
from fastmcp.cli.cli import prepare
@ -220,7 +220,7 @@ class TestProjectPrepareCommand:
assert "Project prepared successfully" in success_call
@patch("pathlib.Path.exists")
@patch("fastmcp.utilities.fastmcp_config.FastMCPConfig.from_file")
@patch("fastmcp.utilities.mcp_server_config.MCPServerConfig.from_file")
async def test_project_prepare_explicit_path(self, mock_from_file, mock_exists):
"""Test project prepare with explicit config path."""
from fastmcp.cli.cli import prepare
@ -243,7 +243,7 @@ class TestProjectPrepareCommand:
output_dir=Path("./test-env"),
)
@patch("fastmcp.utilities.fastmcp_config.FastMCPConfig.find_config")
@patch("fastmcp.utilities.mcp_server_config.MCPServerConfig.find_config")
async def test_project_prepare_no_config_found(self, mock_find):
"""Test project prepare when no config is found."""
from fastmcp.cli.cli import prepare
@ -280,7 +280,7 @@ class TestProjectPrepareCommand:
assert "--output-dir parameter is required" in error_msg
@patch("pathlib.Path.exists")
@patch("fastmcp.utilities.fastmcp_config.FastMCPConfig.from_file")
@patch("fastmcp.utilities.mcp_server_config.MCPServerConfig.from_file")
async def test_project_prepare_failure(self, mock_from_file, mock_exists):
"""Test project prepare when prepare() fails."""
from fastmcp.cli.cli import prepare

View file

@ -13,7 +13,7 @@ from fastmcp.client.client import Client
from fastmcp.client.transports import FastMCPTransport
from fastmcp.mcp_config import MCPConfig, StdioMCPServer
from fastmcp.server.server import FastMCP
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
class TestUrlDetection:
@ -339,7 +339,7 @@ mcp = fastmcp.FastMCP("TestServer")
from unittest.mock import AsyncMock, patch
from fastmcp.cli.run import run_command
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import (
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import (
FileSystemSource,
)
@ -368,7 +368,7 @@ mcp = fastmcp.FastMCP("TestServer")
from unittest.mock import AsyncMock, patch
from fastmcp.cli.run import run_command
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import (
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import (
FileSystemSource,
)

View file

@ -6,13 +6,13 @@ from pathlib import Path
import pytest
from fastmcp.cli.run import load_fastmcp_config
from fastmcp.utilities.fastmcp_config import (
from fastmcp.cli.run import load_mcp_server_config
from fastmcp.utilities.mcp_server_config import (
Deployment,
Environment,
FastMCPConfig,
MCPServerConfig,
)
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
@pytest.fixture
@ -43,17 +43,17 @@ def test_tool(message: str) -> str:
return config_file
def test_load_fastmcp_config(sample_config, monkeypatch):
def test_load_mcp_server_config(sample_config, monkeypatch):
"""Test loading configuration and returning config subsets."""
# Capture environment changes
original_env = dict(os.environ)
try:
config = load_fastmcp_config(sample_config)
config = load_mcp_server_config(sample_config)
# Check that we got the right types
assert isinstance(config, FastMCPConfig)
assert isinstance(config, MCPServerConfig)
assert isinstance(config.source, FileSystemSource)
assert isinstance(config.deployment, Deployment)
assert isinstance(config.environment, Environment)
@ -95,7 +95,7 @@ def test_load_config_with_entrypoint_source(tmp_path):
server_file = src_dir / "server.py"
server_file.write_text("# Server")
config = load_fastmcp_config(config_file)
config = load_mcp_server_config(config_file)
# Check source - path is not resolved yet, only during load_server
assert config.source.path == "src/server.py"
@ -125,7 +125,7 @@ def test_load_config_with_cwd(tmp_path):
original_cwd = os.getcwd()
try:
config = load_fastmcp_config(config_file) # noqa: F841
config = load_mcp_server_config(config_file) # noqa: F841
# Check that working directory was changed
assert Path.cwd() == subdir.resolve()
@ -160,7 +160,7 @@ def test_load_config_with_relative_cwd(tmp_path):
original_cwd = os.getcwd()
try:
config = load_fastmcp_config(config_file) # noqa: F841
config = load_mcp_server_config(config_file) # noqa: F841
# Should change to parent directory of config file
assert Path.cwd() == subdir1.resolve()
@ -180,7 +180,7 @@ def test_load_minimal_config(tmp_path):
server_file = tmp_path / "server.py"
server_file.write_text("# Server")
config = load_fastmcp_config(config_file)
config = load_mcp_server_config(config_file)
# Check we got source - path is not resolved yet, only during load_server
assert isinstance(config.source, FileSystemSource)
@ -201,7 +201,7 @@ def test_load_config_with_server_args(tmp_path):
server_file = tmp_path / "server.py"
server_file.write_text("# Server")
config = load_fastmcp_config(config_file)
config = load_mcp_server_config(config_file)
assert config.deployment.args == ["--debug", "--config", "custom.json"]
@ -221,7 +221,7 @@ def test_config_subset_independence(tmp_path):
server_file = tmp_path / "server.py"
server_file.write_text("# Server")
config = load_fastmcp_config(config_file)
config = load_mcp_server_config(config_file)
# Each subset should be independently usable
# Path is not resolved yet, only during load_server
@ -259,7 +259,7 @@ def test_environment_config_path_resolution(tmp_path):
server_file = tmp_path / "server.py"
server_file.write_text("# Server")
config = load_fastmcp_config(config_file)
config = load_mcp_server_config(config_file)
# Check that UV command is built with resolved paths
uv_cmd = config.environment.build_uv_run_command(["fastmcp", "run", "server.py"])

View file

@ -4,8 +4,8 @@ from pathlib import Path
import pytest
from fastmcp.utilities.fastmcp_config import FastMCPConfig
from fastmcp.utilities.fastmcp_config.v1.sources.filesystem import FileSystemSource
from fastmcp.utilities.mcp_server_config import MCPServerConfig
from fastmcp.utilities.mcp_server_config.v1.sources.filesystem import FileSystemSource
class TestServerArguments:
@ -39,7 +39,7 @@ def get_config() -> dict:
# Test with arguments
source = FileSystemSource(path=str(server_file))
config = FastMCPConfig(source=source)
config = MCPServerConfig(source=source)
from fastmcp.cli.cli import with_argv
@ -69,7 +69,7 @@ mcp = FastMCP(args.name)
""")
source = FileSystemSource(path=str(server_file))
config = FastMCPConfig(source=source)
config = MCPServerConfig(source=source)
from fastmcp.cli.cli import with_argv
@ -96,7 +96,7 @@ mcp = FastMCP(name)
""")
source = FileSystemSource(path=str(server_file))
config = FastMCPConfig(source=source)
config = MCPServerConfig(source=source)
from fastmcp.cli.cli import with_argv
@ -123,7 +123,7 @@ mcp = FastMCP(name)
pytest.skip("config_server.py example not found")
source = FileSystemSource(path=str(config_server))
config = FastMCPConfig(source=source)
config = MCPServerConfig(source=source)
from fastmcp.cli.cli import with_argv

View file

@ -1,6 +1,6 @@
"""Tests for CLI utility functions."""
from fastmcp.utilities.fastmcp_config.v1.fastmcp_config import Environment
from fastmcp.utilities.mcp_server_config.v1.mcp_server_config import Environment
class TestEnvironmentBuildUVRunCommand: