Skip to main content
mcpeye has four stages: capture, ingest, sessionize, and summarize. The trick that makes it cheap is that intent is captured by the agent itself — there is no LLM on the hot path of a tool call.
1

Capture — the SDK injects mcpeyeIntent

When the SDK wraps your MCP server, it merges one optional string parameter, mcpeyeIntent, into every tool’s input schema. The agent fills it in as it calls the tool, explaining in its own words why it’s calling and any blocker the user hit.Because the agent is already reasoning to choose the tool, self-reporting intent costs essentially nothing — no extra LLM call per tool use. The SDK records the call (tool name, arguments, result, error, intent, duration) and redacts obvious secrets before anything leaves your process.
2

Ingest — batched events hit the API

The SDK ships captured calls to the ingest API (API_PORT 3001) as batched IngestPayloads, authenticated with MCPEYE_INGEST_SECRET. The API validates each payload and writes raw tool calls to Postgres. This is a plain write path — fast, no model in sight.
3

Sessionize — calls become sessions

A user’s tool calls are grouped into sessions by identity and an inactivity window. A session is the unit of intent: a coherent run of calls aimed at one user goal. This is what turns scattered log lines into something you can read as a transcript.
4

Summarize — the worker runs the LLM, off the hot path

The summarizer worker (BullMQ on Redis) picks up sessions and makes one LLM call per session — using your ANTHROPIC_API_KEY, with a small default model — to produce a SessionSummary: a one-line intent, an outcome (success / partial / failed), the attemptedButFailed asks, and any missingCapability.On a schedule it then clusters those summaries across all sessions in a window into the GapReport you read in the dashboard. The LLM only ever sees aggregate work, never per-call traffic — so spend is bounded and predictable.

The data flow at a glance

agent → [ SDK wraps server, injects mcpeyeIntent ]
      → ingest API (:3001, MCPEYE_INGEST_SECRET) → Postgres (raw tool calls)
      → sessionize (by user + time window)
      → worker (BullMQ/Redis): 1 LLM call/session → SessionSummary
      → cluster summaries → GapReport → dashboard (:3000)

Why this design

Cheap by construction

Intent is free on the hot path because the agent self-reports. The LLM runs only in the worker, on sessions and reports — not on every call.

Self-hostable end to end

Every stage runs in your stack. The only outbound call is the worker to your chosen LLM, with your key.

What the report shows — and can't

The Intent Gap Report and its honest server-side ceiling.