mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
feat(remote): add --verify flag for TLS certificate verification (#4369)
This commit is contained in:
parent
7f2d034f4d
commit
a13e48ea6f
4 changed files with 147 additions and 3 deletions
|
|
@ -73,6 +73,24 @@ Use `--auth none` for unauthenticated development servers:
|
|||
uvx fastmcp-remote http://localhost:8000/mcp --auth none
|
||||
```
|
||||
|
||||
For servers behind a self-signed certificate, point `--verify` at a CA bundle that trusts the certificate:
|
||||
|
||||
```bash
|
||||
uvx fastmcp-remote https://internal.example.com/mcp --verify /path/to/ca-bundle.pem
|
||||
```
|
||||
|
||||
To disable certificate verification entirely (insecure, only for trusted private networks), pass `--verify false`:
|
||||
|
||||
```bash
|
||||
uvx fastmcp-remote https://internal.example.com/mcp --verify false
|
||||
```
|
||||
|
||||
A CA bundle can also be supplied through the standard `SSL_CERT_FILE` environment variable, which OpenSSL reads automatically:
|
||||
|
||||
```bash
|
||||
SSL_CERT_FILE=/path/to/ca-bundle.pem uvx fastmcp-remote https://internal.example.com/mcp
|
||||
```
|
||||
|
||||
## Options
|
||||
|
||||
- `--transport`: Choose `http` or `sse`. Defaults to `http`.
|
||||
|
|
@ -82,5 +100,6 @@ uvx fastmcp-remote http://localhost:8000/mcp --auth none
|
|||
- `--auth-timeout`: Set how long to wait for the OAuth callback. Defaults to 300 seconds.
|
||||
- `--ignore-tool`: Hide tools whose names match a glob pattern.
|
||||
- `--auth`: Choose `oauth` or `none`. The default uses OAuth unless an `Authorization` header is provided.
|
||||
- `--verify`: Control TLS certificate verification. Pass a path to a CA bundle to trust a self-signed certificate, or `false` to disable verification (insecure). Defaults to verification enabled.
|
||||
|
||||
OAuth tokens are stored under `~/.fastmcp/remote` by default. Set `FASTMCP_REMOTE_CONFIG_DIR` to use another directory.
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ class RemoteConfig:
|
|||
ignore_tools: tuple[str, ...]
|
||||
show_banner: bool
|
||||
log_level: str | None
|
||||
verify: bool | str | None
|
||||
|
||||
|
||||
class IgnoreTools(Transform):
|
||||
|
|
@ -84,6 +85,16 @@ def parse_header(value: str) -> tuple[str, str]:
|
|||
return name.strip(), expanded_value.strip()
|
||||
|
||||
|
||||
def parse_verify(value: str) -> bool | str:
|
||||
"""Interpret the --verify value as a boolean toggle or a CA bundle path."""
|
||||
lowered = value.strip().lower()
|
||||
if lowered in {"false", "0", "no", "off"}:
|
||||
return False
|
||||
if lowered in {"true", "1", "yes", "on"}:
|
||||
return True
|
||||
return value
|
||||
|
||||
|
||||
def default_storage_dir(resource: str | None = None) -> Path:
|
||||
if config_dir := os.environ.get("FASTMCP_REMOTE_CONFIG_DIR"):
|
||||
base = Path(config_dir).expanduser()
|
||||
|
|
@ -147,6 +158,17 @@ def build_parser() -> argparse.ArgumentParser:
|
|||
default=[],
|
||||
help="Hide tools matching this glob pattern. Repeat for multiple patterns.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--verify",
|
||||
type=parse_verify,
|
||||
default=None,
|
||||
metavar="VERIFY",
|
||||
help=(
|
||||
"SSL certificate verification. Pass a path to a CA bundle file, or "
|
||||
"'false' to disable verification (insecure, for self-signed "
|
||||
"certificates). Defaults to verification enabled."
|
||||
),
|
||||
)
|
||||
parser.add_argument(
|
||||
"--debug",
|
||||
action="store_true",
|
||||
|
|
@ -190,6 +212,7 @@ def parse_args(argv: Sequence[str] | None = None) -> RemoteConfig:
|
|||
ignore_tools=tuple(args.ignore_tool),
|
||||
show_banner=not args.silent,
|
||||
log_level=log_level,
|
||||
verify=args.verify,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -228,8 +251,12 @@ def resolve_auth(config: RemoteConfig) -> OAuth | None:
|
|||
def build_transport(config: RemoteConfig) -> SSETransport | StreamableHttpTransport:
|
||||
auth = resolve_auth(config)
|
||||
if config.transport == "sse":
|
||||
return SSETransport(config.url, headers=config.headers, auth=auth)
|
||||
return StreamableHttpTransport(config.url, headers=config.headers, auth=auth)
|
||||
return SSETransport(
|
||||
config.url, headers=config.headers, auth=auth, verify=config.verify
|
||||
)
|
||||
return StreamableHttpTransport(
|
||||
config.url, headers=config.headers, auth=auth, verify=config.verify
|
||||
)
|
||||
|
||||
|
||||
async def run(config: RemoteConfig) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue