# @lensmcp/protocol-types

> The shared event protocol for LensMCP — Zod schemas and inferred TypeScript types for the events, trace nodes, edges, and resources that flow between producers and consumers.

LensMCP is an observability lens for coding agents. This package is the **wire contract** that keeps every part of the system in sync: a single set of [Zod](https://zod.dev) schemas (and the TypeScript types inferred from them) describing the events emitted by instrumentation, the trace graph (nodes + edges) those events build up, the per-domain attribute shapes, and the MCP resources consumers read.

Because the schemas and types are derived from the same definitions, producers (browser/React, Node/Nest taps, the gateway) and consumers (`@lensmcp/core`, the MCP server, the dashboard) share one source of truth — emit-side validation and read-side typing never drift apart.

## Install

```bash
yarn add @lensmcp/protocol-types
```

Requires Node `>=18`. `zod` is a runtime dependency.

## Usage

Validate an event on the producer side, and type it on the consumer side, from the same schema:

```ts
import {
  BaseEventSchema,
  type BaseEvent,
  type EventSource,
} from '@lensmcp/protocol-types';

// Producer: parse/validate before emitting (throws on bad shape).
const event = BaseEventSchema.parse({
  id: 'evt_01',
  sessionId: 'sess_abc',
  timestamp: Date.now(),
  source: 'react',
  category: 'render',
  severity: 'warning',
  context: { sessionId: 'sess_abc', route: '/dashboard' },
  fingerprint: 'render:Slow:/dashboard',
  title: 'Slow render',
});

// Consumer: the inferred type is the contract.
function handle(e: BaseEvent) {
  const from: EventSource = e.source;
  console.log(from, e.category, e.severity);
}
```

Use `.safeParse()` when you want to branch on validity instead of throwing:

```ts
const result = BaseEventSchema.safeParse(input);
if (!result.success) {
  // result.error is a ZodError
}
```

Every schema follows the `XxxSchema` (value) + `Xxx` (inferred type) naming convention, so you can import whichever you need.

## What's in here

### Event (`event.ts`)

- **`BaseEventSchema` / `BaseEvent`** — the common envelope on every emitted event: `id`, `sessionId`, `timestamp`, `source`, `category`, `severity`, `context`, `fingerprint`, `title`, plus optional `message`, `location`, `relatedFiles`, `relatedUrls`, and `raw`.
- **`EventSourceSchema` / `EventSource`** — where the event came from:
  `nx`, `vite`, `typescript`, `eslint`, `rollup`, `client-runtime`, `chrome`, `react`, `valtio`, `nestjs`, `nextjs`, `db`, `redis`, `queue`, `memory`, `visual`, `perf`, `security`, `gateway`, `external`.
- **`EventCategorySchema` / `EventCategory`** — what kind of signal it is:
  `build`, `lint`, `typecheck`, `test`, `runtime`, `render`, `visual`, `trace`, `state`, `network`, `backend`, `db`, `memory`, `performance`, `security`, `deps`, `cluster`.
- **`SeveritySchema` / `Severity`** — `debug`, `info`, `warning`, `error`, `fatal`.

### Trace context (`context.ts`)

- **`TraceContextSchema` / `TraceContext`** — the correlation envelope carried on events and nodes: `sessionId` plus optional browser identifiers (`browserContextId`, `tabId`, `frameId`, `route`, `url`), flow identifiers (`flowId`, `originType`, `originNodeId`, `causedByNodeId`), request identifiers (`requestId`, `traceparent`), and hashed actor identifiers (`userActionId`, `userIdHash`, `tenantIdHash`).
- **`FlowOriginTypeSchema` / `FlowOriginType`** — what kicked off a flow (e.g. `user-click`, `user-input`, `keyboard`, `route-load`, `effect`, `memo-recompute`, `timer`, `raf`, `idle-callback`, `websocket-message`, `broadcast-channel`, `post-message`, `storage-event`, `service-worker-message`, `media-query-change`, `visibility-change`, `resize`, `intersection-observer`, `mutation-observer`, `backend-response`, `hmr-update`).

### Trace graph — nodes & edges (`node.ts`, `edge.ts`)

- **`TraceNodeSchema` / `TraceNode`** — a node in the trace graph: identity (`id`, `parentTraceNodeId`, `logicalId`, `instanceId`, `generation`), `type`, `lifecycle`, `context`, timing (`startTime`, `endTime`, `durationMs`), optional `location`, and an open `attributes` record.
- **`TraceNodeTypeSchema` / `TraceNodeType`** — the node taxonomy spanning the browser process tree, React UI, user interaction, network/API, backend (Nest app/module/provider, requests, DB/Redis ops, queue jobs, loops, promises), state, visual, memory, and build/dev events.
- **`LifecycleSchema` / `Lifecycle`** — `created`, `active`, `completed`, `disposed`, `errored`.
- **`TraceEdgeSchema` / `TraceEdge`** — a directed relationship between nodes: `from`, `to`, `axis`, `type`, `timestamp`, optional `attributes`.
- **`EdgeAxisSchema` / `EdgeAxis`** — the relationship dimension: `ownership`, `caused`, `async`, `data`, `render`, `state`, `network`, `backend`, `db`, `visual`, `performance`, `memory`, `lifecycle`.

### Domain attributes (`attributes.ts`)

Typed `attributes` payloads for specific node types, each with its `XxxSchema` + `Xxx` pair:

- **Render** — `RenderAttrs`, `RenderPhase` (`mount` | `update`), and the discriminated `RenderWhy` (props / react-state / context / valtio-path / parent-render / hook-dep-changed / force).
- **Effects & state** — `EffectRunAttrs`, `ValtioUpdateAttrs`.
- **Backend** — `ServerRequestAttrs`, plus `LoopAttrs` / `LoopPattern` (`N+1`, `sequential-await`, `growing-allocation`).
- **Memory** — `MemoryOwnerAttrs`, `MemoryMutationAttrs`, with `MemoryContainerKind` and `MemoryMutationOperation` enums.
- **Visual** — `VisualFrameAttrs` and `VisualViolationAttrs`, plus `Rect`, `VisualFrameCause`, `VisualChangeKind`, `VisualRuleType`, `VisualRuleTiming`, and `VisualViolationSeverity`.

### Source location (`source-location.ts`)

- **`SourceLocationSchema` / `SourceLocation`** — `file` plus optional `line`, `column`, `symbol`, `componentName`, `hookName`. Reused across events, nodes, and resources to point back at code.

### Resources (`resources.ts`)

The MCP-facing read models, all built on a shared envelope:

- **`ResourceEnvelopeSchema` / `ResourceEnvelope`** — the header on every resource JSON (`schemaVersion`, `revision`, optional `$schema` and `updatedAt`).
- **`URI_SCHEMES` / `UriScheme`** — the well-known LensMCP resource URI schemes (each maps 1:1 to a FrontMCP `@App` package): `agent`, `events`, `build`, `lint`, `typecheck`, `test`, `runtime`, `render`, `visual`, `flow`, `story`, `trace`, `graph`, `bundle`, `security`, `perf`, `deps`, `memory`, `browser`, `react`, `valtio`, `nest`, `next`, `process`.
- **`AgentCurrentStatusSchema` / `AgentCurrentStatus`** (`agent://current-status`) — rollup status (`AgentStatusKind`: `starting` | `clean` | `warning` | `failing`), `blocking` / `warnings` items (`AgentBlockingItem`), `suggestedReads`, and per-domain `checks` (`AgentChecks`).
- **`AgentSessionSchema` / `AgentSession`** (`agent://session`) — session capabilities: supported resources/tools/jobs/channels, default subscriptions, transports, host info, and project info.

### DI tokens (`tokens.ts`)

`Symbol`-based dependency-injection tokens for FrontMCP `@Provider` registrations — `SessionToken`, `EventBusToken`, `GraphStoreToken`, `ResourceStoreToken`, `StorageToken` (union type `LensmcpToken`). The interfaces stay abstract here; packages like `@lensmcp/core` ship the concrete implementations.

### Schema version (`schema-version.ts`)

- **`SCHEMA_VERSION`** (currently `1`) and the **`SchemaVersion`** literal type — stamped into `ResourceEnvelope` so consumers can detect protocol drift.

## How it fits

```
producers                         @lensmcp/protocol-types                    consumers
─────────                         ──────────────────────                    ─────────
browser / React tap        ─┐                                          ┌─►  @lensmcp/core
node / NestJS taps         ─┼──►  Zod schemas + inferred types   ──────┼─►  MCP server
gateway                    ─┘     (the wire contract)                  └─►  dashboard
```

Every `@lensmcp` instrumentation library and the gateway validate and emit events against these schemas; `@lensmcp/core` and the MCP server consume them with the matching inferred types. One definition, validated on the way out and typed on the way in — so the protocol can't silently drift between producer and consumer.

---

Part of [LensMCP](https://github.com/kiwiapps-ltd/lensmcp). Apache-2.0.
