arizuko › reference › MCP tools
Every Model Context Protocol tool the arizuko platform registers on a per-group unix socket. Generated from ipc/ipc.go and ipc/inspect.go. The tool set a given session sees is filtered by grants.MatchingRules against the group's rule list — tools whose name doesn't match any rule are not registered. A handful of tools also gate registration on tier (e.g. list_acl is tier 0–1; set_web_host is tier 0 only).
["*"]). Tier 1 = inner group (full platform-scoped send + group ops). Tier 2 = guest (basic send + folder-scoped routes). Tier 3+ = stranger (reply/send_file/like/edit only). Defaults live in grants/grants.go DeriveRules. Many tools also do inline auth.Authorize checks past the grant filter.
post tier 0–2Create a new top-level post on a platform (mastodon toot, bluesky post, discord channel message, reddit submission). Use for broadcast/announcement content that isn't replying to anyone. Not for replies (reply), direct messages (send), or file delivery (send_file).
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Target chat JID; grant-checked + folder-authorized. |
| content | string | yes | Post body. |
| media | array | no | Filepaths under ~/; validated by mountsec. |
Returns: JSON {"ok": true, "id": "<platformId>"}; on adapter "unsupported", returns error text with platform hint.
replyDeliver a message threaded to a specific earlier message (quote/reply UI on the platform). Use when disambiguating which message you're answering in an active chat, or when replyToId is known. Defaults to the last outbound reply id if omitted. Not for fresh top-level messages (send).
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Target chat JID. |
| text | string | yes | Reply body. |
| replyToId | string | no | Platform message id to thread to; defaults to db.GetLastReplyID(jid, ""). |
Returns: text "ok"; outbound recorded into messages with the returned platform id.
sendDeliver a new top-level message to a chat. Use for the normal reply to the user's last message or for a proactive notification. Not for threaded replies (reply) or file delivery (send_file — its caption replaces this call).
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Target chat JID; grant-checked + folder-authorized via authorizeJID. |
| text | string | yes | Message body. |
Returns: text "ok"; outbound recorded into messages with the platform-returned id.
send_fileDeliver a file from the group workspace (~/) to a chat. Works on every platform whose channel registered the tool. The caption IS the accompanying message — never follow with send. Not for inline text the user can read in-chat.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Target chat JID. |
| filepath | string | yes | Must be under /home/node/ (the group workspace mount). |
| filename | string | no | Display filename in chat. |
| caption | string | no | Message text accompanying the file — this IS the message; don't output separate text. |
Returns: text "ok".
send_voiceDeliver text as a synthesized voice message on the platform — push-to-talk on Telegram/WhatsApp, audio attachment on Discord. voice defaults to PERSONA.md frontmatter or the instance default; pass an explicit name to override.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Target chat JID. |
| text | string | yes | Text to synthesize; non-empty, ≤ 5000 chars. |
| voice | string | no | Voice name (e.g. af_bella for Kokoro). Omit to use PERSONA.md or instance default. |
Returns: JSON {"ok": true, "id": "<platformId>"}; on adapter unsupported, error text with platform hint.
All registered via the regSocial/socialAct helper at ipc/ipc.go:826. All take string args; the first arg (or jidArg) is grant-checked + folder-authorized. All adapter errors are rendered through toolMaybeUnsupported, surfacing the platform hint to the agent.
deleteDelete a post/message previously created by this agent (platform enforces authorship). Use to retract an incorrect or superseded post. No edit tool — delete and re-post.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Chat the message lives in. |
| targetId | string | yes | Platform id of message to delete. |
Returns: text "ok".
dislikeEndorse-negative on a message (Discord 👎 reaction). Native only — Mastodon, Bluesky, and most platforms have no native downvote and return unsupported with a hint.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Chat the message lives in. |
| targetId | string | yes | Platform id to downvote. |
Returns: text "ok".
editModify a message previously sent by this agent in-place (Discord, Mastodon, Bluesky, Telegram own bot messages). Preserves the platform message id. Email is unsupported.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Chat the message lives in. |
| targetId | string | yes | Platform id of message to edit. |
| content | string | yes | New content. |
Returns: text "ok".
forwardRedeliver an existing message to a different chat with provenance preserved (Telegram forward, WhatsApp forward, email Fwd:). Not for replying within the same chat (reply) or amplifying on a public feed (repost / quote).
| name | type | req | description |
|---|---|---|---|
| sourceMsgId | string | yes | Platform id to forward. |
| targetJid | string | yes | Destination chat JID; grant-checked. |
| comment | string | no | Optional accompanying text. |
Returns: JSON {"ok": true, "id": "<platformId>"}.
likeLike an existing message (unicode emoji on Discord, favourite on Mastodon, like on Bluesky). Use when acknowledging or endorsing a specific earlier message without sending text. Platform decides what reaction strings are valid; unsupported platforms return an error.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Chat the message lives in. |
| targetId | string | yes | Platform id to react to. |
| reaction | string | yes | Platform-specific reaction (emoji on Discord; like/favorite on Mastodon/Bluesky). |
Returns: text "ok".
quoteRepublish a message on your own feed with added commentary (Bluesky quote, X quote-tweet). Native only — Mastodon has no quote primitive and returns unsupported with a hint to use post(content=..., source_url=...).
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Destination feed JID. |
| sourceMsgId | string | yes | Message to quote. |
| comment | string | yes | Your commentary. |
Returns: JSON {"ok": true, "id": "<platformId>"}.
repostAmplify a message on your own feed without added text (Mastodon boost, Bluesky repost, X retweet). Use to endorse-and-share. Not for commentary (quote) or sending a copy to a different chat (forward).
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Destination feed JID. |
| sourceMsgId | string | yes | Message to amplify. |
Returns: JSON {"ok": true, "id": "<platformId>"}.
pin_messagePin a message to a chat/channel (Slack pins.add, Discord channel pin, Telegram pinned message). Use to mark a live status surface (deploy progress, standup link) or anchor a reference. Targets any message in the chat — not author-scoped like edit/delete. Mastodon, Bluesky, Reddit, email, WhatsApp return unsupported.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Chat the message lives in. |
| targetId | string | yes | Platform id of the message to pin. |
Returns: text "ok".
unpin_messageRemove the pin on a specific message (Slack pins.remove, Discord channel unpin, Telegram unpinChatMessage). Use to retire a status surface or rotate the pinned reference. Not for clearing every pin (unpin_all) or deleting the message (delete).
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Chat the message lives in. |
| targetId | string | yes | Platform id of the message to unpin. |
Returns: text "ok".
unpin_allClear every pin in a chat/channel (Slack iterates pins.list + pins.remove; Telegram unpinAllChatMessages). Use when wholesale resetting a channel's pinned set. Discord has no bulk primitive — call unpin_message per id.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | Chat whose pins to clear. |
Returns: text "ok".
fetch_historyPull authoritative conversation history from the channel adapter and cache it. Use to reconstruct context before replying, especially on first contact or after a reset_session. Falls back to local cache if the adapter is down. Not for DB/routing audits (inspect_messages) or single-thread slices (get_thread).
| name | type | req | description |
|---|---|---|---|
| chat_jid | string | yes | Chat to fetch. |
| limit | number | no | Default 100; clamped to (0, 200]. |
| before | string | no | RFC3339 cursor. |
Returns: JSON {messages, count, oldest, source, cap}. source is platform / platform-capped / cache-only / unsupported / cache; messages rendered by router.FormatMessages.
get_historyDEPRECATED alias for inspect_messages. Same handler, same params, same return. Do not use in new code — pick inspect_messages for whole-chat DB audit, get_thread for a single (chat_jid, topic) slice, or fetch_history for platform-truth context.
| name | type | req | description |
|---|---|---|---|
| chat_jid | string | yes | Chat to query. |
| limit | number | no | Default 100; clamped to (0, 200]. |
| before | string | no | RFC3339 cursor. |
Returns: JSON {messages, count, oldest, source:"local-db"}.
get_threadReturn rows from local messages.db scoped to one thread (chat_jid + topic). Use when a chat fans out into per-topic conversations (Telegram forum topics, web-chat topics).
| name | type | req | description |
|---|---|---|---|
| chat_jid | string | yes | Chat to query. |
| topic | string | yes | Topic / thread key. |
| limit | number | no | Default 50; clamped to (0, 100]. |
| before | string | no | RFC3339 cursor. |
Returns: JSON {messages, count, oldest, source:"local-db"}.
inspect_messagesReturn rows from the local messages.db for one chat_jid, including outbound/bot rows and errored entries. Use for routing/delivery audits or to verify what the store recorded.
| name | type | req | description |
|---|---|---|---|
| chat_jid | string | yes | Chat to query. |
| limit | number | no | Default 100; clamped to (0, 200]. |
| before | string | no | RFC3339 cursor. |
Returns: JSON {messages, count, oldest, source:"local-db"}.
find_messagesFull-text search over local messages.db using SQLite FTS5. query takes FTS5 syntax — a bare token, a "quoted phrase", a OR b, a NOT b, prefix*, or NEAR(a b, 5). Use to find a past message by what it said. Not for whole-chat scroll (inspect_messages), single-thread slices (get_thread), or platform-truth fallback (fetch_history).
| name | type | req | description |
|---|---|---|---|
| query | string | yes | FTS5 query — token, phrase, OR/NOT, prefix*, NEAR(...). Malformed syntax surfaces the SQLite error. |
| scope | string | no | One chat_jid (contains :) or a folder subtree (no :; matches routed_to and its children). |
| sender | string | no | Exact match on the sender column. |
| since | string | no | RFC3339 lower bound (inclusive) on timestamp. |
| limit | number | no | Max rows; default 20, clamped to (0, 200]. |
Returns: JSON {messages, count, source:"local-db"}. Each row carries chat_jid, sender, timestamp, content (a snippet() fragment with «» around the hit, not the full body), and rank (BM25 — lower is a better match). Ordered by rank, then newest first.
inspect_routingReturn routes visible to this group plus the errored-chat aggregate; pass jid to also resolve that JID to its folder. Use when a message isn't reaching the expected group, or to triage delivery failures.
| name | type | req | description |
|---|---|---|---|
| jid | string | no | JID to resolve; non-root callers may only resolve JIDs routed to their folder. |
| limit | number | no | Default 50; clamped to (0, 200]. |
Returns: JSON {routes, errored?, jid?, resolved_folder?}.
inspect_sessionReturn current session_id for this group/topic plus recent session_log rows (message counts, last error, last reset). Use to check whether context is healthy. Not for clearing state (reset_session).
| name | type | req | description |
|---|---|---|---|
| topic | string | no | Topic key; default empty (root topic). |
| limit | number | no | Default 10; clamped to (0, 100]. |
Returns: JSON {folder, topic, session_id, recent}.
inspect_tasksReturn tasks visible to this group; pass task_id for that task's recent run logs (durations, errors). Use to debug why a scheduled prompt didn't fire or failed.
| name | type | req | description |
|---|---|---|---|
| task_id | string | no | Specific task; if omitted, returns the full visible list with no runs. |
| limit | number | no | Default 50; clamped to (0, 200]. |
Returns: JSON {tasks, runs?}.
delegate_group tier 0–1Hand a prompt down to a specific child group for async execution; the child runs in its own session and workspace. Depth capped at 1.
| name | type | req | description |
|---|---|---|---|
| group | string | yes | Target child folder. |
| prompt | string | yes | Prompt body delivered as a synthetic message. |
| chatJid | string | yes | JID used as ForwardedFrom provenance. |
| depth | number | no | Caller-passed depth counter; rejected when ≥ 1. |
Returns: JSON {"queued": true}; enqueues a message-check for the target.
escalate_group tier 0–1Hand a prompt up to this group's parent folder; the parent responds back through this child. Use when the request exceeds this group's authority or needs operator review. Depth capped at 1.
| name | type | req | description |
|---|---|---|---|
| prompt | string | yes | Prompt to bubble up. |
| chatJid | string | yes | Originating chat JID (for reply_to in the wrap). |
| depth | number | no | Caller-passed depth counter; rejected when ≥ 1. |
Returns: JSON {"queued": true, "parent": "<folder>"}.
refresh_groups tier 0–2Return folder/name/parent for every registered group. Use to discover delegation targets or audit the group tree.
Params: none. Returns: JSON array of {folder, name, parent?}.
register_group tier 0–1Create a child agent group and route a JID to it. Use when onboarding a new chat into its own isolated workspace, or when spinning up a sub-agent from this group's prototype/ (fromPrototype=true).
| name | type | req | description |
|---|---|---|---|
| jid | string | yes | Source chat JID to route into the new group. |
| name | string | no | Display name; defaults to the JID. |
| fromPrototype | boolean | no | If true, spawn a child via SpawnGroup(parentFolder, jid); folder is derived. |
| folder | string | no | Required when fromPrototype=false. Target folder path. |
| parent | string | no | Parent folder (for tree). |
Returns: JSON {"registered": true, "folder": "<f>", "jid": "<jid>"}; SetupGroup seeds skills/settings/tasks.
set_group_open tier 0–1Toggle this group's visibility to sibling folders. When open=true, sibling folders' ambient messages surface in this group's <observed> block (and this group's messages surface to open siblings). Default: open. Use to seal off a sensitive folder from cross-folder ambient context. Spec: 6/F. Concept: scopes.
| name | type | req | description |
|---|---|---|---|
| open | bool | yes | true to expose to siblings, false to seal off. |
Returns: JSON {"ok": true, "open": <bool>}.
set_observe_windowOverride this group's ambient observe-window caps (messages and/or chars). Per-group caps win over instance env defaults (OBSERVE_WINDOW_MESSAGES, OBSERVE_WINDOW_CHARS); per-route caps still win over both. Pass -1 to clear an override; omit a field to leave it unchanged. Spec: 6/F.
| name | type | req | description |
|---|---|---|---|
| messages | number | no | Max ambient messages surfaced per turn; -1 clears override. At least one of messages / chars must be present. |
| chars | number | no | Max ambient chars per turn; -1 clears override. |
Returns: JSON {"ok": true, "messages": <n>, "chars": <n>}.
get_workRead this group's work.md — current work, blockers, next steps. Use at the start of a turn to recover what was in-flight. Returns empty content when the file doesn't exist.
Params: none. Returns: JSON {content, exists}.
inject_messageWrite a synthetic inbound message into the store as if received from chat, triggering the normal agent loop. Use for programmatic prompts, tests, or scheduling one-off runs from tool code.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | JID the synthetic message is bound to. |
| content | string | yes | Message body. |
| sender | string | no | Defaults to "system". |
| senderName | string | no | Defaults to "system". |
Returns: JSON {"injected": true, "id": "<mid>"}.
fork_topicBranch a topic from another’s current state. The gateway copies the parent’s Claude Code session file to a fresh session_id, so the child resumes natively with the parent’s history already in its session — no prompt-injection block. Use when starting a focused side-conversation that needs the parent’s recent state but should not pollute it. Pass force=true to overwrite an existing child. Spec: 6/F.
| name | type | req | description |
|---|---|---|---|
| parent | string | yes | Parent topic to fork from ("" = main). |
| child | string | yes | New child topic name. |
| force | bool | no | Overwrite the child if it already exists. |
Returns: JSON {"folder", "parent_topic", "child_topic"}. Error "topic_exists" when child exists and force=false.
pane_set_promptsSlack only — stage suggested-prompt buttons shown at the bottom of the assistant pane after your next reply lands. Fire-and-forget; the buttons appear once and persist until your next call. Use after a reply when you can anticipate the user’s likely follow-ups (e.g. “dig deeper”, “summarise”, “export”). 3-4 prompts is the visible cap. Adapters without pane semantics return chanlib.ErrUnsupported. Spec: 6/D. Concept: slack pane.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | JID of the pane DM channel (slack DM). |
| prompts | [{title, message}] | yes | Title shows on the button; message is sent as user input on click. |
Returns: text "ok".
pane_set_titleSlack only — override the title shown at the top of the assistant pane. Fires after your next reply lands. Use to reflect the active topic (e.g. “atlas — debugging the build”). Defaults to <assistant> — chat when never set. Spec: 6/D.
| name | type | req | description |
|---|---|---|---|
| chatJid | string | yes | JID of the pane DM channel. |
| title | string | yes | Title (max 256 chars; non-empty). |
Returns: text "ok".
engageMark (jid, topic) engaged for the ENGAGEMENT_TTL window so subsequent inbounds fire even when the route table wouldn't route them here. Use before a scheduled or autonomous turn, or to recover after a failed reply. Caller folder must already own the conversation (last reply here, or default route here). Spec: 5/G.
| name | type | req | description |
|---|---|---|---|
| jid | string | yes | Chat JID to engage. |
| topic | string | no | Topic to engage. Defaults to main topic when omitted. |
Returns: JSON {"ok": true}.
disengageClear engagement for (jid, topic). Subsequent inbounds need a fresh mention to re-fire. Use when the bot is done helping or when a corrective fork is closing. Caller folder must own the conversation. Spec: 5/G.
| name | type | req | description |
|---|---|---|---|
| jid | string | yes | Chat JID to disengage. |
| topic | string | no | Topic to disengage. Defaults to main topic when omitted. |
Returns: JSON {"ok": true}.
reset_sessionDrop the Claude session for a group so the next message starts fresh context. Use when the user asks for /new, when context is confused/polluted, or before a topic switch. Not for injecting content (inject_message).
| name | type | req | description |
|---|---|---|---|
| groupFolder | string | yes | Folder whose session to clear. |
Returns: text "ok".
set_work tier 0–2Overwrite this group's work.md with a fresh snapshot of current work, blockers, and next steps. Use at turn end to checkpoint state. This replaces the file — read with get_work first if merging.
| name | type | req | description |
|---|---|---|---|
| content | string | yes | New work.md contents. |
Returns: text "ok".
cancel_task tier 0–1Permanently delete a scheduled task. Use when the task is no longer wanted. Not for temporary suspension (pause_task) — this cannot be undone.
| name | type | req | description |
|---|---|---|---|
| taskId | string | yes | Task to delete. |
Returns: JSON {"ok": true}.
list_tasks tier 0–1Return scheduled tasks visible to this group. Use for a plain task dump; prefer inspect_tasks when you also want task_run_logs or per-task history.
Params: none. Returns: JSON array of core.Task.
pause_task tier 0–1Mark a scheduled task paused so it stops firing but is preserved. Use when suspending a task temporarily.
| name | type | req | description |
|---|---|---|---|
| taskId | string | yes | Task to pause. |
Returns: JSON {"ok": true}.
resume_task tier 0–1Re-activate a paused task so it resumes firing on its schedule. Use to undo pause_task. No effect on already-active or cancelled tasks.
| name | type | req | description |
|---|---|---|---|
| taskId | string | yes | Task to resume. |
Returns: JSON {"ok": true}.
schedule_task tier 0–1Create a scheduled prompt that fires against a target chat. cron accepts a 5-field cron expression, an integer millisecond interval, or an RFC3339 one-shot timestamp.
| name | type | req | description |
|---|---|---|---|
| targetJid | string | yes | Chat the task fires against; folder derived via DefaultFolderForJID. |
| prompt | string | yes | Prompt body delivered at fire time. |
| cron | string | no | 5-field cron, millis interval, or RFC3339 one-shot. |
| contextMode | string | no | group (default) or isolated. |
Returns: JSON {"taskId": "task-<ms>-<uuid8>"}.
add_route tier 0–1Append one routing rule. Preferred over set_routes for everything except full rewrites.
| name | type | req | description |
|---|---|---|---|
| route | string (JSON) | yes | JSON object: seq (int), match (key=glob pairs; keys: platform, room, chat_jid, sender, verb), target (folder path, or folder: / daemon: / builtin: prefix). |
Returns: JSON {"id": <routeId>}.
delete_route tier 0–1Remove one routing rule by id. Use after list_routes/inspect_routing to surgically drop a rule. Cannot delete the caller's own default route (seq=0, target=own folder).
| name | type | req | description |
|---|---|---|---|
| id | number | yes | Route id. |
Returns: JSON {"deleted": true, "id": <id>}.
list_routes tier 0–1Return the routing table rows this group can see. Use for a raw route dump; prefer inspect_routing when you also want JID→folder resolution or errored-chat context.
Params: none. Returns: JSON {"routes": [...]}.
set_routes tier 0–1Bulk-overwrite the full routing table for this folder subtree. Use only for wholesale reconfiguration; prefer add_route/delete_route for targeted edits.
| name | type | req | description |
|---|---|---|---|
| routes | string (JSON) | yes | JSON array of route objects (same shape as add_route). |
Returns: JSON {"updated": true, "count": <n>}.
list_acl tier 0–1Audit the unified acl rows whose scope equals the target folder. Subsumes the pre-v0.38.0 get_grants/set_grants surface; writes now happen via arizuko grant or the dashd UI, not over MCP.
| name | type | req | description |
|---|---|---|---|
| folder | string | yes | Folder to read. |
Returns: JSON {"folder": "<f>", "acl": [{principal, action, scope, effect, params, predicate}, ...]}.
invite_create tier 0–1Issue an invite token granting access to a path glob. The recipient accepts via /invite/<token> and gets an acl(admin, target_glob) row. The agent's authority must cover target_glob — you can't issue access you don't have.
| name | type | req | description |
|---|---|---|---|
| target_glob | string | yes | Path glob the invite confers access to. |
| max_uses | number | no | Default 1; min 1. |
| expires_at | string | no | RFC3339 timestamp. |
Returns: JSON {token, target_glob, max_uses, expires_at?, accept_url?}.
del_web_routeDelete a web route by path. Only routes owned by this folder may be deleted (operators can delete any).
| name | type | req | description |
|---|---|---|---|
| path | string | yes | Path prefix to remove. |
Returns: text "ok", or error if not found / not owned.
get_web_host tier 0–1Return the hostname currently bound to a folder (or this folder by default). Use to verify vhost wiring before pointing users at a URL. Non-root can only query own folder.
| name | type | req | description |
|---|---|---|---|
| folder | string | no | Folder to query; defaults to caller's folder. |
Returns: JSON {"hostname": "<host>", "folder": "<f>"}; hostname empty when no binding.
list_web_routesList all web routes owned by this folder.
Params: none. Returns: JSON array of {path_prefix, access, redirect_to, folder, created_at}.
set_web_host tier 0Bind a hostname to a group folder in vhosts.json so proxyd serves that folder at that host. Use when exposing a group's web/ via a custom domain.
| name | type | req | description |
|---|---|---|---|
| hostname | string | yes | Valid hostname (a–z, 0–9, . - :; ≤ 253 chars). |
| folder | string | yes | Must be an existing directory under GroupsDir. |
Returns: JSON of the full vhosts map after the write.
set_web_routeUpsert a web route: control whether a URL path is public, auth-gated, denied, or redirected. Scoped to the caller's folder.
| name | type | req | description |
|---|---|---|---|
| path | string | yes | URL path prefix; must start with /. |
| access | string | yes | One of public / auth / deny / redirect. |
| redirect_to | string | no | Required when access=redirect. |
Returns: text "ok".
inspect_identityResolve a platform sender sub (e.g. tg:123, discord:abc) to its canonical identity and the full set of subs claimed by that identity. Advisory only — agents query, never enforce. Returns {identity:null, subs:[]} when the sub is unclaimed.
| name | type | req | description |
|---|---|---|---|
| sub | string | yes | Platform sender sub to resolve. |
Returns: JSON {sub, identity, subs}.
submit_turnPer-turn agent result delivery. Not a tool — a JSON-RPC method on the same MCP unix socket. Hidden from tools/list; the agent loop calls it directly with the turn payload. Idempotency enforced by gated on (folder, turn_id).
| name | type | req | description |
|---|---|---|---|
| turn_id | string | yes | Unique per-turn id; enforces dedupe. |
| session_id | string | no | Claude session id. |
| status | string | no | success or error. |
| result | string | no | Final result text (on success). |
| error | string | no | Error text (on failure). |
Returns: JSON-RPC {"result": {"ok": true}}, or a JSON-RPC error.
log_external_costRecord one non-Anthropic LLM call against the folder's daily budget. Call this AFTER invoking an external model (e.g. codex exec --json for /oracle). Anthropic costs are captured automatically via submit_turn — this tool is for everything else the agent shells out to. Skipping it hides the call from cost-caps; the only operator-visible drift becomes the provider's own invoice. Spec 5/34. Registration is conditional on db.LogExternalCost being wired.
| name | type | req | description |
|---|---|---|---|
| provider | string | yes | openai, codex, other. |
| model | string | yes | Model identifier, e.g. gpt-5, codex-mini. |
| cost_usd | number | yes | USD cost reported by the provider; gateway rounds to cents. |
| input_tokens | number | no | Input token count (0 if unknown). |
| output_tokens | number | no | Output token count (0 if unknown). |
Returns: JSON {"ok": true, "cents": N}.
registerRaw consults grants.MatchingRules(rules, name); if no rule matches the tool name, the tool is never added to tools/list. The matched rules are appended to the tool description as grants: [...] so the agent sees what it has been granted.refresh_groups (tier ≤ 2), set_work (tier ≤ 2), list_acl (tier ≤ 1), get_web_host (tier ≤ 1), and set_web_host (tier == 0) wrap the AddTool call in a tier check — even at tier 0 with rules ["*"], tier-bracketing trumps glob match.authorizeJID after the grant check: a tier ≥ 1 caller cannot dispatch to a JID whose DefaultFolderForJID resolves outside the caller's folder subtree, even when grants would otherwise permit it.registerRaw, granted, regSocial, raw srv.AddTool. The registerWithSecrets/injectSecretsAdapter broker (spec 9/11) is wired but no tool declares requires=[...] yet — lookup at ipc/ipc.go:616.inspect_routing, inspect_tasks, inspect_session, inspect_identity, inspect_messages, find_messages (requires db.FindMessages), get_history, get_thread, fetch_history, all *_task tools (require db.GetTask).acl, routes, web_routes, secrets, scheduled tasks and the like are not per-group MCP tools — they are CRUD resources driven by the resreg engine and reachable over REST, MCP, YAML manifests, and /openapi.json from one struct. See OpenAPI and the gated registry.tier1FixedActions lists get_routes but the registered tool is list_routes; at tier 1 the default rules don't grant it without explicit override. See grants/grants.go:154.