Skip to content

Firefight ships a Model Context Protocol server, so AI agents like Claude can take part in your incidents directly. An agent connected over MCP can search incidents, pull a full incident timeline, inspect alerts and how they routed, look up ownership in the service catalog, find what runs where on the resource map, and dry-run your alert routing rules. It can ask Halon, Firefight’s own agent, a question or start an investigation, and read logs, metrics and deploys of anything on the map through your integrations. With permission it can also work an incident the way a person does: declare one, raise and pick up work, claim a runbook step, pull people into the channel, ask a named person to respond, and close it out. It can maintain your catalog, runbooks and routing rules, and resolve approvals, too. Everything an agent does is recorded under Gateway → Activity.

The server speaks Streamable HTTP at a single endpoint.

POST https://app.firefight.app/mcp

All data is scoped to the workspace of the token you authenticate with.

There are three ways to connect, depending on what is doing the connecting.

Clients that support MCP OAuth, such as Claude Code, connect without you ever handling a token. Add the server and start using it.

Terminal window
claude mcp add --transport http firefight https://app.firefight.app/mcp

On first use, your browser opens Firefight’s consent screen. It names the client asking for access, the workspace it would reach and who you are signed in as, says what the client will be able to do, and shows where your browser goes once you authorize, such as an app on your own computer or the client’s website. Check that address before you click, and click Deny if you did not start the connection. If you belong to more than one workspace, pick the one you want it to reach. Click Authorize and the client is connected. The client registers itself automatically through dynamic client registration, PKCE is required, and access tokens are short-lived with refresh rotation. The connection acts as you, with the same access you have in the workspace.

An AI that takes part in incidents gets its own identity rather than borrowing yours. Create it under Gateway → Agents, which hands you its token once, and configure your client to send that.

Terminal window
claude mcp add --transport http firefight https://app.firefight.app/mcp \
--header "Authorization: Bearer ff_4kWm2xPqR8vNcT6yBhJd3fLzGaU9sEnQoXwA"

Everything the agent does is recorded under its own name, so an incident it declared says the agent declared it, and an action item it picked up shows the agent holding it. It holds only the abilities you granted it, whatever access you have yourself. Agent tokens do not expire. Rotate one at any time from its row. See Agents.

Automation with nothing to say on a timeline passes a Firefight API key as a Bearer token instead. Create one under Developer → API Keys, then configure your client to send it.

Terminal window
claude mcp add --transport http firefight https://app.firefight.app/mcp \
--header "Authorization: Bearer ff_4kWm2xPqR8vNcT6yBhJd3fLzGaU9sEnQoXwA"

For Cursor, put the same thing in .cursor/mcp.json.

{
"mcpServers": {
"firefight": {
"url": "https://app.firefight.app/mcp",
"headers": { "Authorization": "Bearer ff_4kWm2xPqR8vNcT6yBhJd3fLzGaU9sEnQoXwA" }
}
}
}

Any other MCP client works the same way, either through OAuth discovery at /.well-known/oauth-protected-resource or with the Authorization: Bearer header.

A connection reaches one workspace, whichever way you authenticated. An OAuth connection is granted for the single workspace you picked on the consent screen, and an API key belongs to the workspace you created it in. There is no setting that widens a connection to cover more.

To give an agent a second workspace, add the server again under a different name.

Terminal window
claude mcp add --transport http firefight-acme https://app.firefight.app/mcp

Authorize that one and pick the second workspace on the consent screen. For a headless agent, create an API key in the second workspace and pass it the same way. Each connection stands on its own, so its tools appear under the name you gave it, and revoking one leaves the other working.

An agent is told which workspace it reaches as soon as it connects, so you can ask it directly rather than working it out from what it returns.

The Connected agents list under Developer → API Keys shows the connections for the workspace you are viewing. Switch workspaces to see the rest.

These tools read your workspace and change nothing.

ToolWhat it returns
search_incidentsIncident summaries, newest first. Filter by status, severity, lifecycle stage, free-text query, and declared-at time range.
get_incidentOne incident in full, by ID or identifier like INC-42. Details, timeline events (each update with its message and the fields it changed), postmortem status, attached alerts, every incident role with whoever holds it, the open action items with any tracked issue’s link, the attached runbooks with their steps, and its pages in PagerDuty or Opsgenie with where each stands.
search_similarIncidents, postmortems and findings that read like a situation you describe, nearest first, each saying whether it is still open. Findings are included when the key may read investigations.
search_alertsIngested alerts, newest first. Each shows its source, firing status, routing state, the rule that matched, and the incident it attached to.
search_catalogCatalog entries with their attributes and relationships, such as which team owns a service. Filter by type, name query, or exact slug.
get_resource_mapThe first place to find which provider and account hold a named domain, service or database. Without a resource, every resource grouped by provider and account, with how each connection last read the map. Once the map holds 300 resources or more, it returns counts instead of a list, by provider, kind, environment and health, with the resources most others depend on, and names the tools below for finding the rest. With a resource’s name or ID, its fact sheet: where it runs, its page, the catalog services it runs and who owns them, what people confirmed about it, recent incidents on those services, what normal looks like for its metrics over the last week, the log lines it usually prints, its key checks, and every resource within two links with how each link was found. Only what runs in the environments the caller can read, see Permissions.
find_resourcesResources on the map, 50 to a page by default and up to 200. Filter by provider, kind, account, environment, status, health, owning team, catalog entry, provider tag (team or team=payments), exact details, the start of a name, or what changed since a time. Removed resources are left out unless you ask for them. Sort by name or by how many resources depend on each. Each row has the resource’s ID, which the other map tools take, and the total counts up to 10,000. Pass next_cursor back for the next page.
get_resourceOne resource by its name, its provider’s ID or its ID on the map. The same fact sheet as get_resource_map without the resources two links away, plus how many links lead in and out of it by relation.
get_resource_linksThe links into and out of one resource, 100 to a page by default and up to 500. Choose the direction, the relations, and whether you want confirmed links, suggestions or both. Each link reads as a sentence, such as “web uses orders-db”, and says how it was found. A suggestion also says how sure Firefight is and why.
get_resource_neighboursThe resources one link away from a resource, what it depends on and what depends on it, grouped by relation. Confirmed links only unless you ask for suggestions, and it says how many suggestions it left out. Up to 200 resources.
traverse_resource_mapFollows links from a resource towards what it depends on or what depends on it, 2 links by default and up to 6. Each resource reached says how many links away it is and which link reached it. Narrow it by relation or by kind. Up to 200 resources, and it says how many more it reached.
blast_radiusEverything that fails with a resource, up to 10 links away, counted by kind, provider and environment, the catalog services they run with the teams that own them, the open incidents on those services, and the 25 dependents most others rely on. What unconfirmed suggestions would add is counted separately and never in the total.
resource_map_statsThe map in numbers. Counts resources by provider, kind, account, environment, status or health, with the same filters as find_resources, and says how each connection last read the map, how many suggested links are waiting for someone to review, and what changed in the last day.
search_mapOne search across the map, the catalog and confirmed memories, ranked together with an exact name or id first. Give a query, such as a name, part of one, a tag or what a service does, and optionally types (resource, catalog_entry, memory) and the map’s filters, such as provider, kind, environment or owner. Each result says what it is, why it matched and links to the page that opens it. Only the kinds the credential may read are searched, and the response names any it left out. Page with next_cursor.
evaluate_routingA dry run of alert routing against hypothetical alert fields. Returns the matching rule, the outcome, a per-condition trace, and warnings when a routing role your rules depend on is not set on any catalog attribute. Nothing is created or notified.
search_runbooksRunbook listings with name, summary, other names, step count, whether Halon can run it, and the workflow each runs with whether it can run now. Filter by a query that matches the name, summary or another name.
get_runbookOne runbook in full, by slug. The complete procedure content, ordered steps (with the tool and arguments of a step Halon runs), external link, for a runbook Halon can run its inputs, other names and what it watches afterwards, and the workflow it runs with that workflow’s steps, questions and page.
list_skillsYour workspace’s own skills, with when Halon uses each, whether it is on, its version and how many workflows run it.
get_skillOne skill in full, by name or ID: its tools, its steps and the version to send back when changing it.
list_workflowsYour workflows, each with its name and other names, what starts it, whether it is live, when it runs next, how its last run went, its steps and the inputs a run asks for.
list_handbook_pagesThe handbook pages in the order Halon reads them, each with its kind, link and length.
get_handbook_pageOne handbook page in full, by its ID or title, with the wording_id an edit sends back.
search_approvalsApproval requests and their status, each naming who asked in principal_name, such as Halon, for Maya Ortiz. A request for a connection’s tool names the connection the way you tell it apart, such as Faylee (Northflank), and its provider.
list_abilitiesEverything that can be granted, with its risk level and whether an approval rule can hold it.
list_principalsThe people, agents and service keys of the workspace, and Firefight’s own built-in agents, each with the grants it holds.
list_member_accessWhat members can read and change in each connected tool, the rows of Who can do what on the Permissions screen. Each row’s read and change says everyone, nobody or chosen with the people chosen, and who a row leaves out but still reaches the tool through another permission set.
search_activityThe gateway’s audit log, filtered by decision or ability, each row naming who made it in principal_name. A call through a connection names that connection, such as Faylee (Northflank), and its provider.
list_unattended_rulesThe changes Halon may make on its own, each with why it cannot act yet and how many times Halon acted under it. See Halon on call.
list_allowancesThe risky changes Halon may make in a person’s chat without asking, each with how many changes Halon made under it, and whether safe changes run without asking. See Changes without asking.
get_formOne lifecycle form and every field on it, hidden ones included, with each field’s type, whether it is visible, required, or locked, whether the form asks it right now and why not, and any conditions gating it.
get_workspace_configHow the workspace is set up, in one call: severities, statuses with their lifecycle stage, incident types, incident roles, alert sources and webhooks. Disabled entries are included and marked. A caller who may read the workspace settings, which is an admin’s connection, gets those too.
list_integrationsWhat can be connected to Firefight and what already is, by category, such as Cloud and hosting or Observability. Without a category, what is connected in each one. It never connects anything. Connecting happens under Configure → Integrations. For GitHub, GitLab, Bitbucket and Azure DevOps it also lists each connection’s paths Halon may not change.
list_agentsThe agents in the workspace, each with its live tokens and how many abilities it holds.
list_api_keysThe workspace’s service keys, with the abilities each holds and when it was last used. Never the token itself.
get_postmortemThe postmortem written for an incident, as HTML, with its status and who wrote it.
list_noticesThe problems Halon raised on its own from scheduled checks and leaked secrets, newest first, with their urgency, the day each becomes a problem, and when Halon last said it. See Monitoring and security.
get_incident_transcriptWhat people said in the incident’s channel, oldest last, with who said it and when. Needs its own ability and the workspace setting.
what_changedOne list, newest first, of what changed around a resource, a catalog service, or the whole workspace: deploys and runs, settings and status changes, changes a provider reported, and changes made through Firefight, each with its link. See What changed.
check_status_pageAn outside provider’s public status page, read now, by the provider’s name or by an address your errors mention.
blind_spotsThe outside systems your apps use that nothing connects, with where each was seen and how to connect it.

These need a credential with permission to make the change, and every call is recorded.

ToolWhat it does
update_workspace_settingsChanges the settings under Settings → Workspace, such as transcript access, how long after an incident ends its channel is archived, web search, and which issue tracker incident items are kept in step with. Admin-only.
update_protected_pathsAdds or removes paths Halon may not change in a GitHub, GitLab, Bitbucket or Azure DevOps connection’s repositories, the list under Code changes on the connection. Give the connection and the paths to add or remove. Answers with the whole list. Admin-only.
upsert_catalog_entryCreates or updates a catalog entry
suggest_resource_linkSuggests a link between two resources on the map, with the evidence. It shows as a suggestion until someone confirms or dismisses it
delete_catalog_entryRemoves a catalog entry
upsert_catalog_typeCreates or changes a kind of thing the catalog holds, and the attributes its entries carry
delete_catalog_typeRemoves a catalog type and the entries under it
upsert_routing_ruleCreates or updates an alert routing rule
delete_routing_ruleRemoves a routing rule
update_routing_configChanges routing configuration
upsert_runbookCreates or updates a runbook
upsert_handbook_pageAdds a handbook page, or changes one by its ID or title. With wording_id, an edit made over somebody else’s is refused
delete_handbook_pageDeletes a handbook page and its history
upsert_skill / delete_skillCreates, changes, turns on or off, or removes one of your workspace’s skills
upsert_custom_fieldCreates or updates a custom field and its options
upsert_form_fieldAttaches a field to a form, or changes its visibility, required setting, or conditions
upsert_severity / delete_severityCreates, changes or removes a severity
upsert_status / delete_statusCreates, changes or removes a status
upsert_incident_type / delete_incident_typeCreates, changes or removes an incident type
upsert_incident_role / delete_incident_roleCreates, changes or removes an incident role
upsert_alert_source / delete_alert_sourceCreates, changes or removes an alert source
upsert_outbound_webhook / delete_outbound_webhookCreates, changes or removes a Firefight outbound webhook, which posts your incident events to a URL you own
test_outbound_webhookSends a test delivery to a Firefight outbound webhook, replaying the newest matching event from your workspace
upsert_agent / delete_agentCreates, changes or removes an agent
rotate_agent_token / revoke_agent_tokenIssues a new token for an agent, or ends one
upsert_api_key / delete_api_keyCreates, changes or removes a service key
declare_incidentOpens a new incident and its channel
post_incident_updatePosts an update on an incident
resolve_incidentCloses an incident
cancel_incidentCancels an incident that turned out not to be one
reopen_incidentReopens an incident that came back
create_action_itemAdds a piece of work to an incident and posts it in the channel
assign_action_itemTakes a piece of work, or hands it to someone else
complete_action_itemMarks a piece of work done
rename_action_itemChanges what a piece of work says needs doing
reopen_action_itemOpens a piece of work that was done again
unassign_action_itemLets go of a piece of work, so nobody holds it
create_action_item_issueOpens a piece of work’s issue in your issue tracker, or tries again after it failed
claim_runbook_stepTakes one step of an attached runbook
escalate_incidentAsks a named person to pick the incident up
page_on_callRaises a page in PagerDuty or Opsgenie on the service or team that has the person on call, kept in step with the incident
invite_respondersBrings people into the incident channel
link_incidentLinks two incidents, or marks one a duplicate of the other
give_shoutoutThanks someone for their work on the incident
post_to_channelPosts a message as Firefight in any channel it can post in, such as release notes in #general. Name the channel by its name, ID or link. A private channel needs Firefight invited first. The post names who asked for it
assign_incident_rolePuts one person in an incident role, or clears it
attach_runbookAttaches a runbook to an incident
dismiss_timeline_noteRemoves one AI note from an incident’s timeline
approve_approvalApproves a pending request
deny_approvalDenies a pending request
upsert_permission_setCreates or updates a permission set. A built-in pack cannot be changed
delete_permission_setRemoves a permission set from everyone holding it. A built-in pack cannot be deleted
grant_abilityGrants an ability or a set to a person, agent or key
revoke_grantRevokes a grant
set_member_accessSets what members can read or change in one connected tool, the same as a Who can do what dropdown. Give the row’s permission_set from list_member_access and everyone, nobody or chosen with people
upsert_approval_ruleCreates or updates an approval rule. Refused with a token, since approval rules are changed only by a person
delete_approval_ruleRemoves an approval rule. Refused with a token
upsert_unattended_ruleCreates or updates an unattended rule, or turns one on or off. Refused with a token
delete_unattended_ruleRemoves an unattended rule Halon never acted under. Refused with a token
upsert_allowanceAdds or changes an entry of what Halon may do without asking, or turns one on or off. Refused with a token, so only Halon uses it, in a chat, once you confirm it
delete_allowanceRemoves an entry Halon never made a change under. Refused with a token
start_postmortemOpens the postmortem for a resolved incident, empty or drafted by AI
update_postmortemReplaces the body of a postmortem
set_postmortem_statusMoves a postmortem to draft, in progress, in review or completed
create_workflowMakes a workflow, from a template in the library or from a trigger and steps. It goes live when you may publish it, and otherwise waits as a draft while your admins are asked
run_workflowRuns a published workflow by its name, with a value for each input it asks for, and answers with the run’s page
update_workflowChanges one workflow’s settings, the same ones its Settings page holds, such as its most runs per hour and spending ceiling per run
update_workflow_settingsSets how many days a workflow run keeps what each step did, from 1 to 400. Admin-only

upsert_catalog_entry takes attributes by name, and an attribute pointing at another entry accepts that entry’s slug, so an agent can set which team owns a service without looking up an ID.

upsert_catalog_type shapes the catalog itself, adding a kind of thing such as Datastore and saying what every entry under it carries. Attributes are matched by name, so resending a list renames rather than replaces and the entries already holding a value keep it, and sending no attributes leaves the shape alone. A reference attribute names the type it points at by slug. Built-in types keep their slug and their own attributes, and delete_catalog_type refuses a type another type points at, naming the attribute in the way. See Entries, attributes & relationships.

upsert_custom_field and upsert_form_field let an agent change what responders are asked during an incident, so they are worth granting deliberately. Options are matched by label, which means resending a list renames rather than replaces, and the incidents already holding an option keep pointing at it. Conditions accept slugs, so you can gate a field on production without looking up an ID first. A condition on a custom field names that field by its key and takes option labels or catalog entry slugs as its values, so gating on an Affected service field being checkout needs no IDs either. Severity and Status refuse to be hidden or made optional here exactly as they do in the dashboard. Call get_form first to see what a form holds, including hidden fields, because an update replaces the set rather than adding to it.

The gateway tools let an agent administer access the same way an admin does on the dashboard: see who holds what, bundle abilities into sets, grant and revoke, and decide which abilities wait for approval. They check permissions, which only an admin holds and which cannot be granted to a key, so they work over a personal token or an OAuth connection made by an admin, never a service key. Every one of these that changes something waits for an admin to approve it, whatever the connection holds and whatever your approval rules say, so a person sees each change to who may do what before it runs. The tool result gives the approval id, the request is decided on the Approvals page or in Slack, and the agent retries the same call with approval_id within the hour. The same goes for approve_approval and deny_approval, for the API key, agent and webhook tools, and for creating or rotating a token. A request that was made with a token is approved only by a person on the Approvals page or in Slack, never with approve_approval. Approval rules, what Halon may change on its own and what it may do without asking are read here but changed only by a person, so upsert_approval_rule, delete_approval_rule, upsert_unattended_rule, delete_unattended_rule, upsert_allowance and delete_allowance refuse a token with a message saying so. Connected as you, an agent can still be your chief of staff, spotting a request that names you in search_approvals and telling you. See Permissions and Approvals.

attach_runbook takes the incident and a runbook slug, and posts that runbook’s steps in the incident channel. Runbooks whose conditions match attach on their own, so this is for the ones that do not. Attaching the same runbook twice does nothing the second time. It needs incidents: update, not a runbooks permission, because it changes the incident rather than the runbook.

dismiss_timeline_note takes the incident and the id of a note, and removes that note from the timeline. It is for the case where a note reads a conversation wrong, crediting the wrong person or taking a joke for a decision. The note stops coming back from get_incident. Note ids come from that same timeline, where each note also names its kind, so an agent can ask for the root cause of a past incident directly. See Timeline notes.

The incident tools are the same operations a person has in Slack, so an agent using them is a responder rather than a reporter. What it does shows up in the incident channel as it happens, and on the incident’s timeline under the agent’s own name.

declare_incident, post_incident_update, resolve_incident, cancel_incident and reopen_incident all ask exactly what your workspace’s incident forms ask a person, custom fields included. Call get_form first with the form you are about to submit, then pass the answers keyed the way it named them. A field the form does not ask for is refused rather than quietly dropped, and a missing required field comes back naming what is missing. A field get_form marks as not asked right now is one the form will not take, so leave it out. When you update, resolve or cancel an incident, a required answer you leave out keeps the incident’s current value, so send only what changes.

create_action_item adds a piece of work and posts it in the channel, exactly like /ff action. Pass kind as action for work during the incident or followup for work after it, and member to hand it straight to someone.

assign_action_item takes a piece of work when you leave member out, which is the I can take this button, and hands it over when you name someone else, which announces the handover in the channel. complete_action_item marks it done and posts the completion. Both take the item’s id, which comes from get_incident.

rename_action_item, reopen_action_item and unassign_action_item change an item the way its menu does on the dashboard, and its issue follows when it has one. A title can be up to 3,000 characters. create_action_item_issue opens an item’s issue in the tracker your workspace keeps items in step with, and the item then shows the issue’s key and link in get_incident. It is refused, with the reason, when the item already has one or your workspace opens none. See Issue tracking.

claim_runbook_step takes one step of a runbook already attached to the incident, which creates the action item behind that step, or hands over the one that already exists. Runbook and step ids come from get_incident.

invite_responders brings people into the incident channel so they can see what is happening. escalate_incident is the stronger one. It asks one named person to pick the incident up, posts the ask in the channel, messages them directly with an acknowledge button, and reminds them if they do not answer. Reach for it when the agent has gone as far as it can on its own.

page_on_call wakes whoever is on call through your on-call tool. Give the incident, the target (in PagerDuty a service, in Opsgenie a team, escalation, schedule or person, as the tool’s schema lists for each connection) and the reason the person needs. With several on-call tools connected, name one in tool. It answers whether the page is paging, waiting for approval, or was not raised and why. See Halon on call.

Escalating, inviting and giving a shoutout all post in the incident channel, so all three refuse an incident that has been resolved or canceled, and one whose channel Firefight is still creating. The refusal names which it is.

link_incident records a related link on both incidents’ timelines and changes nothing else. Passing duplicate instead also cancels this incident, naming the one that absorbed it, so use it only when the two really are the same event seen twice.

give_shoutout thanks a named person in the incident channel, the same as /ff shoutout.

Every one of these needs incidents: create or incidents: update, so an agent granted only incidents: read can follow an incident and change nothing about it.

assign_incident_role takes the incident, the role slug, and the person as an email address or Slack user ID. Leave the person out to clear the role. Each role holds one person, so assigning hands the role over from whoever had it. Call get_incident first to see which roles exist and who currently holds them. Every role change announces itself in the incident channel, so the tool refuses any of them on a resolved or canceled incident and names the role it would have changed. See Incident roles.

An incident that has been resolved can have its write-up started, edited and moved along without anyone opening the dashboard. start_postmortem opens it. Leave generate out for an empty one you write yourself, or pass it to have Firefight draft the first version from the incident.

Generating takes a moment, so the response comes back immediately with a generation state to poll on. Read it back with get_postmortem until the state clears.

update_postmortem sends the whole document as HTML and replaces what was there rather than appending to it, so read the current one first if you mean to add a section. Every version is kept, so a rewrite can be compared and rolled back from the dashboard. set_postmortem_status moves it to draft, in_progress, in_review or completed, which is how your team knows whether it still needs writing or reading.

get_postmortem gives you a version, and update_postmortem takes it back. This matters because a person is often writing the same document in the dashboard at the same time. If they saved while the agent was composing, the agent’s write is refused rather than replacing what they wrote, and the agent reads again and reapplies. Moving the status needs no version, since it changes nothing anybody is typing.

Starting one is refused while the incident is still open, and refused outright for a canceled incident, which has nothing to write up. An incident that already has a postmortem is refused too, so read before you start. All four tools check incidents, not a permission of their own. See Postmortems.

get_incident_transcript returns what people actually said in the incident channel, which is where the reasoning lives that a timeline only summarises. Read it when you know what happened and need to know why.

It needs the Incident Transcripts ability, which is separate from incidents on purpose, and the workspace has to have turned transcript access on under Settings → Workspace. An agent granted every incident ability reads nothing until both are true. See Incident conversations.

Messages come back oldest last, 100 at a time and 500 at most, with a more_before cursor for walking further into the past. Each message says whether anything in it was redacted.

Every settings screen has tools behind it. That means you can ask an agent connected as you to do the setup, rather than clicking through it. “Add a SEV0 above our current top severity, and a Mitigating status in the active stage” is one conversation instead of two screens.

Call get_workspace_config first. It returns your severities, statuses, incident types, incident roles, alert sources and webhooks in one response, and the slugs it gives back are what every other tool takes.

Each list has its own pair of tools, since the lists do not ask for the same things. A status belongs to a lifecycle stage, a severity’s position says how severe it is, and only some are colored or have a default. Each of these four lists takes position, 1 being first, so “add a SEV0 above our current top severity” is position: 1.

Passing a slug changes the one that already has it, and leaving the slug out creates a new one. Renaming never moves the slug, because the slug is what your existing incidents point at. A slug that matches nothing comes back as an error rather than quietly creating a second entry under a fresh name.

Deleting is refused while anything still points at the entry, and the refusal says how many. Disabling is what you want then. A disabled entry keeps its slug and stops being offered to responders, and get_workspace_config still returns it so an agent can turn it back on.

The workspace settings have a tool too. update_workspace_settings changes the settings under Settings → Workspace. Give only the settings you want to change. Turning Halon makes safe changes without asking on or off is refused with a token, since only a person in Firefight decides what Halon does without asking.

SettingWhat it changes
transcript_access_enabledWhether incident transcripts may be read at all
transcript_retention_daysHow many days a transcript is kept after the incident ends. null keeps them forever
archive_channel_delayHow long after an incident ends its channel is archived
web_search_enabledWhether Halon may search and read the public web
halon_regression_enabledWhether Firefight may test new versions of Halon on answers your team rated
memory_expiry_daysHow many days a memory Halon learned is used without anyone confirming it. null keeps using it until someone decides
code_fix_agentWhich connected coding agent writes a fix’s code changes, by its connection. null for Firefight’s own
code_fix_budget_centsHow much, in cents, Firefight’s own agent may spend on one code fix before it pauses and asks you to continue. 200 by default
issue_trackerWhich connected issue tracker incident items are kept in step with. null for none
issue_creationWhen a new item gets an issue there
issue_tracker_targetWhere new issues go, by the tracker’s own fields
issue_webhook_secretThe signing secret of the tracker’s webhook. It is never read back
alert_investigations_enabledWhether an alert that opens an incident starts Halon on it, once per alert group. Off by default
alert_storm_ceiling_centsHow much, in cents, the runs alerts start may spend together in any hour. Past it, an alert opens its incident without starting Halon
on_call_paging_enabledWhether Halon, in a run an alert started, escalates the incident to whoever it found on call. Off by default
safe_changes_without_askingWhether Halon makes a safe change in a person’s chat without asking first. On by default. Refused with a token, so only Halon sets it, in a chat, once you confirm it

It needs the workspace permission, which only admins hold, and an agent in chat asks you to confirm before it changes any of them. See Incident conversations for what turning transcript access on means.

Creating an agent, rotating its token and minting a service key are all available here, and they behave differently from everything else on this page. They check permissions and api_keys, which are admin-only and cannot be granted to anyone. A connection acting as an admin reaches them. A service key or an agent never can, whatever it has been granted, so an agent cannot create another agent or widen its own access.

A token made here is never shown to the agent that asked for it. Once an admin approves the call, upsert_agent, rotate_agent_token and upsert_api_key show the new token once to the person behind the connection, in a Slack message only they see, and the agent reads only that it was shown. Copy it from Slack straight away, since the message is gone once Slack reloads and Firefight keeps no copy. If Firefight cannot reach you in Slack, the call is refused and says to create the token under Gateway → Agents or Developer → API Keys instead, where it is shown to you once. If Slack fails to show it, the token is switched off at once and you issue a new one. Neither list_agents nor list_api_keys ever carries a token.

Rotating is an overlap rather than a swap. The new token works immediately while the old one keeps working, so the agent stays up while you update its configuration, and revoke_agent_token ends the old one when you are ready. See Agents.

Seven tools put Halon, Firefight’s own agent, in front of the agent you connect, such as one in your editor. Each runs as whoever the credential belongs to. A personal token or OAuth connection runs as you, an agent token as the agent, and a service key as itself.

ToolWhat it does
ask_halonAsks Halon a question and waits up to 20 seconds for the answer. Most answers take ten seconds to a minute, so one still in progress comes back with status set to working and a conversation_id. Name an incident to ask about it. Questions from the same credential carry on in one chat. Halon acts with exactly the permissions of whoever the credential belongs to
get_halon_answerWaits up to 20 seconds more for an answer ask_halon was still working on, by its conversation_id. It answers with the same statuses, so call it again while it says working
start_investigationStarts Halon investigating an incident, or a problem nobody has declared an incident for. Without an incident, symptom is required. You can also pass started_around, names of the services, apps or repositories involved, and error_text. It runs in the background for minutes and posts its finding in the incident’s channel when there is one
get_investigationOne investigation by id, or an incident’s newest: its status, each theory with the steps behind it, every step it took, and the finding with each claim and what it rests on, including the fix it proposes
get_halon_performanceHow Halon has done over the last 7, 30 or 90 days, 30 by default: how many investigations ran and reached an answer, the median time to one, what your team said of the answers, what came of its fixes, the answers marked wrong with what Halon learned from each, and the problems its pull request reviews prevented, 20 to a page by prevented_page
list_watchesThe watches Halon keeps for you, such as one you started by asking ask_halon to tell you when a deploy finishes: its name, such as Watch “Deploy finished”, what each follows, how long it watches and why, its ceiling on reads and how many it made, each step as it stands with when it was last read and the run’s page when there is one, everything it said and how it ended. Pass active for only the ones still going. See Halon watching for you
stop_watchStops one of your watches by its id from list_watches. It says it stopped wherever the watch reports

One investigation runs per incident at a time, so a second start_investigation is told which one is running. Poll get_investigation to follow it. See Investigations and Halon’s performance.

An MCP call has no Approve button, so when Halon reaches a change it would ask you about in a chat, ask_halon does not make it. It comes back with status set to waiting and the questions in waiting_on, in the words the dashboard shows, such as “Api request on Faylee (Northflank), project faylee?”. Approve it in Firefight, then ask again. See What Halon can do.

ask_halon, get_halon_answer and start_investigation need investigations: create, the same as asking Halon in the dashboard. Every member holds it without a grant unless an admin took it away, so an OAuth connection or personal token can ask from the start, and an agent or service key needs it granted. get_investigation, get_halon_performance and list_watches need investigations: read, and stop_watch needs investigations: create. A watch reads with the credential’s own permissions, so an agent or service key watches only what its grants reach.

Every tool switched on for a connection under Configure → Integrations also appears here, so an agent can query PlanetScale or open a Linear issue through the same connection. A connection’s tools arrive switched on, a tool you switch off disappears, and who may call each is set in Permissions. An agent’s tool list only carries the capabilities its credential may call, so a narrowly scoped key never sees the rest of your connections. See Connect an integration.

A capability’s tool is named after its connection and the capability, joined with an underscore, such as northflank_search_logs for the Northflank connection’s search_logs. A second account connected under the name Faylee gives faylee_search_logs. Its description says which connection it goes through. Wherever a call through a connection is shown to a person, in approval requests, in Activity, and in what search_approvals and search_activity return, the connection is named the way you tell it apart, such as Faylee (Northflank).

A connection wired to more than one environment takes an environment parameter naming which one to use, and the tool lists the choices. Leave it out when the connection has a single environment.

A connection’s tool that changes who can reach something or sets a secret, such as GitHub’s set_actions_secret or adding someone to a status page, always waits for an admin to approve it when an agent or a token calls it, whatever the credential was granted and whatever your approval rules say. The tool result gives the approval id, and the agent retries the same call with approval_id once it is approved.

These tools work on any service, database, Worker, site or zone on the map, whichever connection runs it or watches it. The agent names the resource, and Firefight sends the request to that connection. They answer for every connected provider that offers the capability, and What Halon can do lists which providers can roll back, restart or scale.

ToolWhat it does
search_logsLog lines of a resource, newest first, filtered by text or a regular expression. It can read what the app prints, its builds, or the requests reaching it, where the provider keeps them. With the build logs, deployment reads one deployment’s or build’s log by the id run_history gives, rather than the newest
query_metricsMetrics of a resource over time, such as CPU, memory, requests and 5xx responses, with the low, average, high and latest value of each
search_errorsErrors a resource raised, newest first, grouped by kind with how often each happened
search_tracesRequest traces through a resource, slowest or failed first, with where the time went
recent_deploysWhat went out to a resource, newest first, with the id rollback takes
resource_statusHow a resource is set up and how it stands now
run_historyRecent CI runs, builds or deploys of a resource, newest first, each with its status, when it started and finished and how long it took, and how long finished ones usually take. name keeps only runs whose workflow, pipeline or kind contains it, and run reads one run by its id with its jobs, steps or phases where the provider lists them
rollbackPuts a resource back on an earlier build or version
restartRestarts a resource that is stuck while its code is fine
scaleSets how many instances a resource runs
run_key_queryRuns one of a resource’s key checks, such as error_rate, latency_p95 or throttles. Give resource, query and optionally minutes. The answer starts with how the reading compares with what is normal for the resource over the last week, then the reading itself
new_log_patternsReads a resource’s recent logs and answers which kinds of line it did not print in the last week, and which of its error lines are usual. Give resource and optionally minutes. It never returns the raw lines

Each tool takes resource, the name or id the map shows. When more than one connection could answer, the agent also gives connection, and the tool’s description lists the choices. A tool that only reads also takes connection: all, which asks every connection that could answer and heads each answer with the connection it came from. When two resources share a name, the agent names the one it means by its id.

When an observability tool such as Datadog watches a resource that a platform runs, logs, metrics, traces and errors come from the observability tool, and the platform answers instead when the observability tool has nothing, saying so in the answer.

A call through one of these tools counts as a call to the connection’s own tool. It needs the same permission, it waits for the same approval rules, and it shows in Activity under that tool. A tool appears in an agent’s list once a connection tool that can answer it is switched on under Configure → Integrations and the agent may call it. A connection tool whose name is the same as one of these is left out of the list. If the connection tool that would answer is switched off, the call says so.

Search tools return 25 results by default and accept a limit of up to 50. When more results exist than the cap allows, the response includes a truncated flag set to true, so agents know to narrow their filters instead of assuming they saw everything. Incident timelines in get_incident are capped at 50 events with their own timeline_truncated flag. Each token may make up to 1,000 MCP requests per minute.

What a connected agent can query depends on the credential it authenticates with.

CredentialAccess
OAuth connectionActs as you, with your access
Personal tokenActs as you, with your access
Agent tokenActs as the agent, with only what the agent was granted
Service keyOnly what it has been granted, and nothing by default

Agent tokens and service keys map to tools by resource.

ToolRequired permission
search_incidents, get_incident, get_workspace_config, get_postmortemincidents: read
search_similarincidents: read, and findings only with investigations: read
get_incident_transcriptincident_transcripts: read, with transcript access turned on
search_alertsalerts: read
search_catalogcatalog: read
get_resource_map, search_map, find_resources, get_resource, get_resource_links, get_resource_neighbours, traverse_resource_map, blast_radius, resource_map_statsmap: read
evaluate_routingpolicies: read
search_runbooks, get_runbookrunbooks: read
list_handbook_pages / get_handbook_pagehandbook: read
search_approvalsapprovals: read
get_formforms: read
list_integrationsintegrations: read, admin-only and ungrantable
get_investigation, get_halon_performance, list_watchesinvestigations: read
ask_halon, get_halon_answer, start_investigation, stop_watchinvestigations: create
search_logs, query_metrics, search_errors, search_traces, recent_deploys, resource_status, run_history, rollback, restart, scale, run_key_query, new_log_patternsThe permission for the connection tool that answers
upsert_catalog_entrycatalog: create or catalog: update
delete_catalog_entrycatalog: delete
upsert_catalog_typecatalog: update
delete_catalog_typecatalog: delete
suggest_resource_linkcatalog: update
upsert_routing_rulepolicies: create or policies: update
delete_routing_rulepolicies: delete
update_routing_configpolicies: update
upsert_runbookrunbooks: create or runbooks: update
upsert_handbook_pagehandbook: create or handbook: update
delete_handbook_pagehandbook: delete
list_skills / get_skillskills: read
upsert_skill / delete_skillskills: create, update or delete
upsert_custom_fieldcustom_fields: create or custom_fields: update
upsert_form_fieldforms: update
update_workspace_settingsworkspace: update, admin-only and ungrantable
update_protected_pathsintegrations: update, admin-only and ungrantable
upsert_severity / delete_severityseverities: create, update or delete
upsert_status / delete_statusstatuses: create, update or delete
upsert_incident_type / delete_incident_typeincident_types: create, update or delete
upsert_incident_role / delete_incident_roleincident_roles: create, update or delete
upsert_alert_source / delete_alert_sourcealerts: create, update or delete
upsert_outbound_webhook / delete_outbound_webhookwebhooks: create, update or delete
test_outbound_webhookwebhooks: update
list_agents, upsert_agent, rotate_agent_token, revoke_agent_token, delete_agentpermissions, admin-only and ungrantable
list_api_keys, upsert_api_key, delete_api_keyapi_keys, admin-only and ungrantable
declare_incidentincidents: create
post_incident_update, resolve_incident, cancel_incident, reopen_incidentincidents: update
create_action_item, assign_action_item, complete_action_item, rename_action_item, reopen_action_item, unassign_action_item, create_action_item_issueincidents: update
claim_runbook_step, escalate_incident, invite_responders, link_incident, give_shoutout, assign_incident_role, attach_runbook, dismiss_timeline_noteincidents: update
start_postmortem, update_postmortem, set_postmortem_statusincidents: update
approve_approval, deny_approvalapprovals: update
list_abilities, list_principals, list_member_access, search_activitypermissions: read
set_member_accesspermissions: update
post_to_channelchannel_posts: create
list_noticesmonitoring: read
list_workflowsworkflows: read
create_workflow, run_workflowworkflows: create
update_workflowworkflows: update
update_workflow_settingsworkspace: update, admin-only and ungrantable
what_changedmap: read, plus the read permission of each provider tool it runs
check_status_pageNone. It reads only public pages
blind_spotsmap: read
upsert_permission_setpermissions: create or permissions: update
delete_permission_setpermissions: delete
grant_abilitypermissions: create
revoke_grantpermissions: delete
upsert_approval_rulepermissions: create or permissions: update
delete_approval_rulepermissions: delete
A connection’s own toolsThe permission for that tool, which exists once you switch it on
list_unattended_rulespermissions: read
upsert_unattended_rulepermissions: create or permissions: update
delete_unattended_rulepermissions: delete
list_allowancespermissions: read
upsert_allowancepermissions: create or permissions: update
delete_allowancepermissions: delete

A tool call without the needed permission returns an error naming the missing permission, and the agent can keep using the tools it does have. A call an approval rule holds changes nothing and returns an error carrying the approval’s id. Once someone approves it, retry the identical call with approval_id set to that id. A call one of Firefight’s own rules stops, such as a push to a protected branch, returns an error that starts with “Firefight’s own rule refused this call, not the provider, and it is final.” and then the reason. Tell the person why rather than looking for another way around it. A refused call shows in Activity as deny, a call one of Firefight’s own rules stopped shows as refused, and a call the connected tool answered with an error of its own shows as error with the first line of what it said. See API overview for how keys and permissions work.

Everything connected over OAuth appears under Developer → API Keys in the Connected agents section, where you can revoke any connection. Revoking immediately invalidates its tokens, and the client has to go through consent again to reconnect. Automation using an API key is managed like any other key on the same page, so deactivate or delete the key to cut it off. An AI with its own identity lives under Gateway → Agents instead, where you rotate or revoke its tokens, change what it may do, or switch it off without losing what it did. See Agents.