Skip to main content
Glama

Agent Bridge

Local MCP message bridge for Claude Code and Kimi CLI.

Agent Bridge lets two coding agents exchange tasks, results and bounded autonomous conversations through one shared SQLite database. It uses MCP stdio transport and local files only — no TCP/UDP server, no external service and no network protocol of its own.

The reference Claude Code setup runs the Claude-side worker against Strata, model qwen3.8-flash-next-unsloth-ud-q4_k_xl, through the local launcher. The bridge core itself is model-agnostic and can dispatch work to any compatible agent client.

Status: experimental. The main exchange flow is implemented and covered by tests, but the project is still evolving. See TODO.md for known gaps.

Stack

  • Claude Code worker: local headless Claude Code launcher, configured for Strata, model qwen3.8-flash-next-unsloth-ud-q4_k_xl.

  • Kimi CLI worker: official Kimi CLI in prompt mode.

  • Agent Bridge core: Python 3.11+, MCP stdio transport and SQLite.

Related MCP server: agent-bridge

Highlights

  • Two-way agent inbox: send, receive, acknowledge and reply to messages.

  • Safe concurrent workers: atomic claims with expiring leases prevent two workers from executing the same task.

  • Bounded conversations: goal-driven task → result dialogues with a turn limit, expiry, server-side ordering and reviewer decisions.

  • Automatic headless delivery: per-agent listeners can dispatch root tasks and conversation turns to one-shot worker processes.

  • Progress indication: a compact listener status shows the current lifecycle stage and the last dispatch result without exposing task payload.

  • Anti-spam primitives: response deadlines, idempotency keys and no automatic retries.

  • Payload-safe diagnostics: logs and status files contain ids, stages and exit codes — not prompts, message text, tokens or worker output.

  • Single-file state: the shared message database is plain SQLite with WAL mode and busy timeouts.

How it works

Claude Code session ── MCP stdio ──► server.py (AGENT_ID=claude) ─┐
                                                                   ├──► bridge.db
Kimi CLI session ───── MCP stdio ──► server.py (AGENT_ID=kimi) ───┘
                                        ▲
                                        │ scan / dispatch
                              systemd/listener.py
                                        │
                              systemd/on_message.py
                                        │
                         one-shot Claude or Kimi worker

Each MCP server process derives its sender identity from AGENT_ID; tool arguments cannot impersonate another sender. Both sides point at the same bridge.db, but use opposite values of AGENT_ID.

Interactive MCP sessions do not receive push notifications: an active agent checks receive_messages when it is already running. The optional listener adds the headless path: it scans the database, runs on_message.py for one dispatchable message and waits until that supervisor exits before scanning again.

Requirements

  • Linux or another POSIX environment

  • Python 3.11+

  • uv

  • Claude Code and/or Kimi CLI, depending on the side being automated

Quick start

git clone <your-repository-url>
cd agent-bridge
uv sync

Run the safe dispatcher test suite:

uv run python systemd/test_dispatcher.py

Start a bridge server manually for development:

AGENT_ID=claude uv run python server.py
# in another terminal:
AGENT_ID=kimi uv run python server.py

server.py is an MCP stdio process, so normally it is launched by the agent client rather than used directly as an interactive command.

MCP registration

Use an absolute repository path. Registration is project-scoped; restart the agent session after adding or changing the MCP server.

Claude Code

claude mcp add-json agent_bridge -s project '{
  "command": "uv",
  "args": [
    "run",
    "--directory",
    "/absolute/path/to/agent-bridge",
    "python",
    "server.py"
  ],
  "env": {
    "AGENT_ID": "claude"
  }
}'

Start a new Claude Code session, approve the project-scoped server and check that eight agent_bridge tools are available.

Kimi CLI

Add the following to the project-scoped Kimi MCP configuration, changing the absolute path as needed:

{
  "mcpServers": {
    "agent_bridge": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/absolute/path/to/agent-bridge",
        "python",
        "server.py"
      ],
      "env": {
        "AGENT_ID": "kimi"
      },
      "enabled": true,
      "startupTimeoutMs": 30000,
      "toolTimeoutMs": 40000,
      "enabledTools": [
        "send_message",
        "receive_messages",
        "claim_message",
        "release_message",
        "mark_read",
        "start_conversation",
        "conversation",
        "listener"
      ]
    }
  }
}

Start a new Kimi session from the project and trust the workspace if the MCP command is expected.

Tools

Tool

Purpose

send_message

Store a message, optionally linked with reply_to, deadline and dedup_key.

receive_messages

Return unread messages for the current AGENT_ID; optionally long-poll up to 30 seconds.

claim_message

Atomically claim or renew a message lease before headless execution.

release_message

Return an unfinished claim to the shared inbox without acknowledging it.

mark_read

Acknowledge completed messages; only the recipient can acknowledge.

start_conversation

Create a bounded dialogue and send its root task.

conversation

Inspect, complete, cancel or escalate a dialogue.

listener

Enable, disable or inspect the current agent's background listener.

Basic exchange

1. sender:   send_message(recipient, text, dedup_key="task-1")
2. recipient: receive_messages()
3. recipient: claim_message(message_id)
4. recipient: send_message(sender, result, reply_to=message_id,
                            dedup_key="task-1:result")
5. recipient: mark_read([message_id])
6. sender:    receive_messages()
7. sender:    mark_read([result_id])

If the recipient cannot finish, it sends a blocked: ... result and releases the original message instead of acknowledging it. A response deadline is advisory metadata: Agent Bridge never auto-resends and never retries an attempted dispatch.

Bounded conversations

start_conversation(recipient, goal, max_turns=6, expires_in_seconds=14400) creates a dialogue with a fixed goal, a turn budget and an expiry time. Messages inside the conversation use kind:

  • task asks the other side to perform the next step;

  • result reports completion, blockage or a request for clarification;

  • notice carries operational information without waking a worker or consuming a turn.

The server enforces pairing and direction: a result answers a task, a follow-up task answers a result, and only one message may be in flight. The reviewer side must choose exactly one terminal action after a result: complete the conversation, send one concrete follow-up task or escalate to needs_human.

Terminal conversations accept no new tasks or results. Hard dispatch failures freeze the dialogue so a broken chain cannot continue automatically.

Automatic delivery and progress

The default automation gate is:

{
  "auto": {
    "claude": true,
    "kimi": false
  }
}

Claude-side headless execution is enabled by default in this configuration. Kimi-side headless execution remains disabled because Kimi CLI prompt mode applies its own automatic permission policy without interactive approvals; enable auto.kimi only as a deliberate local decision.

Useful commands:

uv run python systemd/listener.py status   --agent claude
uv run python systemd/listener.py progress --agent claude --once
uv run python systemd/listener.py watch    --agent claude
uv run python systemd/listener.py disable  --agent claude
uv run python systemd/listener.py enable   --agent claude

listener status keeps the original machine-readable fields and additionally reports:

  • stage: stopped, unknown, idle, received or supervising;

  • progress: the currently trusted lifecycle record;

  • last: the previous dispatch outcome, including duration and exit code where available.

Progress files live in systemd/runtime/<agent>.progress.json and contain ids, enums and numbers only. The runtime directory is private and gitignored.

Claude Code status line

There is no supported API for injecting an arbitrary external event into a live Claude Code session. A supported read-side option is Claude Code's custom status line:

#!/usr/bin/env bash
# ~/.claude/statusline-agent-bridge.sh
uv run --directory /absolute/path/to/agent-bridge \
  python systemd/listener.py progress --agent claude 2>/dev/null
{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline-agent-bridge.sh",
    "refreshInterval": 2
  }
}

This is optional local configuration; Agent Bridge does not modify global Claude settings by itself.

Worker launchers

The supervisor chooses a launcher by recipient:

  • systemd/cclocal_headless.sh starts a non-interactive Claude Code worker. It is an example integration for a local Claude-compatible wrapper and expects the local environment variables used by that wrapper.

  • systemd/kimi_headless.sh starts the official Kimi CLI in prompt mode and passes the task through a private request file so task text does not appear in argv or the process list.

For public or team use, review these launchers and adapt them to your own client wrappers and permission model. Do not weaken static deny rules or hide permission requests.

Reliability model

  • One attempt barrier: dispatch_attempts.message_id is the primary key. A rescan, restart or duplicate listener cannot launch the same message twice.

  • No automatic retry: crash, timeout or uncertainty remains visible for a human decision; a short operational notice is sent without task payload.

  • Evidence-based success: exit code 0 alone is not success. The protocol requires an acknowledged original plus the appropriate result, blocked report, follow-up or terminal conversation state.

  • Lease and timeout: worker claims expire; a worker timeout kills only that worker process group.

  • Crash recovery: stale attempts are reconciled by process evidence and report evidence. --recover examines only messages that have never been attempted.

  • Fresh database bootstrap: the listener creates the dispatcher schema additively before scanning, so a new bridge database does not require a manual supervisor run.

Security notes

  • The bridge is local: MCP stdio, SQLite and local subprocesses.

  • Do not commit bridge.db, runtime files, outbox reports or agent MCP configuration.

  • Secrets are passed through environment variables or private files and are never written to the database, prompts, logs or progress files.

  • Logs are operational metadata only. Do not redirect MCP stderr into a file that also stores secret-bearing diagnostics.

  • Claude-side workers may run with permission prompts disabled. Keep their allowlist minimal and prefer an explicit blocked response over any uncertain action.

  • Kimi-side automatic dispatch is deliberately gated off in the default configuration.

  • Conversations are not authorization to perform external or irreversible actions. Deployments, pushes, purchases and messages to third parties require a human decision.

Development

Safe tests use temporary databases and fake launchers/listeners/workers:

uv run python systemd/test_dispatcher.py

test_bridge.py is a destructive end-to-end test that deletes and recreates bridge.db. Run it only in a disposable copy of the project before live traffic, never against a database containing real messages.

Current safe suite: 44 dispatcher tests.

Known limitations

See TODO.md. The main open item is a SQLite WAL startup race under concurrent supervisor launches; the ordinary suite can pass while a focused concurrent stress test still exposes it.

License

MIT

Available Tools

8 tools
claim_messageA

Atomically claim an unread message for this MCP server process.

An active claim by another process cannot be taken over, acknowledged or released. Repeating the call as the current owner renews the lease. An expired claim can be taken by any process belonging to the recipient. lease_seconds is clamped to 30..3600; expiry is checked during tool calls, without background timers.

NameRequiredDescriptionDefault
message_idYes
lease_secondsNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and does so well. It discloses atomicity, ownership constraints, takeover rules, lease renewal, lease clamping, and that expiry is checked during tool calls without background timers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action and then adds compact lifecycle details. Every sentence provides useful behavioral context without redundant restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is strong for a concurrency-sensitive claim operation, especially given the output schema covers return values. Minor gaps remain around explicit sibling-tool selection and message_id parameter semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description should compensate. It explains lease_seconds meaningfully through renewal and clamping behavior, but message_id is only implied by 'unread message' and lacks explicit semantics or constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: atomically claiming an unread message for this MCP server process. The scope is clear, but it does not explicitly distinguish itself from siblings such as release_message, mark_read, or receive_messages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains claim lifecycle rules, including active-claim restrictions, renewal behavior, and expired-claim takeover. However, it does not explicitly say when to choose this tool over alternatives like receive_messages or mark_read.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

conversationA

Inspect or steer a conversation only its two agents belong to.

status — state, turn_count/max_turns, expiry, recent transitions and the in-flight message; never the goal text, never message text (no payload, no secrets). cancel — stop all further automatic dispatch for it (side effects already produced are NOT rolled back); allowed from active/blocked/needs_human. complete — the initial goal is verifiably achieved (the review worker's outcome a; only from active). needs_human — a human decision is required (outcome c; only from active). Repeating the call for the state the conversation is already in is an idempotent no-op; a different terminal state is rejected, so the two agents can never fight over the outcome.

NameRequiredDescriptionDefault
actionYes
conversation_idYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so unusually well: it discloses that status never returns goal or message text (no payload, no secrets), that cancel does not roll back already-produced side effects, that repeating the current state is an idempotent no-op, and that a conflicting terminal state is rejected so the two agents cannot fight over the outcome. Those are exactly the side-effect, idempotency, and failure-mode facts an agent needs before mutating.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded purpose sentence followed by one dense clause per action, so the agent can jump straight to the relevant mode. The 'never the goal text, never message text (no payload, no secrets)' line is slightly redundant, and the unexplained 'outcome a'/'outcome c' shorthand spends words without transferring meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, yet the description still usefully previews what status returns (state, turn_count/max_turns, expiry, recent transitions, in-flight message), and terminal-state semantics are fully covered. Remaining gaps are the undefined outcome taxonomy and the absence of any note on identity/auth requirements or invalid-conversation_id behavior for a tool whose whole premise is agent-scoped access.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the action parameter has no enum, so the description is the only place the valid action values and their meanings appear — the four 'status/cancel/complete/needs_human' labels plus per-action state constraints. conversation_id gets only indirect semantics ('a conversation only its two agents belong to'), and the list is never explicitly declared exhaustive, so it nearly but does not fully compensate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a concrete verb pair ('Inspect or steer') and resource ('a conversation'), then enumerates four distinct operations (status, cancel, complete, needs_human) with their effects. The scope constraint 'only its two agents belong to' signals the ownership boundary. It never names a sibling tool, so differentiation from send_message/start_conversation is left to inference rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Each action carries its own applicability condition: cancel is 'allowed from active/blocked/needs_human', complete and needs_human are 'only from active'. That is genuine when-to-use guidance. It stops short of naming alternatives or saying when not to call this at all, and the '(the review worker's outcome a)' / '(outcome c)' references point at an undefined taxonomy the agent cannot resolve.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

listenerA

Manage this agent's own background listener (AGENT_ID only).

status: enabled/running/pid and the id of the message the listener is currently waiting on — never task payload. enable: removes the disabled marker and idempotently starts the listener (duplicate sessions create no duplicate — the listener holds an exclusive flock). disable: writes the marker; the listener then takes no new task, lets the current worker finish and exits. No PID is ever killed from here. Dispatch itself stays governed by systemd/config.json auto..

NameRequiredDescriptionDefault
actionYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does: it discloses idempotency guarantees (exclusive flock, no duplicate sessions), the supervision semantics of disable (finishes the current worker, then exits), and a safety boundary ('No PID is ever killed from here'). It also scopes the returned data ('never task payload'), which preempts a plausible agent assumption.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with identity and scope, then segmented by action, with zero filler sentences. The register is telegraphic ('removes the disabled marker', 'writes the marker'), which compresses well but occasionally forces the reader to reconstruct grammar rather than read meaning directly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with an output schema and no annotations, this covers the operations, their side effects, idempotency, and the safety boundary. What is left unsaid is failure behavior (e.g., what status reports when no listener is running, or what happens on enable when already enabled) and any auth requirement beyond the AGENT_ID scope.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and the single 'action' parameter has no enum, so the description must supply the value domain — and it does, defining status/enable/disable with the exact behavior of each. It falls short of 5 because the values are only implied by colon-prefixed labels rather than stated as a closed set, leaving open whether other actions exist.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line names a specific resource (this agent's own background listener) and a hard scope limit (AGENT_ID only), and the three sub-operations status/enable/disable define exactly what 'manage' covers. It is clearly distinct from the messaging siblings, though the generic verb 'Manage' does the least work in the sentence and 'listener' is only defined indirectly via the task/worker/flock details.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Each action is given a use condition: status to inspect, enable to clear the disabled marker, disable to stop taking new work gracefully. The closing line 'Dispatch itself stays governed by systemd/config.json auto.<agent>' is an explicit exclusion telling the agent not to reach for this tool to change dispatch, though no sibling or alternative tool is named as the route for that.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mark_readA

Acknowledge messages by id; only their recipient (AGENT_ID) can do so.

Already-acknowledged, foreign and actively claimed-by-other-worker ids are skipped silently. Free messages and expired claims remain compatible with the original recipient-only acknowledgement behavior.

NameRequiredDescriptionDefault
message_idsYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral burden and discloses important traits: recipient-only authorization and silent skipping of already-acknowledged, foreign, and actively claimed ids. It also notes compatibility for free messages and expired claims, though it could say more about the acknowledgement side effect and return behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded and appropriately short for a one-parameter tool. Most sentences earn their place by covering authorization and skip behavior, though the final compatibility sentence is somewhat dense.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be described. For a simple one-parameter tool, the description covers the key invocation constraints and edge cases, with the main remaining gap being explicit guidance relative to sibling message-handling tools.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the undocumented message_ids parameter. It clarifies that ids refer to messages and are subject to recipient-only acknowledgement, but it does not explain array/batch behavior, duplicate handling, or empty-input semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: acknowledge messages by id. It also clarifies the recipient-only scope. It does not explicitly distinguish mark_read from siblings such as claim_message or receive_messages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context that only the recipient can acknowledge and that some ids are skipped silently. However, it does not explicitly say when to use mark_read instead of claim_message, release_message, or receive_messages.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

receive_messagesB

Return available unread messages addressed to AGENT_ID, oldest first.

Messages actively claimed by another server process are hidden. Waits up to wait_seconds, capped at MAX_WAIT_SECONDS (30). Messages stay unread until mark_read. Each message carries response_deadline, claim_expires_at and owned_by_current_worker; cursor is the last returned id, or None.

NameRequiredDescriptionDefault
limitNo
wait_secondsNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does a solid job: it discloses claim-hiding, the wait cap of MAX_WAIT_SECONDS (30), non-destructive read semantics (stays unread until mark_read), and per-message metadata fields. However, it omits auth/AGENT_ID resolution, empty-result behavior, and any error or timeout semantics.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with the core action, which is good. But the trailing "cursor is the last returned id, or None" sentence does not fit an input-side description and is partly redundant given the tool has an output schema, so it does not fully earn its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter, no-annotation polling tool, the description covers the essential pull semantics: claimed messages are hidden, the wait cap, and unread persistence. The output shape is already covered by the output schema, and the only meaningful gap is the undocumented limit parameter.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains wait_seconds including the hard cap, but says nothing about limit, its default of 20, or what happens if limit is exceeded; "cursor is the last returned id" refers to an output field, not a parameter, so it does not help parameter use.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource with scope: "Return available unread messages addressed to AGENT_ID, oldest first." The unread/address-to-this-agent scope and the oldest-first ordering distinguish it from siblings like claim_message and mark_read, though no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: messages claimed by another process are hidden, and "messages stay unread until mark_read" hints at the follow-up tool. There is no explicit statement of when to choose this over listener or claim_message, so the agent must infer the routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

release_messageA

Release this process's active claim without acknowledging the message.

NameRequiredDescriptionDefault
message_idYes

Output Schema

NameRequiredDescription

No output parameters

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full behavioral burden. It discloses the central effect—releasing the active claim without acknowledging the message—but does not clarify edge cases, required permissions, idempotency, or behavior when no active claim exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The definition is a single front-loaded sentence with no filler. Every phrase contributes to specifying the operation and its contrast with acknowledgement.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value detail is not required, and the operation is simple with one parameter. However, the absence of annotations and the lack of usage or parameter guidance leave meaningful gaps for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the single parameter, message_id, is undocumented in the schema. The description does not mention the parameter or explain its role, so it fails to compensate for the missing schema semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb, 'Release', and names the concrete resource, 'this process's active claim', making the operation identifiable. The phrase 'without acknowledging the message' also distinguishes it from acknowledgement-oriented siblings such as mark_read.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when this tool applies by contrasting it with acknowledging the message, but it does not explicitly state when to choose it over siblings like mark_read or claim_message. Usage is inferable but not fully guided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

send_messageA

Send a message to another agent; sender is this process's AGENT_ID.

reply_to optionally links this message to the id of a previous message (use it to answer requests). response_timeout_seconds (clamped to 1..3600) is persisted as response_deadline = now + timeout: pure metadata for the receiver — nothing is timed, deleted or resent automatically; after a deadline report it and wait for human direction, late replies stay valid. dedup_key (e.g. a task id): repeating the same (sender, dedup_key) returns the existing message with duplicate=true and inserts nothing. Returns the message id either way.

Conversation messages belong to a bounded autonomous dialogue (see start_conversation): pass conversation_id and kind — 'task' (substantive work that wakes the recipient's listener), 'result' (report on a task; wakes the initiator's review worker only while the conversation is active) or 'notice' (informational, never wakes a worker). Omit conversation_id to inherit it from the conversation of reply_to. Conversation sends are validated atomically: the dialogue must be active and unexpired, the message must answer its task/result and go back to that message's sender, exactly one message may be in flight, and each task/result takes one turn (a send past the turn limit moves the conversation to needs_human and is rejected). A send_message without kind is a plain message and never becomes autonomous.

NameRequiredDescriptionDefault
kindNo
textYes
reply_toNo
dedup_keyNo
recipientYes
conversation_idNo
response_timeout_secondsNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so well: it discloses that response_timeout_seconds is pure metadata with nothing timed, deleted, or resent, that duplicate (sender, dedup_key) inserts return the existing message with duplicate=true, and that conversation sends are validated atomically with an in-flight limit and turn limits that reject and move to needs_human. These are non-obvious side effects an agent could not infer.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the one-line purpose, then organized by topic (reply/timeout, dedup, conversation semantics). It is long, but nearly every clause carries operational detail; the parenthetical 'e.g. a task id' is the only clearly disposable fragment.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 7-parameter mutation tool with no annotations and an output schema present, the description covers side effects, idempotency, validation failure modes, and parameter interactions. Nothing an agent needs to call it safely is missing, and return values are correctly delegated to the output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across 7 parameters, so the description must compensate and does: it defines reply_to, dedup_key semantics, conversation_id inheritance from reply_to, the clamp range and default persistence for response_timeout_seconds, and the three kind values with their differing wake behavior. Only recipient and text are left implicit, which is reasonable given their names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Send a message to another agent') and pins down the implicit sender identity ('this process's AGENT_ID'), which the agent could not know otherwise. It is immediately distinguishable from the receiving-side siblings (receive_messages, claim_message, release_message).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives concrete conditional guidance: use reply_to to answer requests, use dedup_key for idempotent retries, pass conversation_id/kind for dialogue sends, and omit kind for a plain message. It also directs behavior after a deadline ('report it and wait for human direction'). It stops short of explicitly stating when to prefer start_conversation over a plain send, which is the main missing routing cue.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

start_conversationA

Start a bounded autonomous conversation with another agent.

Creates a conversation (goal, initiator = AGENT_ID, recipient, state active) and posts its root task as turn 1, so the recipient's listener picks it up without any manual phrase. The two agents then exchange task/result messages inside this conversation until one marks it completed or needs_human, the turn limit or expiry is reached, or it is cancelled. The limit counts every automatic worker turn (result reviews included); max_turns is clamped to 2..20 (hard cap 20) and the expiry window to 60..86400 s. A worker reaching the limit or a stopped state must not spawn new work: the dialogue goes to needs_human for a human. dedup_key makes repeated starts idempotent (existing root task, duplicate=true). An ordinary send_message never creates a conversation.

NameRequiredDescriptionDefault
goalYes
dedup_keyNo
max_turnsNo
recipientYes
expires_in_secondsNo
response_timeout_secondsNo

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and does so richly: it discloses the conversational state machine, the auto-posted root task as turn 1, the turn accounting rule ('counts every automatic worker turn, result reviews included'), clamping ranges, the needs_human escalation path, and dedup idempotency returning duplicate=true. This is exactly the behavioral context an agent cannot infer from the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose then behavior, and nearly every clause adds operational information. It is somewhat dense and the parenthetical '(goal, initiator = AGENT_ID, recipient, state active)' plus the mid-sentence line break cost a little readability, but there is little true waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a six-parameter state-creating tool with an output schema and no annotations, the description covers lifecycle, limits, escalation, idempotency, and the sibling distinction. An agent has everything needed to invoke it correctly; only response_timeout_seconds is left to the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate, and it does for five of six parameters: max_turns (clamped 2..20, hard cap 20, counts all worker turns), expires_in_seconds (60..86400 s window), dedup_key (idempotent restart semantics), recipient (listener picks up), goal (posted as root task/turn 1). response_timeout_seconds is never mentioned, leaving one parameter's meaning entirely undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence states a specific verb and resource — 'Start a bounded autonomous conversation with another agent' — and the closing sentence explicitly contrasts it with the sibling send_message ('An ordinary send_message never creates a conversation'). An agent can distinguish it from conversation, listener, and send_message without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear triggering context ('so the recipient's listener picks it up without any manual phrase'), names the alternative that does NOT apply (send_message), and specifies when the conversation ends (completed, needs_human, turn limit, expiry, cancellation). No explicit 'prefer X when Y' for the other siblings like claim_message, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 8 tool updatesv0.1.0
    • First observedclaim_message
    • First observedconversation
    • First observedlistener
    • First observedmark_read
    • First observedreceive_messages
    • First observedrelease_message
    • First observedsend_message
    • First observedstart_conversation

