Skip to content

design: remote-MCP tiers (2+3) for results-inspector — auth-first scope (build gated on demand) #20

Description

@Jammy2211

Overview

Design + scope only (human decision 2026-07-21). Captures the auth model,
tier-2 transport plan, tier-3 hosting sketch, and the Richard/PyAutoMCP
coordination for making the read-only results-inspector MCP server reachable
remotely. No code is written and no network surface is built here. The build
is gated on demonstrated demand + a security-review pass and must never
auto-ship. Follows the passed local-stdio acceptance gate (#17) and the shipped
launcher hardening (#18).

Why design-only now

The prompt gates this as "only pursue once demonstrated demand exists — if it
earns it."
Local stdio (tier 1) is shipped and acceptance-passed; there is no
demonstrated demand for remote access yet, and standing up an unauthenticated
file-reading network surface on spec is the wrong risk. Prior-art coordination
with Richard is also a prerequisite. So: design the security + transport now,
build later only if it earns it.

Security model — the core; build this FIRST when built

The read-only tools (list_searches/get_*/fetch_image) resolve arbitrary
absolute directories
on the host. Local stdio is safe (only the local user's
client spawns it). A tunneled/hosted server is a remote, **unauthenticated file-read

  • directory-enumeration surface** unless all of the following are designed in:
  1. Authentication before any tool dispatch.
    • Tier 2 (personal/prototype): static bearer token — Authorization: Bearer <secret>
      validated by ASGI middleware wrapping the streamable-http app; secret from env
      (PYAUTO_MCP_TOKEN), never committed; reject unauthenticated requests with 401
      at the transport layer, before MCP dispatch.
    • Tier 3 (hosted/shared): OAuth2/OIDC (the MCP HTTP spec supports OAuth) or an
      auth gateway; per-user identity; short-lived tokens.
  2. Path confinement (defense in depth, both tiers). An env allowlist of roots
    (PYAUTO_MCP_ALLOWED_ROOTS); every tool Path.resolve()s its directory arg and
    rejects anything not under an allowed root — blocks ../ traversal and absolute-path
    escape even for an authenticated caller. Tier 3: per-user root scoping.
  3. Transport hardening. Bind 127.0.0.1; expose only via the tunnel (cloudflared/
    ngrok) or a TLS ingress; never bind 0.0.0.0 without auth+TLS; rate-limit; audit-log
    every tool call (who / which dir / when) for tier 3.
  4. Keep the read-only invariant. No writes, no compute/fit tools on a remote surface
    (contrast PyAutoMCP below) — the smaller the remote surface, the smaller the risk.

Tier 2 — remote via tunnel (transport plan)

  • Add an opt-in run mode to server.py (both assistants): a CLI/env flag
    (PYAUTO_MCP_HTTP=1 / python -m autoassistant.mcp --http) that calls
    mcp.run(transport="streamable-http", host="127.0.0.1", port=…) instead of stdio.
    Default stays stdio — no accidental network exposure. (Installed mcp FastMCP
    supports streamable-http — verified.)
  • Wrap the FastMCP ASGI app (mcp.streamable_http_app()) with the bearer-auth +
    path-allowlist middleware before serving.
  • cloudflared/ngrok recipe (quick tunnel to test; named tunnel for stability); the
    tunnel HTTPS URL is the connector endpoint pasted into claude.ai (custom connector)
    / ChatGPT (developer mode).
  • Docs: a remote section in {af,al}_inspect_results_mcp.md marking the token +
    allowlist as mandatory — never run the tunnel without them.
  • Effort: medium; MUST pass security-review before any PR.

Tier 3 — hosted (sketch, gated on demand)

Deploy next to shared collaboration outputs (Euclid sample-scale triage). Auth =
OAuth/OIDC + per-user output scoping; TLS at ingress; audit log; rate limits; async +
aggregator-load caching for scale. Natural consumer: rhayes777/aggregator-agent
(pydantic-ai vision triage of lens-modelling output) — a tier-3 client, not part of
this server. This is "the substance"; do not detail-scope until demand + a hosting
target are chosen.

Coordinate with Richard (rhayes777/PyAutoMCP)

PyAutoMCP (automcp: aggregate/compute/optimisation/visualise/resources/
schema/pydantic_wrapper) is a parallel, broader MCP — it exposes compute +
optimisation (fitting), which our read-only server deliberately does not. Neither has a
remote transport/auth layer today (code search: 0 matches). Decision to make with
Richard before building remote:
converge on one server with profiles (a read-only
"inspect" profile = ours + a "compute" profile = his, sharing one transport/auth layer),
or keep two and share only the auth/tunnel recipe. For the read-only remote profile,
drop the optimise/compute surface.

Hard gates

  • Build only once demonstrated demand exists.
  • MUST run the security-review skill on the branch before any PR.
  • NEVER auto-ship — human-required. The intake classifier mis-sized this small/safe;
    it is a network-facing file-read surface.

Original Prompt

Click to expand starting prompt

draft/feature/autofit_assistant/remote_mcp_deployment_tiers.md — build remote-MCP
tiers 2 (tunnel) + 3 (hosted) for the results-inspector server. Scope = transport +
deployment + auth, NOT new tools. human-required + security-review; only pursue once
demonstrated demand exists.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions