MCP Server Configuration Reference

Copy Markdown View Source

Canonical reference for every flag, environment variable, response profile, catalog mode, tracing setting, and lifecycle command exposed by ptc_runner_mcp. For installation and client wiring see mcp-server-cli.md; for the conceptual overview (when to use the server, security model, architecture) see mcp-server.md. Aggregator concepts live in aggregator-mode.md, agentic mode in agentic-mode.md, and lisp_debug in mcp-debug.md.

Boot-time configuration model

All configuration is read once at boot, either from a CLI flag or the equivalent environment variable. CLI flags win when both are set. Aggregator-mode defaults only apply when no explicit value is given. To pass flags through Claude Desktop / Cline / Cursor, append them to the args array, for example:

"args": ["start", "--max-frame-bytes", "8388608"]

Core flags

FlagEnv varDefaultMeaning
--max-frame-bytesPTC_RUNNER_MCP_MAX_FRAME_BYTES8388608 (8 MiB)Hard cap on a single NDJSON frame.
--max-program-bytesPTC_RUNNER_MCP_MAX_PROGRAM_BYTES65536 (64 KiB)Hard cap on the program argument.
--max-context-bytesPTC_RUNNER_MCP_MAX_CONTEXT_BYTES4194304 (4 MiB)Hard cap on the context argument.
--max-concurrent-callsPTC_RUNNER_MCP_MAX_CONCURRENT_CALLS8Concurrency gate; excess calls return :busy.
--log-levelPTC_RUNNER_MCP_LOG_LEVELinfoOne of debug, info, warn, error.
--trace-dirPTC_RUNNER_MCP_TRACE_DIRunsetDirectory for per-call JSONL trace files. Tracing is OFF unless this is set.
--trace-payloadsPTC_RUNNER_MCP_TRACE_PAYLOADSsummaryOne of none, summary, full. Controls program / context / result inclusion in traces.
--trace-max-filesPTC_RUNNER_MCP_TRACE_MAX_FILES1000Rolling-deletion cap on --trace-dir.
--turn-log-dirPTC_RUNNER_MCP_TURN_LOG_DIRunsetDirectory for the canonical stateful-session turn log. When set, all accepted lisp_session_eval attempts write event: "turn" records to one JSONL file.
--preludePTC_RUNNER_MCP_PRELUDEunsetPath to a Capability Prelude source file attached to every lisp_eval, lisp_session_eval, and agentic lisp_task run. The file is read once at boot; attach-time requires still fail closed against configured upstreams and granted tools.
--prelude-store-seedPTC_RUNNER_MCP_PRELUDE_STORE_SEEDunsetFile or directory of .clj Capability Prelude sources used to seed a volatile in-memory PreludeStore at boot. Each file's id is derived from its compiled namespace, not its filename.
--aggregator-read-onlyPTC_RUNNER_MCP_AGGREGATOR_READ_ONLYfalseAggregator-mode annotation override for upstream configs that are read-only by construction.
--agenticPTC_RUNNER_MCP_AGENTICfalseExpose the experimental lisp_task tool when aggregator mode is active.
--agentic-modelPTC_RUNNER_MCP_AGENTIC_MODELgemini-flash-litePlanner model alias or provider-qualified model id.
--agentic-task-timeout-msPTC_RUNNER_MCP_AGENTIC_TASK_TIMEOUT_MS45000Wall-clock cap for one lisp_task request.
--agentic-planner-timeout-msPTC_RUNNER_MCP_AGENTIC_PLANNER_TIMEOUT_MS15000Per-planner-call timeout.
--agentic-max-output-tokensPTC_RUNNER_MCP_AGENTIC_MAX_OUTPUT_TOKENS1200Planner output token cap.
--agentic-max-result-bytesPTC_RUNNER_MCP_AGENTIC_MAX_RESULT_BYTES4096Maximum rendered answer bytes in the lisp_task response.
--agentic-include-programPTC_RUNNER_MCP_AGENTIC_INCLUDE_PROGRAMtrueInclude the generated PTC-Lisp program in lisp_task responses.
--agentic-trace-promptsPTC_RUNNER_MCP_AGENTIC_TRACE_PROMPTSfalseInclude agentic prompt snapshots in traces. Use only for local debugging.
--agentic-max-turnsPTC_RUNNER_MCP_AGENTIC_MAX_TURNS1Maximum SubAgent planner turns per lisp_task.
--agentic-retry-turnsPTC_RUNNER_MCP_AGENTIC_RETRY_TURNS0Additional retry turns after parser/runtime/validation feedback.
--agentic-allow-writesPTC_RUNNER_MCP_AGENTIC_ALLOW_WRITESfalsePermit lisp_task in write-capable or unknown-effect aggregator configurations.
--agentic-subagent-configPTC_RUNNER_MCP_AGENTIC_SUBAGENT_CONFIGunsetJSON config file for max_turns, retry_turns, and prompt prefix/suffix.
--agentic-capability-summary-max-bytesPTC_RUNNER_MCP_AGENTIC_CAPABILITY_SUMMARY_MAX_BYTES800Byte cap for the auto-generated lisp_task capability summary.
--agentic-capability-summaryPTC_RUNNER_MCP_AGENTIC_CAPABILITY_SUMMARYunsetPath to an operator-supplied capability summary for lisp_task.
--sessionsPTC_RUNNER_MCP_SESSIONSfalseExpose opt-in stateful PTC-Lisp session tools.
--sessions-allow-prelude-writePTC_RUNNER_MCP_SESSIONS_ALLOW_PRELUDE_WRITEfalsePermit lisp_session_start with mode: "write_capable" when a prelude store is configured. The session attaches the host prelude/ wrapper and grants private prelude_store_* backing tools only for that session's evals.
--max-sessionsPTC_RUNNER_MCP_MAX_SESSIONS64Maximum live sessions per MCP server process.
--max-sessions-per-ownerPTC_RUNNER_MCP_MAX_SESSIONS_PER_OWNER16Maximum live sessions per owner.
--session-ttl-msPTC_RUNNER_MCP_SESSION_TTL_MS1800000 (30 min)Maximum lifetime for a session.
--session-idle-timeout-msPTC_RUNNER_MCP_SESSION_IDLE_TIMEOUT_MS900000 (15 min)Close a session after this much idle time.
--max-session-memory-bytesPTC_RUNNER_MCP_MAX_SESSION_MEMORY_BYTES1048576 (1 MiB)Persisted Lisp memory cap per session.
--max-session-binding-bytesPTC_RUNNER_MCP_MAX_SESSION_BINDING_BYTES262144 (256 KiB)Per-binding persisted memory cap.
--max-session-bindingsPTC_RUNNER_MCP_MAX_SESSION_BINDINGS200Maximum persisted bindings per session.
--max-session-history-entry-bytesPTC_RUNNER_MCP_MAX_SESSION_HISTORY_ENTRY_BYTES65536 (64 KiB)Per-result cap for *1 / *2 / *3; oversized values become preview markers.
--max-session-print-entriesPTC_RUNNER_MCP_MAX_SESSION_PRINT_ENTRIES50Maximum persisted println entries.
--max-session-print-bytesPTC_RUNNER_MCP_MAX_SESSION_PRINT_BYTES65536 (64 KiB)Persisted print-history byte cap.
--max-session-tool-call-entriesPTC_RUNNER_MCP_MAX_SESSION_TOOL_CALL_ENTRIES50Maximum persisted tool-call history entries.
--max-session-tool-call-bytesPTC_RUNNER_MCP_MAX_SESSION_TOOL_CALL_BYTES131072 (128 KiB)Persisted tool-call history byte cap.
--max-session-upstream-call-entriesPTC_RUNNER_MCP_MAX_SESSION_UPSTREAM_CALL_ENTRIES50Maximum persisted upstream-call history entries.
--max-session-upstream-call-bytesPTC_RUNNER_MCP_MAX_SESSION_UPSTREAM_CALL_BYTES131072 (128 KiB)Persisted upstream-call history byte cap.
--max-session-preview-charsPTC_RUNNER_MCP_MAX_SESSION_PREVIEW_CHARS512Character cap for value previews in lisp_session_eval result and memory feedback. Raising this increases response tokens and remains subject to response profile / envelope caps.
--collection-hintPTC_RUNNER_MCP_COLLECTION_HINTfalseWhen a lisp_session_eval result is a collection of 20+ maps, append a one-line feedback hint suggesting (describe *1 {:paths true}) for field-coverage profiling. Replaces the generic truncation hint when both would apply.
--response-profilePTC_RUNNER_MCP_RESPONSE_PROFILEslim (or debug when --debug-tool is set)lisp_eval / lisp_session_eval response shape: slim | structured | debug. See Response profiles.
--debug-toolPTC_RUNNER_MCP_DEBUG_TOOLfalseExpose the opt-in read-only lisp_debug diagnostics tool (see mcp-debug.md). Also flips the response profile to debug unless --response-profile is set explicitly.
--debug-ring-sizePTC_RUNNER_MCP_DEBUG_RING_SIZE500In-memory ring-buffer capacity for lisp_debug (clamped to [10, 5000]).
--max-debug-response-bytesPTC_RUNNER_MCP_MAX_DEBUG_RESPONSE_BYTES65536 (64 KiB)Hard cap on a single lisp_debug response (raised to a 4 KiB floor if set lower); oversized responses are truncated and flagged.

The debug ring is also byte-bounded internally: individual records are summarized above 256 KiB, and the in-memory ring is capped at 8 MiB of stored record data before oldest records are evicted. These internal caps are independent of the response-size cap above.

--trace-dir and --turn-log-dir are separate on purpose. Trace files are per-request MCP debug envelopes. The turn log is the cross-session record used by PtcRunner.TraceLog.Analyzer and the log/ introspection prelude: it records accepted session eval attempts with the client-visible ptcs_... session id, monotonic attempt number, committed turn counter, status, result preview, credential-free tool-call summaries, and session-level failure/limit reasons. Owner mismatches, stale request ids, expiry races, and aborted evals do not emit turn events because no accepted session work can be attributed.

Streamable HTTP flags

HTTP mode is opt-in. Without --http, the release starts exactly as a stdio MCP server. With --http, the process starts a Streamable HTTP listener and does not attach stdio. See mcp-server-http-deployment.md for the deployment runbook.

FlagEnv varDefaultMeaning
--httpPTC_RUNNER_MCP_HTTPfalseEnable the HTTP listener.
--http-hostPTC_RUNNER_MCP_HTTP_HOST127.0.0.1Bind IP address or localhost. Non-loopback binds always require auth.
--http-portPTC_RUNNER_MCP_HTTP_PORT7332Bind port.
--http-pathPTC_RUNNER_MCP_HTTP_PATH/mcpStreamable HTTP MCP endpoint. Must differ from /health, /ready, and --http-metrics-path.
--http-auth-tokenPTC_RUNNER_MCP_HTTP_AUTH_TOKENunsetStatic bearer token. Must be at least 32 characters; generate it from a CSPRNG.
--http-disable-authPTC_RUNNER_MCP_HTTP_DISABLE_AUTHfalseDisable bearer auth. Only permitted on explicit loopback binds; cannot be combined with --http-allow-unsafe-network.
--http-allowed-originPTC_RUNNER_MCP_HTTP_ALLOWED_ORIGINunsetBrowser Origin allow-list. May be repeated or comma-separated. This is a DNS-rebinding check, not full CORS support.
--http-request-timeout-msPTC_RUNNER_MCP_HTTP_REQUEST_TIMEOUT_MS15000HTTP request read timeout.
--http-shutdown-grace-msPTC_RUNNER_MCP_HTTP_SHUTDOWN_GRACE_MS10000Application-stop drain window before in-flight workers are cancelled.
--http-max-body-bytesPTC_RUNNER_MCP_HTTP_MAX_BODY_BYTES--max-frame-bytesHTTP request body cap.
--http-session-ttl-msPTC_RUNNER_MCP_HTTP_SESSION_TTL_MS3600000Absolute HTTP protocol-session lifetime.
--http-session-idle-timeout-msPTC_RUNNER_MCP_HTTP_SESSION_IDLE_TIMEOUT_MS900000Idle timeout for HTTP protocol sessions.
--http-max-sessionsPTC_RUNNER_MCP_HTTP_MAX_SESSIONS256Global HTTP protocol-session cap.
--http-max-sessions-per-ownerPTC_RUNNER_MCP_HTTP_MAX_SESSIONS_PER_OWNER32Per-owner HTTP protocol-session cap. In single-token v1 every client shares one owner.
--http-max-in-flight-per-sessionPTC_RUNNER_MCP_HTTP_MAX_IN_FLIGHT_PER_SESSION4Non-queueing cap for executing requests in one HTTP protocol session.
--http-allow-unsafe-networkPTC_RUNNER_MCP_HTTP_ALLOW_UNSAFE_NETWORKfalseAllows non-loopback bind addresses (network-binding gate only; does not affect auth requirements).
--http-metricsPTC_RUNNER_MCP_HTTP_METRICSfalseReserved for the Prometheus endpoint follow-up; core telemetry is emitted regardless.
--http-metrics-pathPTC_RUNNER_MCP_HTTP_METRICS_PATH/metricsReserved metrics path; must not collide with HTTP control paths.
--http-instance-labelPTC_RUNNER_MCP_HTTP_INSTANCE_LABELhostnameStable instance label stamped into HTTP logs, telemetry, and trace metadata.

HTTP emits sanitized telemetry under [:ptc_lisp, :http, ...] and logs request stop lines to stderr. Raw bearer tokens and raw MCP-Session-Id values are not logged.

When the HTTP listener is bound to loopback, /mcp also requires a loopback Host/authority value. This lets non-browser clients omit Origin while still rejecting DNS-rebinding requests that arrive with a public attacker-controlled host. POST requests with a present Content-Type must use application/json or a +json media type.

Response profiles

lisp_eval and lisp_session_eval render their eval results according to a boot-time response profile (--response-profile). The default is slim: optimized for the model consuming the tool result, not for an operator reading a trace. Session utility tools such as lisp_session_start, lisp_session_inspect, and lisp_session_forget keep structured responses in all profiles.

Profilecontent[0].textstructuredContentoutputSchema advertisedObservability fields
slim (default)concise human-readable text / the valueno for eval toolsomitted everywhere — no ptc_metrics, no upstream_calls, no empty prints/feedback, no default truncated
structuredconcise textcompact {status, result, …} (session eval also keeps session and memory.changed_keys; errors add reason/message/feedback and compact upstream failure summaries when useful)yes (compact)ptc_metrics omitted; full upstream_calls omitted, so diagnostics stay out of the model-facing path
debugthe result, mirroredfull payload (also mirrored as text)yes (full)full ptc_metrics, full upstream_calls (all entries with timings/byte counts), and the rest of the verbose payload