TDQS

A3.9/5.0

Scored across 8 tools

Disambiguation4/5

Most tools target clearly distinct operations: listener controls the local daemon, send_message emits, receive_messages reads, and claim/release/mark_read handle message ownership and acknowledgement. The main soft spots are send_message versus start_conversation (start implicitly posts a root task) and receive_messages versus claim_message, though the descriptions spell out the difference reasonably well.

Naming Consistency4/5

Six of eight tools follow a clear verb_noun pattern (send_message, start_conversation, claim_message, release_message, receive_messages, mark_read), which is highly readable. The two outliers, 'listener' and 'conversation', are bare nouns, a minor deviation from the otherwise predictable convention.

Tool Count5/5

Eight tools is a well-scoped surface for an inter-agent messaging bridge, with each tool covering a distinct lifecycle step (dispatch, inbox, claim lease, ack, conversation control). No tool looks redundant or gratuitous.

Completeness4/5

The message lifecycle is well covered end-to-end: send with dedup/reply linking, receive, atomic claim with lease, release, acknowledge, plus bounded conversation start/inspect/steer and listener enable/disable. Minor gaps remain — there is no direct 'get message by id' or 'list conversations' operation, so agents must go through receive_messages or track ids themselves.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to create, query, update, claim, hand off, and complete tasks on a local SQLite-backed, project-namespaced kanban board through stdio MCP tools, including filtering for ready/blocked/stale work and exchanging task attachments. It also lets agents list projects and manage statuses, ownership, and evidence without any server or accounts.
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables Claude Code, Codex and opencode sessions on the same machine to message each other live over a local pipe, with threaded replies and offline queuing, and to delegate or spawn one another as background subagents. Messages persist in SQLite and any running server can take over as broker, so peers stay reachable without a daemon.
    62 npm
    3
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables coding agents in different editors and MCP clients to share messages, project context, notes, task ownership, handoffs, and advisory file claims through a local SQLite-backed coordination server. Supports MCP stdio, MCP Streamable HTTP, a JSON HTTP API, and a local CLI for multi-project agent collaboration.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables coding-agent sessions on the same machine to collaborate locally and durably by exchanging requests, replies, and task results through an authenticated loopback server with SQLite-backed storage, joined via CLI or an MCP stdio bridge. It also handles message delivery by priority and wait time, deduplicates idempotent sends, enforces task versioning, and preserves artifacts by content hash.
    10 npm
    Apache 2.0