Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,70 @@ from their usual local locations.
- A dashboard at `http://localhost:4600`
- Token, cost, model, project, runtime, and session summaries
- Source-aware capture across local AI coding tools
- MCP tools for querying sessions and usage from other agents
- MCP tools for querying sessions, usage, and trace annotations from other
agents
- Managed local ClickHouse storage, with optional direct ClickHouse
configuration for trusted local or private-network deployments
- Privacy controls for redaction, hashing, capture filters, and offline operation

## Trace Annotations

Beacon annotations can mark a whole session, a transcript message, or a
specific event. Open a session transcript, use **Annotate session** for
session-level notes, or use the inline annotation controls in chat and timeline
views to annotate one message or event. Annotation records include structured
fields for category, outcome, quality score, confidence, labels, follow-up
state, and free-form notes.

Agents can create and maintain the same records through Beacon MCP with
`create_annotation`, `update_annotation`, `list_annotations`, `get_annotation`,
and `delete_annotation`. MCP-created annotations use `source: "mcp"` and
`author_type: "agent"`; updates preserve existing provenance. Tools support
`session_id`, `message_id`, `event_id`, or an `open_ref` returned by Beacon
search/open tools.

## Annotated Trace Datasets

The local JSON API exposes annotated traces directly for review, evaluation,
fine-tuning, and skill-development datasets.

List annotated sessions and their annotated targets:

```bash
curl 'http://localhost:4600/api/annotations/traces?label=dataset:eval&limit=25'
```

Export dataset-ready traces with session metadata, ordered event context, and
annotation records:

```bash
curl 'http://localhost:4600/api/annotations/export?label=dataset:eval&event_limit=2000'
```

Discovery and export responses are paginated with `limit`, `offset`, and
`has_more`. Continue increasing `offset` until `has_more` is false when
collecting a complete dataset:

```bash
offset=0
while :; do
curl -fsS "http://localhost:4600/api/annotations/export?label=dataset:eval&event_limit=2000&limit=200&offset=${offset}" > "annotated-traces-${offset}.json"
jq -e '.has_more' "annotated-traces-${offset}.json" >/dev/null || break
offset=$((offset + 200))
done
```

Each exported trace reports `event_truncated`, and the response includes
`warnings` when `event_limit` clipped ordered event context for a session.

Both endpoints return versioned JSON schema markers:
`beacon.annotated_traces.index.v1` and
`beacon.annotated_traces.export.v1`. Supported filters include `session_id`,
`event_uid`, `target_type`, `label`, `author_type`, `source`, `category`,
`outcome`, `needs_followup`, `include_deleted`, and the usual Beacon scope
filters (`source_name`, `source_names`, `runtime`, `runtimes`, `project_key`,
`project_keys`).

Check the local setup:

```bash
Expand Down
16 changes: 9 additions & 7 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,19 +214,20 @@ Live update paths use explicit buffering rules:
A four-slot semaphore bounds async inserts; saturated query-log attempts are
counted and logged at debug level without affecting search results.

### 7. MCP read path
### 7. MCP tool path

`beacon mcp` opens ClickHouse in read-only mode and starts `internal/mcp.Server`
over stdin/stdout JSON-RPC. The server returns MCP initialization instructions
that tell clients to search first, open returned event IDs for transcript
`beacon mcp` opens the Beacon store and starts `internal/mcp.Server` over
stdin/stdout JSON-RPC. The server returns MCP initialization instructions that
tell clients to search first, open returned event or message IDs for transcript
context, and treat captured data as historical context rather than current
workspace truth. It exposes:

- `search_sessions`, backed by `internal/search.Searcher` and the precomputed
search tables
- `open`, backed by a window query over `activity_events` for one returned
`event_id` plus surrounding session context
event or message ID plus surrounding session context
- `list_sessions`, backed by `session_projection`
- annotation create, list, update, and delete tools backed by `trace_annotations`

Tool input schemas are kept compatible with OpenAI's MCP/function import path:
the top-level schema is always an object and does not use top-level union or
Expand All @@ -235,8 +236,9 @@ The advertised schema should stay simple and match the IDs returned by Beacon
tools.

The MCP server uses the same database tables as the web UI. It does not run
capture, migrations, or writes. MCP searches skip query logging so the tool
surface remains read-only.
capture, but it opens the writable store so annotation tools can persist notes;
startup may run schema migrations through the normal store open path. MCP
searches still skip query logging.

## Ownership boundaries

Expand Down
171 changes: 159 additions & 12 deletions docs/mcp.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
# MCP Integration

Beacon includes a read-only stdio MCP server for coding agents and other MCP
clients. The MCP server lets agents search prior local Beacon sessions while
they stay inside their normal workflow.
Beacon includes a stdio MCP server for coding agents and other MCP clients. The
MCP server lets agents search prior local Beacon sessions, inspect context, read
usage summaries, and annotate traces while they stay inside their normal
workflow.

Run Beacon locally with `beacon up` and configure the MCP client to launch
`beacon mcp`.

## How It Works

`beacon mcp` is launched by the MCP client over stdin/stdout JSON-RPC. It opens
Beacon's configured ClickHouse database read-only.
Beacon's configured ClickHouse database.

Beacon exposes four tools:
Beacon exposes these read tools:

- `search_sessions` searches the precomputed activity index and returns session
and event IDs plus `open_ref` values.
Expand All @@ -22,12 +23,27 @@ Beacon exposes four tools:
values.
- `usage_summary` aggregates event-level token usage for exact windows and
optional top-contributor groupings.

The server does not run capture, migrations, or writes. MCP searches also skip
Beacon's query log, so the tool surface remains read-only. Beacon returns MCP
server instructions during initialization so clients prefer the search-then-open
workflow and treat captured transcripts as historical context that should be
verified against the current workspace before acting.
- `list_annotations` lists Beacon annotations for a session, message, event, or
returned `open_ref`.
- `get_annotation` reads one annotation by ID after verifying its target is in
scope.

Beacon exposes these write tools:

- `create_annotation` creates an agent annotation on a session, message, or
event.
- `update_annotation` updates an existing annotation after verifying the target
remains in scope.
- `delete_annotation` soft-deletes one annotation after verifying the target
remains in scope.

The server does not run capture. It opens the writable Beacon store so annotation
tools can persist notes, which means startup may run schema migrations on the
configured database. MCP searches skip Beacon's query log, and annotation write
tools are explicitly advertised as non-read-only in their tool annotations.
Beacon returns MCP server instructions during initialization so clients prefer
the search-then-open workflow and treat captured transcripts as historical
context that should be verified against the current workspace before acting.

## Start Beacon

Expand Down Expand Up @@ -212,5 +228,136 @@ summary from a shell; see [usage summaries](usage.md).
`open` accepts `event_id`, returned `open_ref` objects, or `session_id` with
`anchor: "latest"`. Returned `open_ref` values carry the effective scope from
the tool result that produced them; `open` intersects that scope with any
explicit scope filters and the token's auth scope. Do not pass legacy `id` or
explicit scope filters and the token's auth scope. Do not pass `id` or
`event_uid` arguments.

## Annotation Tools

Annotation tools share the same scope filters as search tools. Message targets
require a message event and are returned with both `event_id` and `message_id`;
event targets use `event_id`; session targets use `session_id`. Use
`message_id` or the message `open_ref` returned by message search/open results
when you want a message-level annotation; event `open_ref` values create event
annotations unless the target type is explicit.

`create_annotation`:

```json
{
"target_type": "message",
"session_id": null,
"message_id": "message:abc123",
"event_id": null,
"open_ref": null,
"author_id": "agent-run-42",
"author_name": "Reviewer Agent",
"category": "quality",
"outcome": "needs_fix",
"quality_score": 2,
"confidence": 85,
"needs_followup": true,
"labels": ["dataset:eval", "rubric:correctness"],
"note": "The assistant missed the user's explicit constraint.",
"metadata_json": "{\"rubric_version\":\"2026-06\"}",
"source_name": null,
"source_names": null,
"runtime": null,
"runtimes": null,
"project_key": null,
"project_keys": null
}
```

`target_type` may be `session`, `message`, or `event`. If omitted or `null`,
Beacon infers it from `message_id`, `event_id`, `session_id`, or `open_ref`.
For message annotations, prefer `message_id` or use the message `open_ref`
returned for message search/open results. Event `open_ref` values infer event
targets unless `target_type: "message"` is explicit.
`metadata_json` must be a JSON object encoded as a string when provided.
Successful creates return schema `beacon.mcp.create_annotation.v1`, the
annotation record, and an `open_ref` for the target.

`update_annotation`:

```json
{
"annotation_id": "ann_abc123",
"category": "quality",
"outcome": "fixed",
"quality_score": 4,
"confidence": 90,
"needs_followup": false,
"labels": ["dataset:train"],
"note": "Updated after verifying the corrected trace.",
"metadata_json": "{\"rubric_version\":\"2026-06\"}",
"source_name": null,
"source_names": null,
"runtime": null,
"runtimes": null,
"project_key": null,
"project_keys": null
}
```

Updates return schema `beacon.mcp.update_annotation.v1`. Updates change content
fields and preserve the annotation's existing author and source attribution.

`list_annotations`:

```json
{
"target_type": null,
"session_id": "session:abc123",
"message_id": null,
"event_id": null,
"open_ref": null,
"include_deleted": false,
"limit": 50,
"offset": 0,
"source_name": null,
"source_names": null,
"runtime": null,
"runtimes": null,
"project_key": null,
"project_keys": null
}
```

For a session ID with no explicit `target_type`, Beacon lists all visible
annotations in that session, including session, message, and event annotations.
Use `"target_type": "session"` only when you want session-level annotations and
not message or event annotations.
Responses use schema `beacon.mcp.list_annotations.v1` with `metadata.limit`,
`metadata.offset`, `metadata.result_count`, and `metadata.result_complete`.

`get_annotation`:

```json
{
"annotation_id": "ann_abc123",
"include_deleted": false,
"source_name": null,
"source_names": null,
"runtime": null,
"runtimes": null,
"project_key": null,
"project_keys": null
}
```

`delete_annotation`:

```json
{
"annotation_id": "ann_abc123",
"source_name": null,
"source_names": null,
"runtime": null,
"runtimes": null,
"project_key": null,
"project_keys": null
}
```

Deletes are soft deletes and return schema `beacon.mcp.delete_annotation.v1`
with `status: "deleted"`.
23 changes: 14 additions & 9 deletions docs/privacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ database as sensitive local data even after redaction.

## Data Beacon stores

Beacon can store the following content from configured capture sources:
Beacon can store the following local content:

- raw source records from agent session files;
- normalized prompts, responses, reasoning summaries, tool calls, tool results,
Expand All @@ -25,6 +25,10 @@ Beacon can store the following content from configured capture sources:
- session and analytics projections derived from captured events;
- search query log rows containing search text, normalized terms, result counts,
and timing data;
- trace annotation records created through the dashboard, REST API, or MCP tools,
including author/source metadata, target IDs, categories, outcomes, labels,
quality/confidence values, notes, JSON metadata, follow-up flags, status, and
soft-delete timestamps;
- capture checkpoints and capture errors used to replay files safely.

The ClickHouse schema and table ownership are documented in
Expand Down Expand Up @@ -55,8 +59,9 @@ The web dashboard exposes captured session summaries, transcripts, search
results, tool payloads, metrics, and recent activity through local HTTP routes.
Anyone who can reach the Beacon web server can inspect that data.

The MCP server exposes the same local database through read-only tools:
`search_sessions`, `open`, `list_sessions`, and `usage_summary`. Those tools can
The MCP server exposes the same local database through query tools such as
`search_sessions`, `open`, `list_sessions`, and `usage_summary`, plus writable
annotation tools for marking sessions, messages, and events. Query tools can
return transcript context, session summaries, source/runtime/project metadata,
token-usage aggregates, and working directories. MCP clients should be
configured only for trusted agent environments, especially when pointing Beacon
Expand All @@ -74,12 +79,12 @@ Beacon sets dashboard security headers including `Content-Security-Policy`,
JavaScript execution. Dashboard controls are wired through external scripts and
server-rendered captured content is escaped by default.

The optional `POST /api/mcp` route exposes the same read-only MCP tools as the
local dashboard server and inherits the dashboard server's local-trust boundary.
If Beacon is exposed beyond loopback, put it behind an external authenticated
proxy or equivalent network control. If Beacon adds browser-driven mutation
routes such as reset or admin settings, those routes should require same-origin
proof or CSRF protection and must not mutate state via GET.
The optional `POST /api/mcp` route exposes the same MCP tools as the local
dashboard server and inherits the dashboard server's local-trust boundary. If
Beacon is exposed beyond loopback, put it behind an external authenticated proxy
or equivalent network control. Browser-driven mutation routes reject explicit
cross-site browser signals, require JSON content types for JSON writes, and must
not mutate state via GET.

## Retention policy

Expand Down
8 changes: 5 additions & 3 deletions docs/production.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This guide covers running Beacon as a single-machine service. Beacon captures
local AI-agent activity, stores it in ClickHouse, serves the dashboard on the
same host, and exposes read-only MCP over local stdio.
same host, and exposes MCP over local stdio.

If you expose Beacon outside loopback, put it behind infrastructure you control
and authenticate that external access before traffic reaches Beacon.
Expand Down Expand Up @@ -147,8 +147,10 @@ Configure the client to launch Beacon over stdio:
beacon mcp
```

The MCP server opens ClickHouse read-only and does not run migrations or writes.
For details, see [MCP Integration](mcp.md).
The MCP server does not run capture, but it opens the writable Beacon store so
annotation tools can persist notes. Startup may run schema migrations on the
configured database, matching `beacon up`. For details, see
[MCP Integration](mcp.md).

## Service Managers

Expand Down
Loading
Loading