Skip to content

Replace local MCP tool implementations with FastMCP proxy to remote server#37

Merged
josecsotomorales merged 3 commits intomainfrom
ets/fastmcp_proxy
Mar 26, 2026
Merged

Replace local MCP tool implementations with FastMCP proxy to remote server#37
josecsotomorales merged 3 commits intomainfrom
ets/fastmcp_proxy

Conversation

@ets
Copy link
Copy Markdown
Contributor

@ets ets commented Mar 26, 2026

Summary

The CLI's MCP server previously maintained 35 hand-written tool implementations that mirrored the Qualytics REST API. Since every Qualytics deployment already exposes its own full-featured MCP server at {base_url}/api/mcp, the CLI now proxies that remote server over a local stdio transport — giving LLM clients the best of both worlds.

What you keep / gain

Before After
Tool count 35 (manually maintained) All tools the platform exposes
Stays in sync with API No (manual updates required) Yes, automatically
stdio transport Yes Yes
auth_status (local config) Yes Yes (added back explicitly)
Network required Yes (calls REST API) Yes (calls remote MCP)
SSL verify respected Yes Yes

Changes

  • qualytics/mcp/server.py — 828 → 62 lines. All 34 REST-backed tool functions removed. Only auth_status() remains as a plain function (reads ~/.qualytics/config.yaml, not the API).
  • qualytics/cli/mcp_cmd.py — Builds a FastMCPProxy via create_proxy() backed by a StreamableHttpTransport pointed at {config_url}/mcp with bearer token auth and configurable SSL verification. auth_status injected via proxy.add_tool(). Unauthenticated startup exits with a clear error.
  • qualytics/cli/auth.py — Added full URL field to auth status output (previously printed hostname only).
  • pyproject.toml / uv.lock — Added httpx>=0.27.0 as an explicit dependency (previously transitive via fastmcp).
  • tests/test_mcp.py — Removed 34 now-remote tool tests. Added proxy URL/auth construction verification and unauthenticated exit path test. 551 tests passing.

Test plan

  • uv run qualytics auth status — verify URL field now appears in output
  • uv run qualytics mcp serve --transport streamable-http + uv run fastmcp list http://127.0.0.1:8000/mcp — verify remote tools are proxied
  • uv run pytest — all 551 tests pass

🤖 Generated with Claude Code

ets and others added 2 commits March 25, 2026 21:04
…erver

The CLI's MCP server previously maintained 35 tool implementations that
duplicated the Qualytics API. Since every deployment exposes its own full
MCP server at {base_url}/api/mcp, the CLI now proxies that remote server
over stdio transport — combining the platform's always-current native tool
surface with easy local connectivity for desktop LLM clients (Claude Code,
Cursor, etc.).

Changes:
- mcp/server.py: stripped from 828 → 62 lines; only auth_status() remains
  as a local tool (reads ~/.qualytics/config.yaml, not the API)
- cli/mcp_cmd.py: builds a FastMCPProxy via create_proxy() backed by a
  StreamableHttpTransport pointed at {config_url}/mcp with bearer token
  auth and configurable SSL verification; auth_status injected via
  proxy.add_tool()
- cli/auth.py: added full URL field to auth status output (was hostname-only)
- pyproject.toml + uv.lock: added httpx>=0.27.0 as explicit dependency
- tests/test_mcp.py: removed 34 now-remote tool tests; added proxy URL/auth
  construction test and unauthenticated exit path test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@josecsotomorales
Copy link
Copy Markdown
Member

@greptileai

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 26, 2026

Greptile Summary

This PR replaces the CLI's 35 hand-written MCP tool implementations with a FastMCP proxy that transparently forwards requests to the remote Qualytics deployment's native MCP server ({config_url}/mcp), while keeping auth_status as a locally-executed tool that reads ~/.qualytics/config.yaml. The result is a dramatically simpler codebase (828 → 62 lines in server.py) that stays in sync with the platform's API automatically.

Key changes:

  • mcp_cmd.py now builds a StreamableHttpTransport with bearer-token auth and configurable SSL, creates a FastMCPProxy via create_proxy(), injects auth_status locally, and runs the proxy over stdio or streamable-HTTP
  • Both previous review concerns are fully addressed: empty url/token guards were added (lines 69–74 of mcp_cmd.py) and a dedicated test_mcp_serve_forwards_ssl_verify_false test was added that extracts the httpx_client_factory lambda and asserts httpx.AsyncClient is constructed with verify=False
  • auth.py gains a URL: line in the auth status display to make the configured endpoint visible
  • httpx is explicitly pinned in pyproject.toml (previously a transitive-only dependency)
  • 551 tests passing

Confidence Score: 5/5

Safe to merge — both prior review concerns are resolved, implementation is clean, and 551 tests pass.

The two previously flagged gaps (missing empty-config guard and missing ssl_verify forwarding test) are both fully addressed in this revision. The proxy construction follows standard FastMCP patterns, the httpx dependency is correctly pinned, and the test coverage for the new code path is thorough. No new critical issues found.

No files require special attention.

Important Files Changed

Filename Overview
qualytics/cli/mcp_cmd.py Core of the refactor: replaces the local FastMCP server with a StreamableHttpTransport proxy, adds empty-config guards (url/token), and injects auth_status as a local tool alongside proxied remote tools.
qualytics/mcp/server.py Reduced from 828 to 62 lines — all 34 REST-backed tool implementations removed; only auth_status() remains as a plain callable that reads local config without contacting the API.
tests/test_mcp.py Old tool-mirroring tests dropped; new tests cover proxy URL construction, bearer token wiring, empty url/token guard, unauthenticated exit, and ssl_verify=False forwarding into the httpx client factory.
qualytics/cli/auth.py Adds a URL field to auth status output so users can verify the full configured URL; one-line addition with no functional risk.
pyproject.toml httpx>=0.27.0 promoted from transitive to explicit dependency to pin the version range required by the new httpx.AsyncClient usage in mcp_cmd.py.

Sequence Diagram

sequenceDiagram
    participant LLM as LLM Client(Claude/Cursor)
    participant Proxy as FastMCPProxy(in-process)
    participant Remote as Remote MCP Server({config_url}/mcp)
    participant Config as ~/.qualytics/config.yaml

    LLM->>Proxy: call remote tool (e.g. list_datastores)
    Proxy->>Remote: HTTP POST /mcp Authorization: Bearer {token} verify={ssl_verify}
    Remote-->>Proxy: tool result
    Proxy-->>LLM: forwarded result

    LLM->>Proxy: call auth_status
    Proxy->>Config: load_config() [local, no network]
    Config-->>Proxy: config dict
    Proxy-->>LLM: auth status result
Loading

Reviews (2): Last reviewed commit: "Address pr review" | Re-trigger Greptile

@josecsotomorales
Copy link
Copy Markdown
Member

@greptileai

@josecsotomorales josecsotomorales merged commit 9f00424 into main Mar 26, 2026
10 checks passed
@josecsotomorales josecsotomorales deleted the ets/fastmcp_proxy branch March 26, 2026 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants