Skip to main content
Glama

xenia

Xenia helps agents work better on your computer by providing a local MCP for them to:

  • check for repeated mistakes from agents on this computer

  • request actions requiring credentials without revealing the credentials to the agent

  • register work that may impact others so they can coordinate on it

It runs with a tray icon and gives you an overview page. Install and run on linux or mac with:

./bin/xenia

Needs Python 3.11+

MCP tools

xenia_report

view

One row is

tasks

What an agent set out to do, in its own words, and whether it got there. The label comes from its plan where it kept one and the outcome is read off the calls made under it. Ordered by what went wrong, not by the clock — pass order: "at" for a timeline.

instructions

Something the user asked for, and how it turned out.

failures

A kind of work that has failed more than once, worst first, grouped across sessions and repos — or, with group_by: "cause", one row per reason rather than per kind of work.

repeats

Work a session did again soon after it had already attempted the same thing.

tools

Counts, failure rates, latency and reply size, per tool, broker, channel, host, repo or signature.

disk

What was written, how often each file was rewritten, and how much of that hashed to what was already there.

credentials

Name of a credential the user has stored in a keychain that xenia can use

claims

List of shared resource claims

xenia_calls

Breaks a xenia_report row into its calls.

xenia_trace

The actions between an action_id failure and the fix, including how long it took.

xenia_claim

For posting, updating or releasing a claim on a resource. | no | live work, held by a running session | | ask | past the expiry but the holder is alive has not deregistered | | yes | past the expiry and the owner is gone |

Arguments

since (24h, 7d, or a date) repo (work outside any checkout is filed under general) limit applies to every view. Every reply starts with now and now_local because the record is UTC and the logs it gets lined up against usually are not.

Where tool, via, channel, session and signature are accepted they match exactly or as a glob (via: "acme-*"), and a signature from any view drills straight into the calls behind that row.

See ARCHITECTURE.md.

Custom request signing can be supplied by an executable using the signing provider protocol.

Available Tools

3 tools
xenia_callsA

Individual calls, for the one question every xenia_report view raises and cannot answer: which call was that. A 'tools' row reporting a 33KB maximum does not say which call returned it, and one signature covering six journalctl runs is one row on purpose. Deliberately thin — action id, time, tool, status, duration, reply size and a short command, and nothing that repeats identically down the rows. Defaults to the heaviest replies first; pass the 'signature' or 'tool' from a report row to drill into it, and the 'action_id' it returns to xenia_trace. 'detail' is cut to 120 characters so a page of rows stays readable — xenia_trace on the same action id is where the whole command is, for any call and not only a failed one.

Inputs: via, kind, repo, tool, +9 more.

xenia_reportA

How coding agents have been getting on with their work on this machine. One record, six views of it — choose what a row should be with 'view':

tasks one unit of work an agent named for itself, and whether it got there: achieved, partial, failed, abandoned or no_action. The outcome is read off the calls made under the task, never off the agent's claim about it; where the two disagree 'overstated' is 1 and 'declared' is what the agent said. Start here. instructions the same question one level up: one thing the user asked for, and how it turned out. The only view that carries whole prompts, which is why the rest carry a 'goal_id' — pass one back as 'goal_id' for the full text of that instruction. failures one kind of work that keeps failing, worst first, grouped across sessions. 'repos' names the checkouts it failed in, because that is where a fix goes; 'previously' is the same count over the window before this one, so a row failing 8 times against 0 is new and one against 12 is already getting better. 'recovered' is how often a later call put it right; many failures and few recoveries is a gap in the environment or the instructions, and the most actionable row here. Refusals split by who did the refusing: 'refused_by_rule' is a hook or a permission rule, and the reason is in 'example_error' — a config or code fix; 'declined_by_user' is a person saying no at the prompt, which is not yours to change. Pass 'example_action_id' to xenia_trace. repeats one piece of work a session did again minutes after it had already succeeded. This is the waste 'failures' cannot show, since none of it failed. Cost it in 'repeated_bytes' rather than 'repeated_ms': redoing work is rarely slow, but every repeat puts its whole reply back into a context. tools one tool, broker, host, repo or signature, with calls, failure rate, latency and reply bytes. Ask this rather than totalling rows yourself; order by 'total_bytes' for what floods a context rather than what takes time. disk one file (or repo, tool, session) with what was written to it, how often it was rewritten, and how much of that hashed to what was already there — 'unchanged' is bytes that reached the drive and changed nothing.

Rows come back under 'rows'. The tasks view also returns 'instructions', the text of each instruction its rows sat under, keyed by 'goal_id' — one entry per instruction rather than the same sentence repeated down every row. 'since', 'repo' and 'limit' apply to every view; each other parameter names the views that read it, and passing one to a view that does not is an error rather than a filter that quietly does nothing. For the individual calls behind any row, take its 'signature' to xenia_calls.

Inputs: view (required), via, kind, path, +18 more.

xenia_traceA

One action, the task it was working towards, its outcome, and — when a later action fixed it — every action in between, from that one session. This is how a failure was actually recovered from. A fix in a later session gives the two endpoints only: the work between them belongs to two sessions and threading it into one list by clock time would not be a reading of anything. Takes ANY action id, not only a failed one: it is also the way to read one call's arguments in full, since xenia_calls shortens them to keep its rows scannable and a recovery series is simply absent when there was nothing to recover from.

Inputs: action_id (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.5/5.0

    Scored across 3 tools

    Disambiguation5/5

    The three tools are clearly distinct: xenia_report provides aggregated views, xenia_calls provides individual call details, and xenia_trace provides a recovery trace. Each tool addresses a different level of analysis, with no overlapping purposes.

    Naming Consistency5/5

    All tool names follow a consistent 'xenia_' prefix followed by a noun (report, calls, trace), forming a predictable pattern. The naming is uniform and intuitive.

    Tool Count5/5

    With only 3 tools, the set is well-scoped for an observability server. Each tool earns its place, and the xenia_report tool consolidates multiple views without unnecessary fragmentation, keeping the surface focused.

    Completeness5/5

    The tool set covers the full observability workflow: aggregated reports (xenia_report), per-call inspection (xenia_calls), and detailed action tracing (xenia_trace). There are no obvious gaps, as the three tools enable a complete drill-down from summary to individual action.

    Maintenance

    ActivityActive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers