Reflect the live state: readable data-surface table (reporting/tracksolid/
tickets/fuel + owners), the owner-keyed default-privilege gotcha, the
tickets.inc typed-vs-raw column note, the env knob, code-only redeploy that
reuses tokens, and tickets example prompts. Status flipped to deployed & live.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The analytics_ro role only had USAGE/SELECT on reporting + tracksolid, so
the tickets schema (INC/CRQ, 8 tables + 1 view + 7 fns) and fuel schema
were invisible to the MCP server — queries failed with permission denied.
- analytics_ro_role.sql: GRANT USAGE/SELECT/EXECUTE on tickets + fuel.
Default privileges for these are keyed to postgres (their owner), not
tracksolid_owner, so future objects auto-grant correctly.
- analytics_mcp.py: READABLE_SCHEMAS now includes tickets + fuel and is
overridable via MCP_READABLE_SCHEMAS, so the introspection helpers
(list_tables/describe_table/sample_table) work for them too.
- deploy.sh: reuse existing analyst tokens from the running container when
MCP_AUTH_TOKENS is unset, so a code-only redeploy needs no secret.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The MCP SDK's transport-security DNS-rebinding protection only accepts a
localhost Host header by default and returns 421 behind Traefik (Host =
fleetmcp.*). It targets browser attacks on localhost-bound servers and does
not apply to a public, TLS-terminated, Bearer-authenticated service. Off by
default now; re-enableable via MCP_DNS_REBINDING_PROTECTION=1 + MCP_ALLOWED_HOSTS.
Also: deploy.sh health echo uses python (slim image has no curl).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>