Skip to content

Available Tools

Complete catalog of tools available through the MCP server and the TUI AI assistant. Tool availability depends on the safety mode.

Cloud Resources

DNS & Domains

Tool Safety Description
list_dns_zones Read List all DNS zones in the organization
list_dns_records Read List DNS records for a specific zone
list_domains Read List all registered domains with verification status
create_dns_record Write Create a DNS record in a zone
delete_dns_record Destructive Delete a DNS record

Compute

Tool Safety Description
list_servers Read List all servers in the current project
list_volumes Read List all block storage volumes
list_k8s_clusters Read List all Kubernetes clusters

Networking

Tool Safety Description
list_networks Read List all networks in the project
list_routers Read List all routers in the project
list_load_balancers Read List all load balancers in the project

Billing

Tool Safety Description
get_billing_usage Read Get billing usage and cost breakdown
list_invoices Read List all invoices for the organization

Organization

Tool Safety Description
list_members Read List organization members
list_projects Read List all projects in the organization

Tickets

Tool Safety Description
list_tickets Read List support tickets
get_ticket Read Get ticket details with comments
create_ticket Write Create a new support ticket
add_ticket_comment Write Add a comment to a ticket
delete_ticket Destructive Delete a support ticket

OpenProject (Project Management)

These tools talk to a self-hosted OpenProject instance. They are only available when openproject-url and openproject-api-key are configured — see the OpenProject integration guide.

Destructive operations (delete work package, archive project, delete time entry) are deliberately not implemented — use the OpenProject web UI.

Local conventions live in the mission repo

:pa reads OpenProject workflow conventions (status flows, required custom fields, time-entry rules, naming) from tools/operated/openproject.md in the mission control repo. Its body is delivered to the AI via mission_load_context (as the slug=openproject entry in the tools array) and can be refreshed mid-session with mission_tools slug=openproject. To customise how the assistant uses OpenProject in your org, edit that markdown file — no code change required.

Read

Tool Safety Description
op_list_projects Read List projects (filter by name substring or archived; default sort: name asc)
op_get_project Read Get one project by numeric ID or string identifier
op_list_work_packages Read List work packages. Default sort: updatedAt desc — most recently changed first, so "show me the 5 most recent" is just limit=5 (filters: project, assignee, status, type, query, open-only, updated-since)
op_get_work_package Read Get one work package's metadata by ID. Comments/journal are NOT included — use op_list_work_package_activities.
op_list_work_package_activities Read List the journal of one work package — comments and field-change history, oldest first. Each entry is typed (comment, change, or comment+change).
op_list_time_entries Read List time entries (default sort: spentOn desc; filters: user, project, work package, date range)
op_list_enums Read List statuses / types / priorities / time-entry activities — needed for filtering and creating
op_list_users Read List active users; filter by name substring

Conveniences:

  • Pass assignee=me or user=me and the AI resolves it to your user ID via /users/me.
  • Every list tool accepts sort_by (server field name) and sort_order (asc / desc). Defaults are picked so the AI usually doesn't have to specify them: WPs come back most-recently-updated first, time entries newest first, projects alphabetical.
  • query on op_list_work_packages is a substring match against subject text (also matches numeric IDs); it does NOT search description bodies.

Write

Every write tool requires explicit per-call confirmation, even when the AI session has autoAcceptWrites enabled. Free-text fields written by the AI (descriptions, comments, time-entry notes) are auto-suffixed with — via bnerd.ai so a future reader can grep OpenProject for AI-authored content. Successful writes append a JSONL entry to ~/.bnerd/openproject-audit.jsonl for local review.

Tool Safety Description
op_create_work_package Write Create a work package in a project (subject + type required)
op_update_work_package Write Update fields on a work package (subject, description, status, type, priority, assignee, dates). Optimistic concurrency handled internally via lockVersion.
op_add_comment Write Post a journal comment on a work package
op_log_time Write Create a time entry (decimal hours, e.g. 0.5 = 30 minutes)
op_update_time_entry Write Edit an existing time entry's hours / date / comment / activity

Pickup timers (:pa only)

These three wrap OpenProject's native ongoing time entries — a running timer is an OP time entry with ongoing=true, visible in the OP web UI from the moment it starts. Single timer per user; the wrapper enforces this client-side. Unlike the other write tools, timer tools are NOT confirm-gated — they fire on explicit pickup/finish chat actions.

Tool Safety Description
op_timer_start Write Start a pickup timer (creates an ongoing time entry). Errors if one is already running for the current user.
op_timer_stop Write Stop the active timer: computes elapsed from startTime → now, PATCHes ongoing=false + hours. Refuses elapsed under 1 minute or over 24 hours; pass hours=<decimal> to override and finalise anyway (also dismisses a stuck timer with corrupt/empty startTime, e.g. hours=0.01).
op_timer_status Read Report the active timer (id, work package, project, started_at, live elapsed) or {"active": false}.

Ticket-draft preview (:pa only)

pa_propose_ticket is a no-op-on-the-server stub that the chat session intercepts to render a full work-package draft for review before op_create_work_package ever fires. Unlike the standard write-confirmation modal — which truncates the description body — this view shows every populated field and the entire markdown body without any line cap.

Tool Safety Description
pa_propose_ticket Read Present a full ticket draft for review. Returns one of three JSON decisions: {"decision":"create"}, {"decision":"refine","feedback":"…"}, or {"decision":"cancel"}.

The PA system prompt requires the AI to call pa_propose_ticket first whenever you ask for a new ticket. On create, the AI then calls op_create_work_package with the same payload — that tool's standard confirmation still fires once as an integrity check. On refine, your typed notes are returned to the AI and it drafts a v2. On cancel, the AI drops it.

Inbox triage (multi-messenger, :pa only)

Source-agnostic triage surface across every configured messaging backend (Slack today, Email next, future Mattermost/Teams). Dispatched through the in-process inbox.Hub; each backend (a "source") implements the same MessageSource contract so the same tool call works regardless of which messenger an entry came from. Identifiers are namespaced as source:account:conv:msg (e.g. slack:default:C0123:1700.000200) so the AI can pass them back without ambiguity.

Tool Safety Description
inbox_list Read Newest-first entries across all sources. Optional source / account / limit filters. Each item carries explicit source and account fields plus the canonical id.
inbox_search Read Filter by channel (conversation id), user (sender id), text substring, since/until (RFC3339), include_archived. Optional source/account scoping.
inbox_unread Read Unread count (optionally scoped by source/account) and, with include_entries=true, the unread entries themselves.
inbox_mark_read Write Mark one entry read by id. The hub parses source/account from the id and routes to the right inbox.
inbox_dismiss Write Hide an entry from default lists. Still searchable via include_archived.
inbox_get_thread Read Fetch a thread root + replies via the source's native API (Slack conversations.replies, IMAP FETCH of the References chain). Takes explicit source/account/conv_id/thread_key.
inbox_propose_reply Read Source-aware full-preview proposal block (intercepted by the chat session). Returns {"decision":"send"} / {"decision":"refine","feedback":"…"} / {"decision":"cancel"}. ALWAYS call before inbox_send_reply — the body renders untruncated and the email path additionally surfaces Subject + Cc rows so the user can vet the full header. On send the AI calls inbox_send_reply with the matching source/account/conv_id/thread_key.
inbox_send_reply Write Post a reply via the right backend (Slack chat.postMessage, SMTP for email). Required: source, account, conv_id, body. Optional: thread_key, subject/cc for email. The configured signature suffix is appended automatically.

After acting on an item, the AI is expected to call inbox_mark_read or inbox_dismiss so the unread indicator stays accurate. The reply flow follows the same shape as ticket creation: inbox_propose_reply → user picks Send → AI calls inbox_send_reply (one extra confirm fires as integrity check). On refine, the user's notes are returned to the AI for a v2 draft.

Peek overlay (Ctrl-S) — multi-source surface. The TUI peek shows the merged stream across every configured source with [S] / [E] source badges. Keys 1 / 2 filter to Slack / Email; 0 returns to the merged view. The filter persists across overlay open/close so a focused triage session stays focused.

Slack triage (:pa only) — source-specific escape hatches

Optional integration that runs only when slack.enabled: true and a bot token are configured (see Slack setup). The Slack stack implements the unified inbox_* surface above; the per-source tools below remain registered for behaviour that has no source-agnostic equivalent (subscriptions, native search, watched threads) plus a deprecation window for the pre-unified inbox/reply tools.

Listener behaviour: filters incoming Slack events down to mentions, DMs, and replies in tracked threads, then persists them to a durable JSONL inbox under ~/.local/state/bnerd/slack-inbox/default/. Messages never auto-inject into the chat log — the indicator (📬 N in the header) and the Ctrl-S peek overlay are the user-facing surfaces; the AI triages on demand via the tools above.

Inbox reads & state (deprecated — prefer inbox_*)

Tool Safety Description
slack_inbox_list Read List recent inbox entries (newest-first JSON) including id, status (unread/read/dismissed), and via (live/catchup/backfill). Prefer inbox_list for new sessions.
slack_inbox_search Read Filter the local inbox by channel, user, text substring, since/until (RFC3339), and include_archived. Prefer inbox_search.
slack_inbox_unread Read Returns the unread count and (with include_entries=true) the unread entries themselves. Prefer inbox_unread.
slack_inbox_mark_read Write Mark one inbox entry (id from slack_inbox_list) as read. Prefer inbox_mark_read.
slack_inbox_dismiss Write Mark one inbox entry as explicitly noise. Prefer inbox_dismiss.
slack_get_thread Read Fetch a thread's root + replies from the Slack API for context (channel, thread_ts). Prefer inbox_get_thread.
slack_search Read Hits Slack's own search.messages index for queries that go beyond the local inbox window. Requires the optional slack.user-token (xoxp-…). No source-agnostic equivalent — Slack search is genuinely Slack-specific.

Outbound replies & ticket conversion

Tool Safety Description
slack_propose_reply Read Intercepted by the chat session — renders a full untruncated preview of the proposed reply with Send / Refine / Cancel options. Returns the user's decision as JSON, mirroring pa_propose_ticket. The unified inbox_propose_reply arrives in the unified-peek phase.
slack_send_reply Write Post the approved reply via Slack's chat.postMessage. The configured signature suffix (default — via bnerd.ai) is appended automatically. Prefer inbox_send_reply.

Watched threads (Slack-specific)

Tool Safety Description
slack_watch_thread Write Add a thread to the local watched-thread set so future replies surface in the inbox. Local-only persistence; no remote effect. Idempotent.
slack_unwatch_thread Write Remove a thread from the watched-thread set.

The reply flow mirrors ticket creation: slack_propose_reply → user picks Send → AI calls slack_send_reply (one extra confirm). On Refine, the user's notes are returned to the AI for a v2 draft. Posting in a channel auto-watches that thread so follow-ups land in the inbox.

After acting on an item (replying, ticketing, or deciding it's noise), the AI is expected to call slack_inbox_mark_read or slack_inbox_dismiss to keep the unread indicator accurate.

In :pa you can also press r to ask the AI to draft a reply to the latest Slack message, or t to turn the latest thread into an OpenProject ticket via slack_get_thread + pa_propose_ticket. The Ctrl-S peek overlay's r/t hotkeys do the same but target the row under the cursor instead of the most-recent event.

Relations & dependencies

Relations link two work packages — parent/child, blocks/blocked, precedes/follows, relates, duplicates/duplicated, includes/partof, requires/required. They answer "what's blocking the release?" and let the AI build dependency trees.

Tool Safety Description
op_list_relations Read All relations declared on one work package (both directions)
op_create_relation Write Link two work packages with a relation type (optional lag for follows/precedes)
op_delete_relation Destructive Remove a relation by ID. Unlinks two work packages — does NOT delete either work package. Reversible by re-creating the relation.

Watchers

Tool Safety Description
op_list_watchers Read Users currently watching a work package
op_add_watcher Write Subscribe a user (or me) to a work package
op_remove_watcher Destructive Unsubscribe a user. Reversible.

The "Destructive" classification on op_delete_relation and op_remove_watcher is intentional — they are DELETE operations under the hood and the safety model treats DELETE uniformly. They differ from primary-data deletes (which are not implemented at all) because the entities they unlink remain intact.

Versions, memberships, categories

Release planning + team visibility. Versions (a.k.a. milestones / releases) live inside a project; work packages can be assigned to a version via op_create_work_package/op_update_work_package. Memberships answer "who's on this project, in what role". Categories are project-level classifications optionally with a default assignee.

Tool Safety Description
op_list_versions Read List versions (filterable by project)
op_create_version Write Create a milestone in a project (name, dates, status, sharing)
op_list_memberships Read List project memberships + roles. Filter by project and/or principal (me)
op_list_categories Read List categories defined in one project

op_create_work_package and op_update_work_package accept version and category (numeric IDs). Pass empty string to clear an existing version/category on update.

Users (admin)

User CRUD against /api/v3/users. All write operations require admin rights on the configured OpenProject API key — non-admin tokens get an actionable "permission denied" error. Every write is gated by the standard per-call confirmation prompt and appends to the audit log.

Tool Safety Description
op_get_user Read Fetch one user (any status) by numeric ID. Use this before op_unlock_user since op_list_users only shows active accounts.
op_create_user Write Create a new user (login, first_name, last_name, email required). Omit password for SSO/LDAP instances; supply one for built-in auth. Optional admin, language, status.
op_update_user Write Sparse update — only supplied fields change. Includes optimistic concurrency via the resource's lockVersion.
op_set_user_password Write Reset a user's password to a new value. The password is sent to OpenProject but never written to the audit log (recorded as ***). Communicate the new password to the user out-of-band.
op_lock_user Write Lock the account (blocks login, preserves history). Reversible via op_unlock_user.
op_unlock_user Write Restore login access to a locked account. Implemented as DELETE /users/{id}/lock per the OP REST shape.

Notes:

  • Hard DELETE /users/{id} is intentionally not exposed — locking preserves references and is reversible.
  • Resending invitation emails is not in the OpenProject v3 API (only available in the admin web UI). The AI will advise you to use the OP UI for that workflow.

Groups (admin)

Group CRUD against /api/v3/groups. The same admin/confirmation/audit guarantees as users apply.

Tool Safety Description
op_list_groups Read List groups (id + name only). Use op_get_group for the member list.
op_get_group Read Fetch one group including its member user IDs.
op_create_group Write Create a group. Pass members as a comma-separated list of user IDs (e.g. "3,7,12"); omit for an empty group.
op_update_group Write Rename and/or replace the full member list. Omit members to leave members alone; pass empty string to clear them. Prefer the per-user tools below for single-member edits.
op_delete_group Destructive Dissolve a group. Member users are NOT deleted — only the group itself.
op_add_user_to_group Write Append one user to a group's members. No-op if already a member. Internally does a GET + PATCH using lockVersion for optimistic concurrency.
op_remove_user_from_group Write Drop one user from a group's members. No-op if not a member.

Form schemas & custom fields

Form-schema introspection lets the AI discover what fields exist before writing — eliminating "guess and 422" loops. Custom fields are supported on both create and update.

Tool Safety Description
op_describe_work_package_form Read Returns the schema for a work-package form: required/writable flags, allowed values for constrained fields (status, type, priority, …), and any custom fields the project defines. Pass project= for a new-WP schema, work_package= to introspect an existing WP, optionally narrow with type=.

op_create_work_package and op_update_work_package accept a custom_fields parameter — a JSON-stringified object mapping customFieldN keys to values:

  • Scalar values (string, number, bool) for text/integer/date/boolean custom fields → routed to the request body
  • HAL hrefs (e.g. "/api/v3/users/3" or "/api/v3/projects/3") for user/list/enum custom fields → routed to _links automatically

Recommended flow: call op_describe_work_package_form project=X type=Y first to see which custom fields exist and whether they expect scalars or hrefs, then pass them via custom_fields on the create/update call.

Notifications, saved queries, attachments

The leadership inbox + reusable filters + read-only file attachments.

Tool Safety Description
op_list_notifications Read Your in-app notifications, newest first. Filter unread_only=true and/or reason=mentioned (or assigned/watched/commented/…)
op_mark_notification_read Write Mark one notification read. Reversible by re-opening it in the UI
op_list_queries Read List saved queries (filters) the user has stored. Pass project= to scope.
op_run_query Read Execute a saved query and return its work packages — useful for reusing "My open bugs", "This sprint", etc. instead of reconstructing the filter
op_list_attachments Read Files attached to a work package — filename, size, content-type, download URL. Upload is not supported.

Kubernetes (Direct Cluster Access)

These tools interact directly with a Kubernetes cluster via kubeconfig.

Read Operations

Tool Safety Description
kube_cluster_info Read Cluster overview: version, nodes, capacity
kube_list_namespaces Read List namespaces with status and age
kube_list_nodes Read List nodes with status, roles, resources
kube_list_pods Read List pods (all namespaces or filtered)
kube_get_pod Read Detailed pod info: containers, conditions, events
kube_get_pod_logs Read Get pod logs (last N lines)
kube_list_deployments Read List deployments with replica counts
kube_list_services Read List services with type, IPs, ports
kube_list_ingresses Read List ingresses with hosts and TLS status
kube_list_configmaps Read List configmaps (keys only, not values)
kube_list_secrets Read List secrets (names and types only)
kube_list_pvcs Read List PersistentVolumeClaims
kube_list_statefulsets Read List StatefulSets
kube_list_daemonsets Read List DaemonSets
kube_list_jobs Read List Jobs
kube_list_events Read List recent events (up to 50)
kube_list_hpa Read List HorizontalPodAutoscalers
kube_describe Read Describe any resource (via kubectl)
kube_read_file Read Read a file inside a running pod
kube_list_dir Read List directory contents in a pod
kube_find_file Read Find files by pattern in a pod

Write Operations

Tool Safety Description
kube_scale Write Scale a Deployment/StatefulSet/ReplicaSet
kube_rollout_restart Write Rolling restart of a workload
kube_set_image Write Update container image
kube_label Write Add/update resource labels
kube_annotate Write Add/update resource annotations
kube_cordon Write Mark node as unschedulable
kube_uncordon Write Mark node as schedulable
kube_exec Write Execute command in a pod
kube_apply Write Apply a Kubernetes manifest
kube_apply_dry_run Write Dry-run validate a manifest

Destructive Operations

Tool Safety Description
kube_delete Destructive Delete a Kubernetes resource
kube_drain Destructive Drain a node (evict pods)

Helm

Tool Safety Description
helm_list Read List Helm releases
helm_status Read Get release status
helm_get_values Read Get release values
helm_upgrade Write Install or upgrade a release
helm_rollback Destructive Rollback to a previous revision
helm_uninstall Destructive Uninstall a release

File System

Tool Safety Description
fs_read_file Read Read a local file (max 128KB)
fs_list_dir Read List directory contents
fs_search_content Read Search file contents with regex
fs_glob Read Find files matching a glob pattern
fs_write_file Write Create or overwrite a file (not available in :pa)
fs_patch_file Write Patch a file with exact text replacement (not available in :pa)

Mission Control (:pa write surface)

:pa cannot write outside the mission repo. Writes flow through two families: typed proposals for the scheduling files (schema-validated and auto-archiving), and generic mission-scoped writes for everything else.

Tool Safety Description
mission_propose_today Write Propose / write today.md (typed; auto-archives prior day)
mission_propose_week Write Propose / write current.md (typed; auto-archives prior week)
mission_write_file Write Create or overwrite any other file inside the mission repo (rejects paths outside the repo and the two scheduling files)
mission_patch_file Write Surgical exact-text replacement inside any other mission-repo file (same path restrictions as mission_write_file)

Git

Tool Safety Description
git_status Read Show working tree status
git_diff Read Show changes (staged or unstaged)
git_log Read Show recent commit history
git_init Write Initialize a new repository
git_add Write Stage files for commit
git_commit Write Create a commit
git_push Destructive Push commits to remote

Shell

Tool Safety Description
shell_exec Write Execute a shell command

Web

Tool Safety Description
web_research Read Search the web and read top results
web_fetch Read Fetch a web page by URL

AI Internal

Tool Safety Description
think Read Think through a problem step-by-step
task_notes_write Read Save persistent working notes
task_notes_read Read Read saved working notes
get_current_context Read Get current session context
ask_question Read Ask the user a clarifying question
task_create Read Create a task to track progress
task_update Read Update task status
task_list Read List all tasks
save_report Write Save an investigation report