For lisp_session_eval, normal slim/structured responses expose only the next-step contract: result text, compact session metadata, and changed binding names. Binding values, full upstream-call ledgers, and ptc_metrics are retained for explicit diagnostics instead of being echoed in every eval response.

--debug-tool implies --response-profile debug unless a profile is set explicitly. If you combine --debug-tool --response-profile slim, the client-facing response stays slim while the lisp_debug recorder still gets the full pre-slim payload internally for both stateless and session evals.

Client-facing output limits

MCP tool results are additionally shaped by profile-derived output limits before they are returned to the client. These limits are not separate CLI flags yet; they are intentionally tied to --response-profile.

ProfilePrint outputvalidated exact valueFinal envelope guard
slimmax 20 entries / 8 KiB encodedalways omitted; validated_preview, validated_bytes, and output_truncated are used when validation was requested32 KiB; may fall back to text-only
structuredmax 50 entries / 16 KiB encodedkept only when JSON-encoded value is ≤ 32 KiB; otherwise omitted with preview/byte metadata96 KiB; preserves minimal structuredContent on fallback
debugmax 200 entries / 64 KiB encodedkept only when JSON-encoded value is ≤ 128 KiB; otherwise omitted with preview/byte metadata512 KiB; preserves minimal structuredContent on fallback

validated is exact-or-absent. The server does not put partial values under validated; when the exact value is omitted, clients should look for validated_preview, validated_bytes, validated_preview_truncated, truncated, and output_truncated. feedback is also capped by profile (8 KiB / 16 KiB / 64 KiB). The final envelope guard is a last resort: it drops heavy optional fields and, for structured / debug, keeps machine-readable structuredContent with at least status, truncated, and output_truncated.

Why slim by default — wire cost. Measured by the local payload bench (drives a real @modelcontextprotocol/server-filesystem upstream; bytes ÷ 4 ≈ tokens; deterministic frame-byte counting, not LLM authoring cost):

Per lisp_eval callslimstructureddebugnative MCP, direct
read one file, return it whole~67 t~123 t~873 t~105 t
return the first line of 3 files (1 program vs 3 round-trips)~36 t~60 t~924 t~284 t
return one matched line out of a file~29 t~46 t~790 t~105 t

slim is approximately 13–28x smaller than debug per call — debug's mirrored payload + ptc_metrics + upstream_calls is a roughly fixed ~800–950-token tax regardless of result size, which is exactly why it's opt-in (--debug-tool). Versus calling the upstream MCP tool directly, slim wins whenever the program collapses several calls into one and/or filters the result down (here: ~8x on the 3-file case, 1 round-trip instead of 3; ~4x on the one-line grep), and is about break-even for a single verbatim pass-through. The one-time tools/list ("cold") cost is comparable to a native server's (~2.7 K vs ~3.1 K tokens here); debug adds ~1.2 K tokens of outputSchema there. These ratios are illustrative — actual savings scale with payload size and how much the program reduces it; see aggregator-mode.md for the honest framing of what the server can and cannot measure, and re-run the bench against your own fixtures.

Catalog modes

The --catalog-mode flag (env: PTC_RUNNER_MCP_CATALOG_MODE) controls how upstream tools are exposed. Default is auto.

ModeDescription
inlineA synthetic discovery snapshot inlined in lisp_eval / lisp_session_eval descriptions: server summaries, compact dir name/description lists, and one doc example. Best for small fleets.
lazyConfigured server names plus front-loaded discovery guidance; tools discovered at runtime via REPL discovery forms. Best for large fleets or cost-conscious setups.
autoInline when ≤ --catalog-inline-max-tools (8) and the synthetic discovery snapshot fits within --catalog-inline-max-chars (800); lazy otherwise. Optional prose is capped/dropped before switching to lazy mode.

In lazy (or auto-resolved-lazy) mode, programs discover tools via PTC-Lisp REPL discovery forms that run inside lisp_eval — no extra MCP tool calls:

FormPurpose
(tool/servers)All servers with tool counts and load status
(apropos "query" {:limit 8})Cross-server lexical search returning server.tool - description strings
(dir "server" {:limit 50})Tool names and descriptions for one server
(doc "server/tool")Detailed args/result description with required args and call example
(meta "server/tool")Structured tool metadata and schemas

