Root Upstream Runtime

Copy Markdown View Source

The root ptc_runner library owns the upstream runtime used by both mix ptc.repl and ptc_runner_mcp. It lets PTC-Lisp programs call configured upstream tools with (tool/call ...) and inspect them with (tool/servers), (dir ...), (doc ...), (meta ...), and (apropos ...).

Use this when you want local REPL programs or embedded Elixir callers to use the same OpenAPI/MCP upstream machinery without running the MCP server process.

REPL Usage

mix ptc.repl --upstreams-config upstreams.json
mix ptc.repl --upstreams-config upstreams.json -e "(tool/servers)"
mix ptc.repl --upstreams-config upstreams.json \
  --catalog-snapshot-mode frozen \
  -e "(dir \"github\")"

The REPL resolves the config path from --upstreams-config first, then PTC_RUNNER_UPSTREAMS. If neither is set, it starts a plain PTC-Lisp REPL with no upstream tools.

Useful options:

OptionDefaultMeaning
--max-tool-calls50Per-evaluation (tool/call ...) budget.
--max-catalog-ops25Per-evaluation discovery form budget.
--upstream-call-timeout-ms5000Per-upstream-call timeout.
--max-upstream-response-bytes2097152Per-response cap before decode.
--catalog-modeautoauto, inline, or lazy catalog text exposure.
--catalog-snapshot-modelivelive or frozen catalog population.

Config Format

The config format is shared with ptc_runner_mcp. Use explicit transport names:

  • "openapi" for curated read-only JSON OpenAPI GET operations.
  • "mcp_stdio" for external MCP servers launched over stdio.
  • "mcp_http" for external MCP servers reached over Streamable HTTP.

Old transport names such as "stdio" and "http" are rejected. See aggregator-mode.md for complete JSON examples, credential bindings, static-header restrictions, OpenAPI validation, and the (tool/call ...) authoring model.

OpenAPI v1 Contract

OpenAPI upstreams are a narrow read-only JSON contract, not a general OpenAPI client. The v1 adapter compiles only explicitly included GET operations. Operations with request bodies are rejected at compile time, as are header and cookie parameters; configure service-level headers with auth: or static_headers: instead.

Successful responses must be JSON responses or empty 204 responses. Non-JSON success responses are rejected during schema compilation so callers do not have to branch on transport-specific body formats at runtime.

Snapshot Modes

live mode is the root REPL default. MCP stdio/http clients are not started or listed at runtime startup; discovery and (tool/call ...) attempt to start/list them when needed. This keeps REPL startup fast when a configured MCP upstream is down or expensive to launch.

frozen mode starts and lists MCP stdio/http upstreams during runtime startup. The scrubbed snapshot is then reused for catalog text and discovery. Startup fails if a configured MCP upstream cannot start or answer tools/list. The MCP server uses frozen mode by default so its advertised tool surface is stable for the lifetime of the server process.

OpenAPI schemas are loaded during runtime startup in both modes because the runtime compiles the explicitly included operations before exposing them. Prefer schema_file for production so startup does not depend on a schema host.

Redaction

Credential values from env, file, and literal bindings are resolved when the root upstream runtime starts. They are stored only in the runtime credential struct and scrub set, not in upstream config maps, call records, traces, or catalog snapshots. Rotate an env var or credential file by restarting the REPL or MCP server process.

Catalog and discovery output is scrubbed through the runtime redactor before it reaches REPL output, MCP tool descriptions, traces, debug records, or session history.

When the MCP server embeds the root runtime, it also registers the runtime's secret set with the MCP server redactor so existing trace, debug, session, log, and agentic prompt scrub paths remain active.