Repository navigation
v0.4.0
The server can now run as a hosted HTTP service instead of only over stdio, and it grew the operational surface a hosted deployment needs. stdio behavior is unchanged — if you run the server locally per-client, nothing here requires action.
Running over HTTP
Start the server with --transport streamable-http (or MCP_TRANSPORT=streamable-http) and point clients at a URL instead of spawning the process per client:
python /path/to/fivetran-mcp/server.py --transport streamable-http --host 0.0.0.0 --port 8000| Variable | Required | Default | Description |
|---|---|---|---|
MCP_TRANSPORT |
No | stdio |
stdio or streamable-http. Same as --transport. |
MCP_HOST / --host |
No | 127.0.0.1 |
Bind host, streamable-http only. |
MCP_PORT / --port |
No | 8000 |
Bind port, streamable-http only. |
MCP_ALLOWED_ORIGINS |
No | (empty) | Comma-separated allowed Origin header values. |
MCP_ALLOWED_HOSTS |
No | (empty) | Comma-separated allowed Host header values. |
In streamable-http mode credentials come from each request's Authorization header rather than from the environment: the client sends the same API key/secret pair as a Basic auth header. Do not set FIVETRAN_API_KEY / FIVETRAN_API_SECRET for an HTTP deployment — the server refuses to start if it finds them, since a shared key baked into a multi-tenant process would apply one operator's credentials to every caller.
If neither MCP_ALLOWED_ORIGINS nor MCP_ALLOWED_HOSTS is set, the server runs without DNS-rebinding protection and logs a startup warning.
OAuth resource-server support is scaffolding only and not yet functional. Token verification is unimplemented, so leave FIVETRAN_AUTH_ISSUER unset; HTTP mode today works only in its header-forwarding form.
Per-endpoint denials
DISALLOWED_ACTIONS accepts a third form alongside resource:action:
resource:action:endpoint_name(e.g.connections:write:sync_connection) denies one specific endpoint, with no cascade. The endpoint must belong to that exactresource:actionpair or startup fails.
Operational surface
GET /health— unauthenticated, always mounted, returns the version and a manifest checksum computed once at import and cached.- Structured logging — one JSON log line per tool invocation carrying request id, mode, tool, endpoint, upstream status, latency, and client, emitted from a
finallyblock so it fires even on an uncaught exception. Logs to stdout in streamable-http mode and stderr in stdio mode, since stdio's stdout is the MCP protocol channel. Only whitelisted fields are logged — never request bodies or headers. - A metrics seam —
_record_tool_callis the single hook metrics will attach to. No counters or exporter yet. - A Dockerfile — single-stage
python:3.12-slim, non-root user, defaulting to streamable-http on0.0.0.0:8000. - Upstream status is logged for successful calls as well as errors.
Also in this release
- MCP tool annotations keyed off the action tier:
readOnlyHinton reads,destructiveHinton deletes,openWorldHint=Falsethroughout. Server instructions describe thelist_endpoints→get_schema→ call discovery flow. - Advisory confirmation warnings on write and delete tool descriptions, and a unified error contract across grant, routing, and upstream failures.
- A request-scoped credential resolver with env, header, and OAuth-stub implementations, wired to the transport.
- One shared
httpx.AsyncClientacross outbound Fivetran calls instead of a client per request. endpoint_overrides.json, for prepending text to a specific endpoint's description without regenerating the manifest.account_readcarriesopenai/profile_metaso ChatGPT can disambiguate accounts.configure()is extracted from import time, making startup testable.server.pyreorganized into labeled sections.- Broader test coverage across
configure()paths and concurrency.