Discovery forms have a separate budget from upstream calls: --max-catalog-ops-per-program (default 25) and --max-catalog-result-bytes (default 256 KiB).

FlagEnv varDefaultMeaning
--catalog-modePTC_RUNNER_MCP_CATALOG_MODEautoauto | inline | lazy
--catalog-inline-max-charsPTC_RUNNER_MCP_CATALOG_INLINE_MAX_CHARS800Auto→lazy threshold for the rendered synthetic discovery snapshot
--catalog-inline-max-toolsPTC_RUNNER_MCP_CATALOG_INLINE_MAX_TOOLS8Auto→lazy threshold (tool count)
--max-catalog-ops-per-programPTC_RUNNER_MCP_MAX_CATALOG_OPS_PER_PROGRAM25Discovery call budget per program
--max-catalog-result-bytesPTC_RUNNER_MCP_MAX_CATALOG_RESULT_BYTES262144 (256 KiB)Per-discovery-result cap

The MCP server uses the root upstream runtime machinery in frozen snapshot mode, while the server owns deployment selection and MCP presentation. At boot, ptc_runner_mcp translates its CLI/env flags into PtcRunner.Upstream.Runtime options, starts the selected root runtime as a supervised child, and registers deployment secrets with the MCP-side redaction ETS. Configured MCP stdio/http client upstreams are started and listed during server boot, and the scrubbed root snapshot is reused for tools/list. Root mix ptc.repl uses the same upstream config format but defaults to live snapshot mode, where MCP client startup/listing is attempted on discovery or call.

Aggregator-mode flags

These come into effect when at least one upstream is configured. The first two override the v1 1 s / 10 MB defaults to be more realistic for programs that orchestrate real subprocess upstreams. See aggregator-mode.md for the conceptual reference (PTC-Lisp authoring against tool/call, catalog format, error model, example programs).

