trackmcp
Back to directory

Guck MCP

2 stars TypeScriptOthers Updated Mar 17, 2026

Documentation

Guck

Guck is a tiny, MCP-first telemetry store for agentic debugging. It provides

token-efficient log analytics by capturing JSONL telemetry events and exposing

a minimal MCP toolset for fast, filtered queries.

Guck is designed to be:

  • Language-agnostic: emit JSONL from any runtime
  • Filter-first: no default tailing; MCP tools focus on targeted queries
  • Low-friction: small optional SDK, simple `wrap` CLI for stdout/stderr

Install

sh
pnpm add -g @guckdev/cli
# or
npm install -g @guckdev/cli
# or
npx @guckdev/cli

Note: the `guck` command is provided by `@guckdev/cli`. If you already have the

unrelated npm `guck` installed globally, uninstall it first.

If you previously installed `guck-cli`, switch to `@guckdev/cli`.

Quick start

1) Configure MCP (Codex/Claude/Copilot):

json
{
  "mcpServers": {
    "guck": {
      "command": "guck",
      "args": ["mcp"],
      "env": {
        "GUCK_CONFIG_PATH": "/path/to/.guck.json"
      }
    }
  }
}

2) Drop‑in log capture (JS) — use auto‑capture, emit(), or both:

ts
import "@guckdev/sdk/auto";
import { emit } from "@guckdev/sdk";

emit({ message: "hello from app" });

3) Run your app; the MCP client will spawn `guck mcp` and logs are queryable via

`guck.stats` / `guck.search`.

Vite drop-in (dev)

Add the Vite plugin to proxy `/guck/emit` during development:

ts
import { defineConfig } from "vite";
import { guckVitePlugin } from "@guckdev/vite";

export default defineConfig({
  plugins: [guckVitePlugin()],
});

Then point the browser SDK at `/guck/emit`.

Monorepo layout

  • `packages/guck-cli` — CLI (wrap/emit/checkpoint/mcp)
  • `packages/guck-core` — shared config/types/store/redaction
  • `packages/guck-js` — JS SDK
  • `packages/guck-mcp` — MCP server
  • `packages/guck-py` — Python SDK
  • `packages/guck-vite` — Vite dev server plugin
  • `specs` — shared contract fixtures for parity tests

Python SDK (preview)

PyPI install:

sh
pip install guck-sdk

Local dev install:

sh
uv pip install -e packages/guck-py

Usage:

py
from guck import emit

emit({"message": "hello from python"})

Best practice (copy-paste)

1) Add shared config (commit to repo):

`.guck.json`

json
{
  "version": 1,
  "enabled": true,
  "default_service": "api"
}

Optional: add `.guck.local.json` for per-dev overrides (ignored by git).

You can run `guck init` to scaffold `.guck.json`.

2) Add one line to AGENTS.md:

code
When debugging, use Guck telemetry first (guck.stats → guck.search; tail only if asked).

3) Run:

sh
guck wrap --service api --session session-001 -- 
guck mcp

Session vs trace

Guck supports both `session_id` and `trace_id`, but they serve different purposes:

  • `trace_id` is request-scope correlation (a single transaction across services).
  • `session_id` is run-scope correlation (a dev run, test run, or local experiment).

`session_id` is useful even when you already have traces because many events are

not tied to a trace (startup, background jobs, cron tasks, etc.). It also gives

you a simple way to filter a whole dev run without wiring trace propagation.

Example:

sh
export GUCK_SESSION_ID=session-001
guck wrap --service api --session session-001 -- pnpm run dev

Config

Guck reads `.guck.json` from your repo root. If present, `.guck.local.json` is

merged on top for per-dev overrides.

Guck is enabled by default using built-in defaults. Add a `.guck.json` (and

optional `.guck.local.json`) or set `GUCK_CONFIG_PATH` (or `GUCK_CONFIG`) to

point at a config file or repo directory. You can also set `"enabled": false`

inside the config to turn it off explicitly.

For MCP usage across multiple repos, each tool accepts an optional

`config_path` parameter to point at a specific `.guck.json`.

Multi-service or multi-repo tracing (shared store)

To trace across local microservices (or multiple repos), point every service

at the same absolute log directory via `GUCK_DIR`. This creates a single

shared log store that `guck.search` can query across. Use a shared `GUCK_SESSION_ID` to

correlate events and distinct `service` names to separate sources.

Example shared env:

sh
export GUCK_DIR=/path/to/guck/logs
export GUCK_SESSION_ID=session-001
# optional: share a single config across repos
export GUCK_CONFIG_PATH=/path/to/shared/.guck.json

Example shared config:

json
{
  "version": 1,
  "enabled": true,
  "default_service": "api",
  "redaction": {
    "enabled": true,
    "keys": ["authorization","api_key","token","secret","password"],
    "patterns": ["sk-[A-Za-z0-9]{20,}","Bearer\\s+[A-Za-z0-9._-]+"]
  },
  "mcp": { "max_results": 200, "max_output_chars": 20000, "default_lookback_ms": 300000 }
}

Remote backends (CloudWatch/K8s) require optional SDK installs; install only if you use them.

JS SDK auto-capture (stdout/stderr)

The JS SDK can patch `process.stdout` and `process.stderr` to emit Guck events.

Enable it early in your app startup:

ts
import "@guckdev/sdk/auto";
// or
import { installAutoCapture } from "@guckdev/sdk";
installAutoCapture();

Config toggles:

json
{ "sdk": { "enabled": true, "capture_stdout": true, "capture_stderr": true } }

If you're using `guck wrap`, the CLI sets `GUCK_WRAPPED=1` and the SDK

auto-capture intentionally skips to avoid double logging.

Browser SDK (console + errors)

Use a dev server endpoint that accepts `/guck/emit` and writes events to the

local store. In Vite, the `@guckdev/vite` plugin provides this endpoint. For

other stacks, add a small endpoint that forwards payloads to your server-side

`emit()`.

Emit browser events:

ts
import { createBrowserClient } from "@guckdev/browser";

const client = createBrowserClient({
  endpoint: "/guck/emit",
  service: "web",
  sessionId: "session-001",
});

await client.emit({ message: "hello from the browser" });

Auto-capture console output + unhandled errors:

ts
const { stop } = client.installAutoCapture();

console.error("boom");

// call stop() to restore console and listeners (useful in component unmounts/tests)
stop();

Notes:

  • `installAutoCapture()` should usually be called once at app startup; repeated calls will wrap console multiple times.
  • If you install it inside a component or test, call `stop()` on cleanup to avoid duplicate logging.
  • For SPAs, it's fine to call `installAutoCapture()` once in your app entry (e.g. `index.ts`) and never call `stop()`.
  • There is no prebuilt UMD/IIFE bundle yet; for vanilla JS you should use a bundler or a native ESM import.

Environment overrides

  • `GUCK_CONFIG_PATH` — explicit config path (file or repo dir)
  • `GUCK_CONFIG` — alias of `GUCK_CONFIG_PATH`
  • `GUCK_DIR` — store dir override (default: `~/.guck/logs`)
  • `GUCK_ENABLED` — true/false
  • `GUCK_SERVICE` — service name
  • `GUCK_SESSION_ID` — session override
  • `GUCK_RUN_ID` — run id override

Checkpoint

`guck checkpoint` writes a `.guck-checkpoint` file in the root of your

store dir (`GUCK_DIR` or `~/.guck/logs`) containing an epoch millisecond timestamp. When

MCP tools are called without `since`, Guck uses the checkpoint timestamp as

the default time window. You

can also pass `since: "checkpoint"` to explicitly anchor a query to the

checkpoint.

Event schema (JSONL)

Each line in the log is a single JSON event:

json
{
  "id": "uuid",
  "ts": "2026-02-08T18:40:00.123Z",
  "level": "info",
  "type": "log",
  "service": "worker",
  "run_id": "uuid",
  "session_id": "session-123",
  "message": "speaker started",
  "data": { "turnId": 3 },
  "tags": { "env": "local" },
  "trace_id": "...",
  "span_id": "...",
  "source": { "kind": "sdk" }
}

Store layout

By default, Guck writes per-run JSONL files under `~/.guck/logs`:

code
~/.guck/logs///.jsonl

Set `GUCK_DIR` to override the root.

Minimal CLI

Guck’s CLI is intentionally minimal. It exists to capture and serve

telemetry; filtering is MCP-first.

  • `guck init` — create `.guck.json`
  • `guck checkpoint` — write `.guck-checkpoint` epoch timestamp
  • `guck wrap --service --session -- ` — capture stdout/stderr
  • `guck emit --service --session ` — append JSON events from stdin
  • `guck mcp` — start MCP server
  • `guck upgrade [--manager ]` — update the CLI install

MCP tools

Guck exposes these MCP tools (filter-first):

  • `guck.search`
  • `guck.search_batch`
  • `guck.stats`
  • `guck.sessions`
  • `guck.tail` (available, but not default in docs)

Search and tail parameters

`guck.search` and `guck.tail` support additional output and query controls:

  • `query` — boolean search over message only (case-insensitive). Supports `AND`, `OR`, `NOT`, parentheses, and quoted phrases.
  • `contains` — substring search across message/type/session_id/data (unchanged).
  • `format` — `json` (default) or `text`.
  • `fields` — when `format: "json"`, project events to these fields. Dotted paths like `data.rawPeak` are supported.
  • `flatten` — when `format: "json"`, emit dotted field paths as top-level keys (e.g. `"data.rawPeak": 43`).
  • `template` — when `format: "text"`, format each line using tokens like `{ts}|{service}|{message}`. Dotted tokens like `{data.rawPeak}` are supported. Missing tokens become empty strings.
  • `force` — bypass output-size guard and return the full payload.
  • `max_message_chars` — per-message cap; trims the `message` field only.

Output is capped by `mcp.max_output_chars`. If a response would exceed the cap,

the tool returns a warning instead of events/lines unless `force=true`.

Warnings include `avg_message_chars` and `max_message_chars` computed from full, untrimmed messages.

Examples:

json
{ "query": "error AND (db OR timeout)" }
{ "format": "text", "template": "{ts}|{service}|{message}" }
{ "format": "json", "fields": ["ts", "level", "message"] }
{ "format": "json", "fields": ["ts", "data.rawPeak"], "flatten": true }

Batch search:

json
{
  "searches": [
    { "id": "errors", "query": "error", "limit": 50 },
    { "id": "warnings", "levels": ["warn"], "limit": 50, "max_message_chars": 200 }
  ]
}

Recommended minimal output for agents:

json
{ "format": "text", "template": "{ts}|{service}|{message}" }

AI usage guidance

Start with stats, then search, and only tail if needed:

1) `guck.stats` with a narrow time window

2) `guck.search` for relevant types/levels/messages

3) `guck.tail` only when live-streaming is required

This keeps prompts short and avoids flooding the model with irrelevant logs.

Use Guck as a tight loop to avoid log spam and wasted tokens:

1) Scope with `guck.stats` (short time window, service/session).

2) Inspect with `guck.search` for errors/warns or a specific boundary.

3) Hypothesize the failing stage or component.

4) Instrument only the boundary (entry/exit, inputs/outputs).

5) Re-run and re-query the same narrow window.

This keeps investigations focused while still enabling deep, iterative debugging.

Redaction

Guck applies redaction on write and on read using configured key names

and regex patterns.

Compatibility

Any language can emit Guck events by writing JSONL lines to the store.

The optional SDK simply adds conveniences like `run_id` and redaction.

MCP server config example

json
{
  "mcpServers": {
    "guck": {
      "command": "guck",
      "args": ["mcp"],
      "env": {
        "GUCK_CONFIG_PATH": "/path/to/.guck.json"
      }
    }
  }
}

License

MIT

guck

Frequently asked questions

What is guck-mcp?

guck-mcp is Guck MCP

How do I install guck-mcp?

Open the GitHub repository and follow its README. Most MCP servers are added to your client's MCP config, then called by your agent.

Is guck-mcp open source?

Yes — it is hosted on GitHub at https://github.com/tillkolter/guck-mcp and has 2 stars.

Related MCP tools

Run your own MCP server? See who uses it and what to fix.

Measure it with TrackMCP