# Tares (pypi · tares)

Always-on AI agents: a software factory for Claude Code, or an AI SRE that watches your systems.

- Trust score: 59/100 (low)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-04

## Components

- pypi · `tares`: 59/100 (this document), [markdown](https://verifymcp.io/servers/ai-glassflow-tares/tares.md), [page](https://verifymcp.io/servers/ai-glassflow-tares/tares)

## Channel facts

- Registry: `pypi`
- Package: `tares`
- Version: `1.55.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-04.

- **Supply Chain Security**: 43/100
  - Malware scan not yet available for this package.
  - Known CVEs were checked across the 48 of 59 dependencies we could resolve, so this covers what we could see, not the whole tree.
  - Runs hatchling.build at install time, a recognised build step with no custom scripting around it.
  - Dependency health was assessed across the 48 of 59 dependencies we could resolve, so this covers what we could see, not the whole tree.
- **Provenance & Transparency**: 100/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to glassflow/tares).
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 1 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 61/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 8291 tokens (~125/item across 66 items; 66 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 10/100
  - Stability observed for 3 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 71/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 0% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 75/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - 0 of 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "desk_withdraw" implies "withdraw" and declares no destructiveHint at all, which the MCP spec reads as destructive by default.
  - An AI judge read all 66 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### How do I install the Tares MCP server?

Tares runs locally as a PyPI package, launched with uvx tares. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add ai-glassflow-tares -- uvx tares
```

### Cursor

```json
{
  "mcpServers": {
    "ai-glassflow-tares": {
      "command": "uvx",
      "args": [
        "tares"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "ai-glassflow-tares": {
      "command": "uvx",
      "args": [
        "tares"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add ai-glassflow-tares -- uvx tares
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ai-glassflow-tares": {
      "type": "local",
      "command": [
        "uvx",
        "tares"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ai-glassflow-tares --command uvx --arg tares
```

### Hermes

```yaml
mcp_servers:
  ai-glassflow-tares:
    command: "uvx"
    args: ["tares"]
```

### Netclaw

```json
{
  "McpServers": {
    "ai-glassflow-tares": {
      "Transport": "stdio",
      "Command": "uvx",
      "Arguments": [
        "tares"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add ai-glassflow-tares -t stdio -c uvx -a tares
```

### Other

```json
{
  "mcpServers": {
    "ai-glassflow-tares": {
      "command": "uvx",
      "args": [
        "tares"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-04 (score 59, −17)

- [security regression] Malware scan: pass → unverified
- [security regression] Known CVEs: pass → partial
- [functional] Dependency health: 0.99 → partial

### 2026-11-03 (score 76, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-11-02 (score 61, −14)

- [security regression] Malware scan: pass → unverified
- [functional] Package version: 1.55.0 → 1.55.1

### 2026-11-01 (score 75)

First indexed and scored.

## MCP tools (66)

### `read` (~233 tokens)

Read one correlated, time-ordered timeline of everything matching `selector` across all
sources, or only a `project`'s sources, or only the `sources` you name. `selector` is a
{label: value} conjunction, matched with strict AND, e.g. {"repo": "frontend"} or
{"service": "api-server", "endpoint": "/login"}. An event matches only if it carries every
named label with that value, so adding a label narrows and removing one widens. Use this to
investigate any entity on the fly; once you know which sources matter, create_trigger() over
them. Set `include_payload` when the one-line summaries aren't enough and you need each
event's full lossless record: the return becomes JSON {timeline, events[]} where each event
carries `raw`. With a project key the read covers that project only, its findings
included.

Input parameters:

- `include_payload` (boolean)
- `project` (string)
- `selector` (object, required)
- `sources`
- `window` (string)

Output parameters:

- `result` (string)

### `create_trigger` (~373 tokens)

Create a trigger: a condition Tares evaluates continuously over one or more sources; when
it trips, subscribed agents are woken with the correlated timeline. `sources` names the
sources it watches (at least one). `filters` [{field, op, value}] (ops: eq, neq, in (a list), contains, gt,
lt, gte, lte) narrows them. `key_field` is the entity label (default: the primary label of the
first source). `condition` is {aggregate: any|avg|count|max|min|sum, field: numeric label to
aggregate (omit for count), predicate: e.g. '> 1.0' / '>= 5' / '== 0', window: detection
window e.g. '1m'}. `emit` is {kind: what a firing is called e.g. error_spike, context_window:
timeline the woken agent receives e.g. '15m'}. `project` is the project id the trigger belongs
to (default: the default project); its sources join that project. `description` (optional)
says in one plain line what wakes it, phrased to follow "When", e.g. "an alert fires in the
checkout service"; the project page uses it instead of the rule's own wording (at most 160
characters, one line). catalog_describe a source to confirm its labels first. Wire agents
to it with subscribe().

Input parameters:

- `condition` (object, required)
- `cooldown` (string)
- `description`
- `emit`
- `filters`
- `key_field` (string)
- `name` (string, required)
- `project` (string)
- `sources` (array, required)

Output parameters:

- `result` (string)

### `update_trigger` (~152 tokens)

Edit an EXISTING trigger in place: replace its sources, filters, key_field, condition,
emit and cooldown, and move it to another `project` when given. Create new triggers with
create_trigger(); this only updates one that already exists (renaming isn't supported, so
keep `name` the same). `description` left out keeps the current one, "" clears it. See
create_trigger for the shapes.

Input parameters:

- `condition` (object, required)
- `cooldown` (string)
- `description`
- `emit`
- `filters`
- `key_field` (string)
- `name` (string, required)
- `project` (string)
- `sources` (array, required)

Output parameters:

- `result` (string)

### `subscribe` (~42 tokens)

Register a webhook to be woken (pushed) when a trigger fires. Returns a subscription id.

Input parameters:

- `trigger` (string, required)
- `url` (string, required)

Output parameters:

- `result` (string)

### `catalog_list` (~16 tokens)

List available sources, triggers and projects.

Output parameters:

- `result` (string)

### `catalog_describe` (~75 tokens)

Describe one catalog entry in full: schema (event types + typed fields, inferred from
stored events), freshness, lineage, and sample records. Handles look like source:logs or
trigger:error_spike. Use this to discover label names before creating a trigger or reading
an unfamiliar source.

Input parameters:

- `handle` (string, required)

Output parameters:

- `result` (string)

### `remember` (~83 tokens)

Write an observation back to Tares's agent-memory lane. It becomes a source like any
other: joined into correlated reads, so what you learned this incident appears in the
timeline next time the same key acts up. memory_type: observation | aggregation | decision.

Input parameters:

- `content` (string, required)
- `key` (string, required)
- `memory_type` (string)

Output parameters:

- `result` (string)

### `set_session_flow` (~114 tokens)

Mark this Claude Code session as running a named flow, e.g. "challenger" (a second model
challenges your plan and every commit; Tares keeps the whole exchange and writes the session
summary). Pass an empty string to clear it. Call it when the user asks for the flow at the
start of a session. This tool only acknowledges: the Tares plugin sees the call in the
transcript and marks the session on both the laptop and Tares.

Input parameters:

- `flow` (string)

Output parameters:

- `result` (string)

### `list_connectors` (~55 tokens)

List the connector types you can create a source with, each with its config fields, mode
(poll | push), and whether it supports discovery. Read this first to learn what you can ingest
and how to configure it.

Output parameters:

- `result` (string)

### `discover_source` (~100 tokens)

Introspect an upstream and get a proposed source config — no commitment. Works for
connectors that can introspect: e.g. prometheus given {"url": "http://..."}, or github given
{"repo": "owner/name"}. The returned `proposed_config` can be passed straight to create_source.
(Use list_connectors to see which connectors support discovery.)

Input parameters:

- `config` (object, required)
- `connector` (string, required)

Output parameters:

- `result` (string)

### `discover_docker` (~48 tokens)

Scan the local Docker environment and get a list of proposed sources (one per container's
logs, plus a detected Prometheus). Each item's `config` is ready to pass to create_source.

Output parameters:

- `result` (string)

### `test_source` (~75 tokens)

Dry-run a source config without creating it: poll connectors do one live poll and return a
sample; push connectors return their ingest endpoint. Use before create_source to check the
config works.

Input parameters:

- `config` (object, required)
- `connector` (string, required)
- `name` (string, required)
- `poll` (string)

Output parameters:

- `result` (string)

### `create_source` (~145 tokens)

Create a data source so Tares starts ingesting it immediately (no restart). `config` is
the connector's config (see list_connectors / discover_source); push connectors ignore `poll`.
\`project` is the project id the source joins (default: the default project); other projects
can use it too. Returns {ok, name} or an error detail. After creating, use list_sources to
watch it ingest and catalog_describe("source:<name>") to see its labels.

Input parameters:

- `config` (object, required)
- `connector` (string, required)
- `name` (string, required)
- `poll` (string)
- `project` (string)

Output parameters:

- `result` (string)

### `list_sources` (~39 tokens)

List every configured source with its live health (status, events ingested, last error).
Use it to confirm a source you created is actually ingesting.

Output parameters:

- `result` (string)

### `source_fields` (~100 tokens)

Profile a source's real fields from recent events: every candidate field with its coverage,
distinct count, and top values, plus which are already declared as labels/keys. Call this BEFORE
choosing labels for a source — a label's `field` MUST be one of these exact field names (never
invent one). The `labels` block echoes the source's current declared axes.

