MCP server adapter for Pluto agent coordination. Provides tools for multi-agent messaging, inbox management, lock coordination, and task orchestration via the Pluto coordination server.
Pluto MCP Friend provides 18 well-named tools with consistent pluto_* prefix and clear action verbs (send, broadcast, recv, pop, acquire, release, create, update, get, list). All tools have descriptions (avg ~150 chars, within 10-1024 baseline). Input schemas are present with type declarations and parameter descriptions. However, output schemas are NOT documented, tool descriptions state what is returned (e.g., '{status, lock_ref, ...}') but lack formal JSON Schema definitions. Error handling is mentioned in descriptions (e.g., 'returns {status: error, reason: invalid_mode}') but recovery guidance is sparse. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk classifications in the spec. Parameter descriptions are adequate but lack format constraints (e.g., timeout_s has no min/max bounds). Composition is strong, tools chain well (e.g., lock_acquire → lock_renew → lock_release) and each has a single responsibility.
Broadcast a message to every connected Pluto agent. Use sparingly — direct messages are preferred when the audience is known.
Send a heartbeat to the Pluto server to keep the session alive and check for pending messages. Returns {status: 'ok'} plus any pending inbox messages as _pluto_inbox.
Single-slice inbox watcher: blocks up to wait_timeout_s (default: the launcher's --wait-timeout-s) for fresh messages, then returns. A concurrent call for the same inbox_id returns {already_watching: true} instead of stacking a loop. Watcher subagents sharing the parent's MCP server MUST pass drain=false (non-consuming snapshot) — drain=true pops and acks the parent's inbox.
List all agents currently connected to the Pluto server. Returns {status: 'ok', agents: [...]}, where each agent has id, status, and other metadata.
Acquire an exclusive lock on a resource. Blocks until the lock is granted or timeout_s elapses. Returns {status, lock_ref, ...} on success; {status: 'timeout'} if the wait expires.
Output schemas not formally documented. Tool descriptions mention return structure (e.g., '{status, lock_ref, ...}') but lack JSON Schema definitions. LLMs cannot reliably parse or chain results without explicit output schemas.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) despite clear risk classifications. Tools marked WRITE (pluto_send, pluto_broadcast, pluto_lock_acquire, pluto_task_create) should declare destructiveHint=true; READ_ONLY tools should declare readOnlyHint=true.
Numeric parameters lack bounds. timeout_s, wait_s, wait_timeout_s, max_total_s have no min/max constraints in descriptions. LLMs may pass absurd values (negative, zero, millions) causing timeouts or errors.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | <=2025-11-25 | v2 |
Release a previously acquired lock. Returns {status: 'ok'} on success.
Renew an active lock to extend its TTL. Returns {status: 'ok'} on success; {status: 'error', reason: 'lock_lost'} if the lock was already released or expired.
Query the status of a lock: who holds it, when it expires, and how many agents are waiting. Returns {status: 'ok', holder, expires_at, waiters} or {status: 'error'} if the lock does not exist.
Pop and ack ONE inbox message; returns {message, remaining, empty, delivery_mode}. Pair with delivery mode 'single' so unrelated tool calls don't bulk-drain the buffer. wait_s>0 blocks up to that many seconds for the next arrival.
Drain pending Pluto inbox messages addressed to this agent. Call this at the start of any turn where you have not already invoked another Pluto tool. Returns {'messages': [...]} where each message has at least 'event', 'from', 'payload', and 'seq_token' fields. Returns immediately even if no messages are pending — use pluto_wait_for_messages if you want to block until one arrives.
Send a direct message to another Pluto agent. The recipient must be registered with the same Pluto server. Returns the raw server response with status='ok' on success.
Query live server statistics: message counts, lock operations, agent registrations, and performance metrics. Returns {status: 'ok', stats: {...}}.
Set inbox delivery mode: 'batch' (default; drains everything per pluto_recv/piggyback — turn-driven work) or 'single' (one message per pluto_pop/piggyback — pipeline work). Invalid modes return {status: 'error', reason: 'invalid_mode'}.
Create a new task and optionally assign it to an agent. Returns {status: 'ok', task_id, ...} on success.
Retrieve task details by ID. Returns {status: 'ok', task: {...}} on success.
List all tasks, optionally filtered by status or assignee. Returns {status: 'ok', tasks: [...]}.
Update task status, assignment, or metadata. Returns {status: 'ok'} on success.
Block until at least one Pluto message arrives or timeout_s elapses (default: the launcher's --wait-timeout-s). Returns the drained-and-acked messages; [] on timeout.
Error recovery guidance is minimal. Descriptions mention error responses (e.g., '{status: error, reason: invalid_mode}') but do not guide LLMs on next steps. E.g., pluto_set_delivery_mode should suggest 'If mode is invalid, check available modes: batch, single.'
pluto_task_list lacks pagination parameters (limit, offset, cursor). Returning all tasks without pagination risks context window exhaustion and violates the paginated-result pattern.