FlagEnv varDefault (aggregator)Meaning
--upstreams-configPTC_RUNNER_MCP_UPSTREAMS(XDG default)Path to upstreams JSON. Aggregator mode is enabled iff at least one upstream is configured.
--program-timeout-msPTC_RUNNER_MCP_PROGRAM_TIMEOUT_MS10_000 (10 s)Outer wall-clock cap on the PTC-Lisp program (replaces v1's 1 s).
--program-memory-limit-bytesPTC_RUNNER_MCP_PROGRAM_MEMORY_LIMIT_BYTES100 * 1024 * 1024 (100 MB)Sandbox heap cap (replaces v1's 10 MB).
--upstream-call-timeout-msPTC_RUNNER_MCP_UPSTREAM_CALL_TIMEOUT_MS5_000 (5 s)Per-upstream-call wall-clock cap. Exceeded → {:ok false :reason :timeout :message ...} + entry with reason timeout.
--max-upstream-response-bytesPTC_RUNNER_MCP_MAX_UPSTREAM_RESPONSE_BYTES2 * 1024 * 1024 (2 MB)Per-response size cap, enforced pre-decode. Exceeded → {:ok false :reason :response_too_large :message ...} + entry with reason response_too_large.
--max-upstream-calls-per-programPTC_RUNNER_MCP_MAX_UPSTREAM_CALLS_PER_PROGRAM50Total tool/call budget per program. Exceeded → {:ok false :reason :cap_exhausted :message ...} + entry with reason cap_exhausted. Stops pmap over an unbounded list from runaway-firing.
--aggregator-read-onlyPTC_RUNNER_MCP_AGGREGATOR_READ_ONLYfalseAdvertise aggregator mode as read-only/non-destructive for clients like Codex when upstreams enforce read-only behavior.

CLI flag wins over env var; aggregator-mode defaults only apply when no explicit value is given.

Upstream Config Format

The upstream JSON format is owned by the root ptc_runner upstream runtime and shared by mix ptc.repl and ptc_runner_mcp. The MCP server keeps its own flag/env names, including PTC_RUNNER_MCP_UPSTREAMS, because deployment selection is server-owned, but the selected config is parsed by root upstream modules and translated into root runtime options at boot. MCP-local config remains for MCP presentation concerns such as response profiles, sessions, debug/trace, HTTP transport, agentic mode, and server-side redaction. See upstream-runtime.md for the root REPL entrypoint and snapshot-mode behavior.

Use the explicit root transport names in new configs:

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

See aggregator-mode.md for complete examples, credential emitters, static-header restrictions, and the tool/call authoring model.

OpenAPI Upstreams

An upstream entry with "transport": "openapi" exposes a curated set of read-only JSON GET operations through the same tool/call path as MCP upstreams. Required fields:

  • base_url: HTTPS origin used for all operation calls.
  • exactly one of schema_file or schema_url: OpenAPI schema source.
  • include_operations: non-empty list of OpenAPI operationId strings to expose.

Optional fields include auth, static_headers, operation_overrides, request_timeout_ms, connect_timeout_ms, max_response_bytes, and schema_max_bytes. schema_file is the recommended production shape; schema_url is fetched during upstream startup and can delay boot up to its request timeout if the schema host hangs.

See docs/examples/observatory-openapi-upstreams.json for a production-shaped Observatory config. The matching test fixture schema lives at mcp_server/test/fixtures/openapi/observatory.openapi.json.

Tracing

Setting --trace-dir /tmp/ptc-traces writes one JSONL file per tools/call invocation under that directory. Each file contains the lifecycle telemetry events (lisp.execute.start, lisp.execute.success / lisp.execute.fail, plus per-tool-call rows when relevant) emitted by :ptc_runner. Tracing is opt-in and OFF by default — there is zero overhead when --trace-dir is unset.

--trace-payloads full includes the verbatim program, context, and rendered result bytes; summary (the default when tracing is on) records sizes and SHA-256 digests only. Pick summary unless you are actively debugging a specific call.

For local evaluation of aggregator benefits, run with:

--trace-dir /tmp/ptc-traces --trace-payloads full

Then inspect the JSONL trace file to see the generated PTC-Lisp program, program_bytes, total call duration, and result size. In debug responses, or through lisp_debug records when enabled, upstream_calls records each upstream call's server, tool, status, reason on failure, and duration. To estimate token savings, compare:

  • aggregator tools/list bytes vs the sum of native upstream tools/list bytes;
  • aggregator final result bytes vs the sum of native upstream raw result bytes.

Use --trace-payloads full only for local debugging or measurement; it records source programs and payload values. Use summary or none for normal operation.

Reading traces without writing code

With --trace-dir set you do not need a bespoke trace reader: point a generic filesystem MCP server (e.g. @modelcontextprotocol/server-filesystem) at the trace directory and let the client read the raw per-call JSONL. The zero-code escape hatch — fine for ad-hoc digging, but lisp_debug (see mcp-debug.md) is the purpose-built interface, and ptc_viewer (mix ptc.viewer in the repo) is the human-facing web UI for the same trace files.

Lifecycle commands

The release binary defaults RELEASE_DISTRIBUTION=none so MCP clients can run multiple stdio subprocesses concurrently without Erlang node-name collisions:

ptc_runner_mcp start      # foreground, stdio attached (what MCP clients use)
ptc_runner_mcp version    # print "ptc_runner_mcp <version>"
ptc_runner_mcp eval "..."  # run an expression in a one-shot VM

For remote IEx debugging, start the process with distribution enabled and a unique node name, then attach with the same settings:

RELEASE_DISTRIBUTION=sname RELEASE_NODE=ptc_runner_mcp_debug_1 ptc_runner_mcp start
RELEASE_DISTRIBUTION=sname RELEASE_NODE=ptc_runner_mcp_debug_1 ptc_runner_mcp remote