Input parameters:

- `limit` (integer)
- `name` (string, required)

Output parameters:

- `result` (string)

### `list_projects` (~39 tokens)

List the projects you can work in: id, name, template and status. With a project key it is
the one project the key belongs to.

Output parameters:

- `result` (string)

### `join_project` (~96 tokens)

Join a project: Tares POSTs every firing of every trigger in the project to `url` (your
agent's webhook), the triggers added later included. The body carries dispatch_id, trigger,
project, key (the entity), fired_at, payload (the timeline) and run_ids (the Tares agents it
woke). Returns the subscription id.

Input parameters:

- `project` (string)
- `url` (string, required)

Output parameters:

- `result` (string)

### `stats` (~107 tokens)

Counts per value of the label `by` over the project's sources, the last `window` against
the window before, largest change first. `where` {label: value} narrows the events counted,
\`sources` narrows the sources. Use it to see what moved before reading one entity.

Input parameters:

- `by` (string, required)
- `project` (string)
- `sources`
- `top` (integer)
- `where`
- `window` (string)

Output parameters:

- `result` (string)

### `list_skills` (~44 tokens)

List the project's skills: name and description. Load one with get_skill before relying
on it, only when your task matches its description.

Input parameters:

- `project` (string)

Output parameters:

- `result` (string)

### `get_skill` (~34 tokens)

The instructions of one of the project's skills, as markdown.

Input parameters:

- `name` (string, required)
- `project` (string)

Output parameters:

- `result` (string)

### `list_findings` (~88 tokens)

The findings recorded in the project, newest first: its Tares agents' and the ones
external agents recorded. `entity` and `agent` narrow them. Read them before concluding, so
you build on what is known instead of repeating it.

Input parameters:

- `agent` (string)
- `entity` (string)
- `limit` (integer)
- `project` (string)

Output parameters:

- `result` (string)

### `record_finding` (~200 tokens)

Record what you concluded about an entity (a service, a repo, a customer) in the project.
It lands on the entity's timeline next to the Tares agents' findings and in the project's
activity, under your key's name. `finding` is markdown; `verdict` one lowercase word (for
example rca or resolved); `label` the label the entity is a value of when it is not the
project's usual one (for example service). `headline` is one line (at most 100 characters)
saying what you found, and `next_step` what a person should do (empty when nothing needs
doing): both show on the project's Overview.

Input parameters:

- `entity` (string, required)
- `finding` (string, required)
- `headline` (string)
- `label` (string)
- `next_step` (string)
- `project` (string)
- `verdict` (string)

Output parameters:

- `result` (string)

### `project_timeline` (~59 tokens)

What happened in the project, newest first: each firing with the runs it woke and their
findings, and the findings recorded without a firing (external agents' among them).

Input parameters:

- `limit` (integer)
- `project` (string)

Output parameters:

- `result` (string)

### `create_project` (~115 tokens)

Create an empty Tares project for a piece of work you are about to spec, and tie this
session to it. `name` is the project's handle (unique on Tares); `goal` is one line saying
what it is for. Then write its docs with write_doc and its tickets (write_ticket, or
link_linear_project or link_github_issues when the tickets live in Linear or GitHub).
Returns the project's id and name.

Input parameters:

- `goal` (string)
- `name` (string, required)

Output parameters:

- `result` (string)

### `write_doc` (~229 tokens)

Write a markdown doc into the project, or replace one when `id` is given. `kind` is one
of: `start` (the prompt a session that builds the project starts with: what to read first,
which ticket to take, how to work), `spec` (what is built and why), `plan` (milestones and
the order of work), `agents` (the AGENTS.md of the build: conventions, commands, how to
test), `working` (the working doc of one ticket: context, steps, files likely touched, how to
verify; link it with attach_working_doc), `note` (anything else). Working docs and every
other doc stay in Tares; they never go to Linear or GitHub. A rule or fact that holds for every
project goes in the shared docs with add_to_global instead. Returns the doc's id.

Input parameters:

- `body` (string, required)
- `id` (string)
- `kind` (string, required)
- `project` (string)
- `title` (string, required)

Output parameters:

- `result` (string)

### `list_docs` (~109 tokens)

The project's docs in reading order (starting prompt, spec, plan, AGENTS.md, memory,
notes, working docs): id, kind, title, size, when changed. No bodies: read one with get_doc.
\`kind` narrows the list. Docs marked `global` (the AGENTS.md and the memory for all
projects) belong to every project: read them too, they hold the user's standing rules.

Input parameters:

- `kind` (string)
- `project` (string)

Output parameters:

- `result` (string)

### `get_doc` (~33 tokens)

One of the project's docs, with its markdown body.

Input parameters:

- `id` (string, required)
- `project` (string)

Output parameters:

- `result` (string)

### `read_global_docs` (~72 tokens)

The docs every project shares: the AGENTS.md for all projects (the user's standing rules)
and the memory (facts and preferences that hold across projects), as markdown. Read them at
the start of any work on a project and follow them; do not ask the user again for what they
already say.

Output parameters:

- `result` (string)

### `add_to_global` (~133 tokens)

Add one line to a doc every project shares: `doc` is `agents` (the AGENTS.md for all
projects: a rule every session should follow, e.g. "always build on a branch, never commit
to main") or `memory` (a fact or preference that holds across projects, e.g. "the household
uses euros"). Ask the user first, and add only what holds beyond this project; a project's
own rules go in its own AGENTS.md. A line already there is not added twice.

Input parameters:

- `doc` (string, required)
- `line` (string, required)

Output parameters:

- `result` (string)

### `pick_up` (~150 tokens)

Pick the build up where an earlier session stopped. Call it first when you are told to
work on a project and a ticket is already in progress (list_tickets says so), or when told
to pick up. Returns the hand-over: the ticket with its working doc, what the previous
session said last and the files it touched, the builders' notes and a checklist. It takes
the build over (the previous session is marked replaced) unless that session may still be
open: then it says so and does nothing; ask the person, and call again with take_over=true
only if they say so.

Input parameters:

- `project` (string)
- `take_over` (boolean)

Output parameters:

- `result` (string)

### `list_tickets` (~204 tokens)

The project's tickets in plan order: id, label (the Linear identifier such as ENG-12, the
GitHub identifier such as GH-12, else T<n>), title, status (todo, in_progress, done,
canceled), milestone, depends_on, the GitHub repo it changes (`repo`, owner/name, for a
project that spans several), whether it is ready (all it depends on is done) or which tickets
block it, the link when it lives in Linear or GitHub, and the id and title of each one's
working doc. Work the ready tickets in this order. Also says where they live: `linear` is
the Linear project and `github` the repo and issue label, each with when it was last synced
(null when the project does not use it); with both null the tickets live in Tares. Read one
with get_ticket to get its working doc.

Input parameters:

- `project` (string)

Output parameters:

- `result` (string)

### `get_ticket` (~117 tokens)

One ticket, by its Tares id, its number (T3), its Linear identifier (for example
ENG-12) or its GitHub identifier (for example GH-12), with the body of its working doc, who
holds it and where it stands, its pull request as GitHub has it (head, CI, the reviewer's verdict, merged), its history, and the
crew's messages about it: everything you need to work on it.

Input parameters:

- `project` (string)
- `ticket` (string, required)

Output parameters:

- `result` (string)

### `write_ticket` (~277 tokens)

Add a ticket to the project's list, or change one when `id` is given (its id or T<n>).
Only for a project whose tickets live in Tares: when they live in Linear or GitHub, create
and change them there (milestones and "blocks" or "blocked by" relations included; `gh` for
GitHub) and Tares picks them up on its next sync. `status` is todo, in_progress, done or
canceled; `position` orders the list (a new ticket goes to the end); `milestone` is the name of a milestone written with
write_milestone ("" takes it out of its milestone); `depends_on` lists the tickets (T<n> or
id) that must be done first ([] clears them); `repo` is the GitHub repo the ticket changes
(owner/name), for a project that spans several repos ("" clears it; a Linear or GitHub ticket
takes only this, and attach_working_doc). Returns the ticket with its label (T<n>).

Input parameters:

- `depends_on`
- `id` (string)
- `milestone`
- `position`
- `project` (string)
- `repo`
- `status` (string)
- `title` (string, required)

Output parameters:

- `result` (string)

### `attach_working_doc` (~90 tokens)

Link a working doc (write it first with write_doc, kind `working`) to a ticket, by the
ticket's Tares id, Linear identifier or GitHub identifier (GH-12). Works for tickets in
Linear or GitHub too: the working doc stays in Tares.

Input parameters:

- `doc` (string, required)
- `project` (string)
- `ticket` (string, required)

Output parameters:

- `result` (string)

### `link_linear_project` (~86 tokens)

Tie the project to the Linear project its tickets live in, by the Linear project's id,
URL or name. Tares then keeps its ticket list in sync with Linear (about once a minute) and
runs a first sync now. Needs Linear connected on Tares (Settings). Returns the tickets
found.

Input parameters:

- `linear_project` (string, required)
- `project` (string)

Output parameters:

- `result` (string)

### `link_github_issues` (~152 tokens)

Tie the project to the GitHub repo (owner/name or URL) whose issues carrying `issue_label`
are its tickets (default `tares:<project name>`). Tares then keeps its ticket list in sync
(about once a minute): the GitHub milestones its issues sit in become the project's milestones, "blocked by"
becomes depends_on, and status follows the issues. Uses the GitHub credentials stored on
Tares (Settings, GitHub); one of them must read the repo's issues. Create and change the
issues with `gh`. Returns the tickets found.

Input parameters:

- `issue_label` (string)
- `project` (string)
- `repo` (string, required)

Output parameters:

- `result` (string)

### `write_milestone` (~216 tokens)

Write one of the project's milestones, or change it when one with this `name` exists
(names are unique). Each milestone ships something a person can check: `goal` says what in
one line, `checks` are its acceptance checks, [{"check": "<command or short manual step>",
"expect": "<what it should show>"}], that the releaser runs when the milestone ships.
\`position` orders them (a new one goes last). To rename one, pass its current name or id as
\`id` and the new `name`. Give tickets a milestone with write_ticket(milestone=<name>). When
the project's tickets live in Linear or GitHub, its milestones come from there (for GitHub,
the milestones its issues sit in): add and rename them there and write only the goal and checks here.

Input parameters:

- `checks`
- `goal`
- `id` (string)
- `name` (string, required)
- `position`
- `project` (string)

Output parameters:

- `result` (string)

### `list_milestones` (~64 tokens)

The project's milestones in order: name, goal, acceptance checks, how many tickets and
how many are done, which are ready, and whether the milestone is finished. Work one
milestone at a time, in this order.

Input parameters:

- `project` (string)

Output parameters:

- `result` (string)

### `assign_ticket` (~98 tokens)

Give a ticket (T3, its id, or its Linear or GitHub identifier such as GH-12) to the
station that works it, by the station's name (for example shop-build-m1). Only the
orchestrator, or the person's own session, assigns. A ticket with no stage yet starts at todo.

Input parameters:

- `holder` (string, required)
- `project` (string)
- `ticket` (string, required)

Output parameters:

- `result` (string)

### `set_stage` (~221 tokens)

Move a ticket you hold: `stage` is doing (you started), review (its PR is up: pass `pr`,
the pull request's URL), changes (the reviewer asked for changes), merged, or blocked (say
why in `reason`). Only the releaser marks a ticket shipped. A ticket held by another station
is refused; ask the orchestrator. For a ticket that lives in Linear or GitHub, also move it
there (Linear's own tools, `gh` for GitHub). Name your branch factory/<ticket> (factory/T3)
so Tares finds the pull request on its own too. Asking for review, pass the checks you ran
as `checks` ([{command, result, commit, broke_test}, ...]) instead of one add_check call
each; they are recorded before the stage moves.

Input parameters:

- `checks`
- `pr` (string)
- `project` (string)
- `reason` (string)
- `stage` (string, required)
- `ticket` (string, required)

Output parameters:

- `result` (string)

### `assume` (~166 tokens)

Record an assumption you made so the work does not block: the `question` the plan did not
answer, the `choice` you made, `why`, the `tickets` it touches (T3, ...), and who it
\`affects`. Returns its number (A1, A2, ...): tell the orchestrator that number in one line and
carry on. The orchestrator confirms open assumptions with the person once per milestone.
Never use this for what must go to the person directly (prod deploys, secrets, money, new
contacts, deleting data).

Input parameters:

- `affects` (string)
- `choice` (string, required)
- `project` (string)
- `question` (string, required)
- `tickets`
- `why` (string, required)

Output parameters:

- `result` (string)

### `list_assumptions` (~71 tokens)

The project's assumptions, A1 first: the question, the choice, why, the tickets, and the
state (open: not yet confirmed; kept; overturned, with the person's words). `state`
narrows the list.

Input parameters:

- `project` (string)
- `state` (string)

Output parameters:

- `result` (string)

### `decide_assumption` (~99 tokens)

Record what the person said about an assumption (A3): `state` kept or overturned (or open
again), `words` the person's own words, required when overturned. Only the orchestrator, or
the person's own session, may. Answering a batch on the desk does this for you.

Input parameters:

- `assumption` (string, required)
- `project` (string)
- `state` (string, required)
- `words` (string)

Output parameters:

- `result` (string)

### `add_check` (~200 tokens)

Record a check you ran on a ticket: the exact `command`, what it showed (`result`), the
\`commit` it ran on, and, for a test you added, `broke_test`: the test you saw fail when you
broke the code it covers (then pass again once restored). One line goes into the Checks part
of the ticket's working doc; the rest of the doc is untouched. Record each check after you
run it, never one you did not run: the reviewer compares them with your session. Several
checks you ran back to back go in one call: `more` takes the others as
[{command, result, commit, broke_test}, ...].

Input parameters:

- `broke_test` (string)
- `command` (string, required)
- `commit` (string)
- `more`
- `project` (string)
- `result` (string, required)
- `ticket` (string, required)

Output parameters:

- `result` (string)

### `remember_for_project` (~87 tokens)

Keep one thing you learned about this project (for example "tests need the dev database
running") in its memory, dated and signed; every session on the project reads it. A rule
worth keeping for every project goes to the orchestrator instead (an FYI); only it adds to
the shared memory.

Input parameters:

- `line` (string, required)
- `project` (string)

Output parameters:

- `result` (string)

### `record_review` (~204 tokens)

Record your review of a ticket's pull request, the same verdict you post to GitHub:
\`head` the commit you reviewed, `verdict` pass, changes or block, `verified` what you ran
and what it showed, `not_verified` what you did not cover and why, `findings`
[{"severity": "P1|P2|P3", "file": "", "line": 0, "blocking": true, "text": ""}], and on a
re-review `resolved` marking each earlier finding {"F1": "fixed", "F2": "open"}. A pass
leaves no blocking finding open. Only the reviewer records reviews.

Input parameters:

- `findings`
- `head` (string, required)
- `not_verified` (string)
- `project` (string)
- `resolved`
- `ticket` (string, required)
- `verdict` (string, required)
- `verified` (string, required)

Output parameters:

- `result` (string)

### `review_queue` (~59 tokens)

The pull requests waiting for review across every project, in the order to take them:
those blocking their milestone first, then the longest waiting. Each says whether the
builder's Codex layer is clean and whether an earlier verdict is for an older commit.

Output parameters:

- `result` (string)

### `review_brief` (~131 tokens)

Start every review here: the pull request as GitHub has it (it says STOP when the PR is
merged or its head moved past `head`), the ticket and its working doc, the builder's checks
compared with its recorded session (unmatched first: check those yourself), Codex's
findings and the waivers to judge, earlier rounds and their open findings, assumptions and
decisions, and what keeps coming back in this repo. Then review to your own bar.

Input parameters:

- `head` (string)
- `project` (string)
- `ticket` (string, required)

Output parameters:

- `result` (string)

### `builder_brief` (~167 tokens)

Start every ticket here, and again after a revive: one read with where the ticket stands
(stage, holder, PR, verdict), its working doc, its milestone and acceptance checks, the state
of what it depends on, the project's AGENTS.md (it wins over the generic flow) and the shared
one, open assumptions and desk questions on it, and where you left off (checks recorded,
Codex, earlier review rounds, the crew's latest messages). `start=True` also moves a ticket
that has not been started to doing, so starting a ticket is this one call; a ticket already in
review, changes, blocked or merged keeps its stage.

Input parameters:

- `project` (string)
- `start` (boolean)
- `ticket` (string, required)

Output parameters:

- `result` (string)

### `write_repo_map` (~233 tokens)

Write the map of a GitHub repo (owner/name) that the builder and reviewer briefs serve:
layout, entry points, how to install, build, test and lint, conventions, the files tickets
touch most, known traps. One map per repo, shared by every project on it, at most 8,000
characters (about 2,000 tokens). `body` replaces the whole map, so start from the one in your
brief and pass its `version` as `base` (leave it empty when the repo has no map). If someone
wrote the map since, nothing is written and the answer is the map now: fold your change into it
and write again. `note` says what changed and becomes a dated line in its history. Write it when the
brief says the repo has none; update it when a merged PR changes the layout or the build, test
or lint commands.

Input parameters:

- `base` (string)
- `body` (string, required)
- `note` (string, required)
- `project` (string)
- `repo` (string, required)

Output parameters:

- `result` (string)

### `recurring_findings` (~53 tokens)

Kinds of finding that came back in several tickets of a repo (owner/name) in the last
30 days, with the tickets and examples. Check these first in a review.

Input parameters:

- `repo` (string, required)

Output parameters:

- `result` (string)

### `desk_add` (~281 tokens)

Put a question for the person on the desk (one desk for every project; numbered D1,
D2...): the question, your recommendation and why, the options, two lines of context, what
it blocks (tickets, stations), whether it blocks, and who asked. For the batch of
assumptions to confirm once per milestone, pass their numbers in `assumptions`. Then ask the
person in your session, one item at a time, blockers first. Only the orchestrator writes
the desk.

A permission a station was refused: `station` its name and `command` the exact command it
was refused, verbatim as it reported it; `recommendation` the grant in plain words (which
station may run what, where). The person can allow it with one click in the Tares console;
the crew's watch then restarts that station with the grant in its settings.

Input parameters:

- `asked_by` (string)
- `assumptions`
- `blocking` (boolean)
- `blocks` (string)
- `command` (string)
- `context` (string)
- `options`
- `project` (string)
- `question` (string, required)
- `recommendation` (string, required)
- `station` (string)
- `tickets`
- `why` (string, required)

Output parameters:

- `result` (string)

### `desk_list` (~52 tokens)

The desk: open questions (or `answered`, `withdrawn`) across every project, blockers
first, then oldest. Ask the first one.

Input parameters:

- `project` (string)
- `state` (string)

Output parameters:

- `result` (string)

### `desk_answer` (~210 tokens)

Record the person's answer to a desk item (D3). `words` is their reply exactly as they
typed it in your session, never your summary: Tares checks it against what they typed and
says whether it matches. A reply of one letter ("B") is passed as is: Tares maps it to that
option. `choice` the option it picks. `standing` only when they said it
holds from now on ("always fine for staging"); with `scope` all it holds for every project.
A standing answer that matches becomes a grant. For an assumption batch: `kept` the
assumptions they keep, `overturned` {A3: their words}; open a follow-up ticket for each
overturned one.

Input parameters:

- `choice` (string)
- `item` (string, required)
- `kept`
- `overturned`
- `scope` (string)
- `standing` (boolean)
- `words` (string, required)

Output parameters:

- `result` (string)

### `desk_withdraw` (~49 tokens)

Take a question off the desk when it no longer needs the person (answered by events,
or no longer relevant), saying why.

Input parameters:

- `item` (string, required)
- `reason` (string, required)

Output parameters:

- `result` (string)

### `list_decisions` (~86 tokens)

What the person decided on the project, newest first: the question, their words, the
choice, whether it stands from now on and whether it matched what they typed (`via`
"console": a permission they allowed in the console; the watch restarts that station with
it). Follow them; relay them to stations by quoting the words.

Input parameters:

- `project` (string)

Output parameters:

- `result` (string)

### `get_crew_settings` (~308 tokens)

The tares-factory crew's settings for every project: `autonomy` (L3-review: the person
approves each merge; L4-ship: a builder merges after the reviewer's pass and green CI),
\`releaser` (whether the crew runs a releaser; without one a ticket ends at merged),
\`release_profile`, `prod_pattern` (what counts as prod), `challenger` (builders run the
Codex challenger), `builders_max`, `claude_update` (whether the watch moves stations onto a
new Claude Code; on unless false). Unset ones are null: ask the person, one at a time, with
a recommendation. `kit.frozen` is null while the crew follows the plugin checkout, else
when and by whom the person froze it (`tares factory crew freeze`): the watch then moves no
station onto a newer kit. Read only here; the person freezes and unfreezes from the CLI.
\`idle_wake` (null or false: off): when true the factory's watch wakes you with a message when
you have work and holds your liveness tick, so you arm no schedule of your own. `pace` (null or
false: off): when true the watch slows the crew before the plan's limits: no new builders, a
45-minute tick, and builders wait near the 5-hour limit; its notes to you say what to do.

Output parameters:

- `result` (string)

### `set_crew_settings` (~134 tokens)

Save the crew's settings the person chose (only the ones given change). Only the person's
own session or the orchestrator may. `idle_wake` true has the watch wake idle stations when
they have work, instead of each ticking on its own. `pace` true slows the crew before the plan's
limits are hit.

Input parameters:

- `autonomy` (string)
- `builders_max`
- `challenger`
- `claude_update`
- `idle_wake`
- `pace`
- `prod_pattern`
- `release_profile`
- `releaser`

Output parameters:

- `result` (string)

### `read_grants` (~71 tokens)

What the person allows the crew to do, in their own words with the date: the grants for
every project, and the project's own when `project` is given. Never act on a permission
that is not here or in the person's own words in your session.

Input parameters:

- `project` (string)

Output parameters:

- `result` (string)

### `add_grant` (~111 tokens)

Keep one grant: `words` are the person's own words, quoted exactly as they said them
(never your summary); Tares adds today's date. `scope` is `all` (every project) or
\`project` (this project only, name it in `project`). Only the person's own session or the
orchestrator, relaying the person verbatim, may add one.

Input parameters:

- `project` (string)
- `scope` (string)
- `words` (string, required)

Output parameters:

- `result` (string)

### `list_crew` (~73 tokens)

The crew as Tares sees it: one row per station (orchestrator, reviewer, releaser,
builders, helpers) with its state (working, idle, waiting, quiet, ended), the project it is on,
when it last spoke, the stations it started, and how many earlier sessions played it.

Output parameters:

- `result` (string)

### `get_station` (~29 tokens)

One station with its current session and the earlier sessions that played it.

Input parameters:

- `name` (string, required)

Output parameters:

- `result` (string)

### `hand_over` (~233 tokens)

Hand a specced project to the crew: Tares records it with every repo it spans, and the
orchestrator picks it up from Tares on its next tick. `repos` is one {path, name} per repo:
\`path` the absolute folder it is checked out in on this machine, `name` its GitHub repo
(owner/name), the repo that holds the plan first. A later call adds repos, never replaces
them. `autonomy` only when the person wants this project stricter than the crew
(L3-review: every merge waits for their yes). `repo` (one path) is the older form. Then
send `crew-orchestrator` a `[TF:SHIP]` message with SendMessage so it starts now rather than
on its tick. If no crew is running (list_crew shows no orchestrator working, idle or waiting),
tell the person to run `tares factory crew up` first.

Input parameters:

- `autonomy` (string)
- `project` (string)
- `repo` (string)
- `repos`

Output parameters:

- `result` (string)

### `crew_projects` (~168 tokens)

The projects handed to the crew, oldest first: each with its repos (`path` on this
machine, GitHub `name`) and the tickets and open PRs of each, the autonomy it was handed
over at when stricter than the crew's, tickets done of all, and the milestone it is on. The
orchestrator works from this list: a project here with no builder is one to start. Projects
the person said are done are not in it (`finished` lists them apart). `releasing` lists the
projects the person took back from the crew (`tares factory session <project>`) that still
wait for the orchestrator to stop their builders (`holders`) and call release_project; they
are no longer the crew's to work on.

Output parameters:

- `result` (string)

### `release_project` (~127 tokens)

The person took this project back from the crew (it is under `releasing` in
crew_projects): call this once every builder that held its tickets has stopped, pushed what it
had and written its progress, and has been retired. Tares clears the tickets' holders (stages,
pull requests and working docs stay) and the person's session owns the project from then on.
Then reply to the session that asked with `[TF:RELEASED]`. Only the orchestrator, or the
person's own session when no orchestrator runs.

Input parameters:

- `project` (string, required)

Output parameters:

- `result` (string)

### `finish_project` (~206 tokens)

Mark a project done, once the person said so. Ask them first on the desk ("Is <project>
done? Tickets all merged, milestones checked."), record their answer with desk_answer, then
call this with that item (`decision`, D<n>). Tares keeps their words, sets the project done
and takes it off the crew's work list; a later hand-over opens it again. Refused while a
ticket is open. Only the orchestrator may. Returns how many projects the crew still holds:
with none left, ask the person on the desk whether to stop the crew (`tares factory crew down`
in their terminal).

A person's own session (`tares factory session`, not a crew station) passes `words` instead:
what the person typed when they said it is done, copied exactly. That also finishes a project
the crew never held.

Input parameters:

- `decision` (string)
- `project` (string, required)
- `words` (string)

Output parameters:

- `result` (string)

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Dependencies. The full working is on the page: https://verifymcp.io/servers/ai-glassflow-tares/tares#diagnostics

## Score history

- 2026-11-04: 59
- 2026-11-03: 76
- 2026-11-02: 61
- 2026-11-01: 75

## Common questions

### What is the Tares MCP server?

Tares is an MCP server listed in the public MCP registry as ai.glassflow/tares. Always-on AI agents: a software factory for Claude Code, or an AI SRE that watches your systems. This page covers its PyPI package (tares).

### Is the Tares MCP server safe to use?

Tares scores 59 out of 100 on VerifyMCP. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Tares MCP server expose?

Tares exposes 66 tools: read, create_trigger, update_trigger, subscribe, catalog_list, and 61 more. Their descriptions and schemas cost roughly 8,291 tokens of context every time the server is loaded.

### Is the Tares MCP server still maintained?

Tares is still listed as active in the MCP registry. We last reached this channel on 4 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the Tares MCP server under?

Tares declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- PyPI project: https://pypi.org/project/tares/
- Socket report: https://socket.dev/pypi/package/tares
- Repository: https://github.com/glassflow/tares
- Website: https://docs.glassflow.ai/tares
- Changelog RSS feed: https://verifymcp.io/servers/ai-glassflow-tares/tares.xml
- Changelog JSON feed: https://verifymcp.io/servers/ai-glassflow-tares/tares.json
- HTML version of this page: https://verifymcp.io/servers/ai-glassflow-tares/tares
