# Ace MCP server

> Give coding agents, code reviewers and other MCP clients read-only access to Ace's incident context, lessons from past fixes, your operating rules and the current state of a workload.

Source: https://tryace.dev/docs/mcp

The Ace MCP server gives any [Model Context Protocol](https://modelcontextprotocol.io) client read access to what Ace knows about your incidents, so the agent that changes your code can see what happened in production, what was tried before and how your team wants the work done.

All tools are read-only, and the server can't change anything in Ace or in your systems. Ace changes live systems only through its own actions, under your [approval policy](https://tryace.dev/docs/concepts/actions-and-approvals).

| | |
| --- | --- |
| Server URL | `https://app.tryace.dev/api/mcp` |
| Transport | Streamable HTTP (stateless, JSON responses) |
| Authentication | Bearer token in the `Authorization` header |
| Protocol versions | `2025-06-18`, `2025-03-26`, `2024-11-05` |
| Tools | 5, all read-only |

Common uses:

- A coding agent loads an incident's root cause, evidence and proposed actions before it opens a pull request.
- A reviewer checks whether a change repeats a fix that made a similar incident worse.
- Agents read your [operating rules](https://tryace.dev/docs/concepts/operating-rules) before they diagnose or change anything.
- You check a workload's open incidents, early warnings and recent changes before a deploy.

## Before you start

- Creating a token needs the admin role, because a token reads your whole organization. See [Roles and permissions](https://tryace.dev/docs/security/roles-and-permissions).
- Your MCP client must support remote servers over Streamable HTTP with a custom `Authorization` header. For stdio-only clients, use the `mcp-remote` bridge under **Other clients** in [Step 2](#step-2-connect-your-client).
- Ace authenticates with access tokens, so skip any OAuth sign-in your client offers for this server.

## Step 1: Create a token

1. In Ace, open **Settings** > **MCP**.
2. Under **Create a token**, name the token after its use, such as `Claude Code - payments repo`.
3. Choose when it expires: in 30, 90 (the default), 180 or 365 days.
4. Select **Create token**.
5. Copy the token now, because Ace shows it once and stores only a hash. Tokens start with `ace_mcp_`.

Store the token as an environment variable in your shell profile or secret manager, then reference the variable in your client's configuration so the token stays out of config files:

```bash

```

> **A token can read your whole organization**
>
> A token reads every incident, workload and operating rule in your Ace organization, whoever created it, so treat it as a production read credential. Keep it out of source control, issue one per client or person, and use the shortest expiry that works.

## Step 2: Connect your client

**Claude Code**

Create `.mcp.json` in the repository root. Claude Code expands `${ACE_MCP_TOKEN}` from your environment when it connects, so the file holds no secret and can be committed.

```json title=".mcp.json"
{
  "mcpServers": {
    "ace": {
      "type": "http",
      "url": "https://app.tryace.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer ${ACE_MCP_TOKEN}"
      }
    }
  }
}
```

Or use the CLI. The single quotes save the variable reference instead of its value, so the token itself never lands in the config:

```bash
claude mcp add --transport http ace https://app.tryace.dev/api/mcp --header 'Authorization: Bearer ${ACE_MCP_TOKEN}'
```

Run `/mcp` to check that `ace` is connected with five tools. On first use, Claude Code asks you to approve the project's servers.

**Cursor**

Add Ace to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` for every project. Cursor reads `${env:ACE_MCP_TOKEN}` from the environment it started in, so launch it from a terminal where the variable is set.

```json title=".cursor/mcp.json"
{
  "mcpServers": {
    "ace": {
      "url": "https://app.tryace.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer ${env:ACE_MCP_TOKEN}"
      }
    }
  }
}
```

Check **Cursor Settings** > **MCP** for `ace` with five tools.

**VS Code**

Add Ace to `.vscode/mcp.json` in your workspace, where VS Code uses `servers` as the top-level key. This configuration asks for the token on first start and stores it securely, so the file holds no secret:

```json title=".vscode/mcp.json"
{
  "inputs": [
    {
      "type": "promptString",
      "id": "ace-mcp-token",
      "description": "Ace MCP token",
      "password": true
    }
  ],
  "servers": {
    "ace": {
      "type": "http",
      "url": "https://app.tryace.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer ${input:ace-mcp-token}"
      }
    }
  }
}
```

To read the token from your environment instead, use `"Authorization": "Bearer ${env:ACE_MCP_TOKEN}"` and drop the `inputs` block.

In the Chat view, switch to agent mode and select the tools icon to check that Ace's five tools are listed.

**Codex**

Codex reads the token from the environment variable on each connection:

```bash
codex mcp add ace --url https://app.tryace.dev/api/mcp --bearer-token-env-var ACE_MCP_TOKEN
```

Or edit `~/.codex/config.toml`:

```toml title="~/.codex/config.toml"
[mcp_servers.ace]
url = "https://app.tryace.dev/api/mcp"
bearer_token_env_var = "ACE_MCP_TOKEN"
```

Run `codex mcp list` to check it.

**Other clients**

Point any remote-capable client at `https://app.tryace.dev/api/mcp` over Streamable HTTP, with the header `Authorization: Bearer <token>`. The older SSE transport isn't offered.

For stdio-only clients such as Claude Desktop, use the open-source [`mcp-remote`](https://www.npmjs.com/package/mcp-remote) bridge, which needs Node.js 18 or later. Put the whole header value in an environment variable and leave no space after `Authorization:`, because some clients split arguments on spaces.

```json title="claude_desktop_config.json"
{
  "mcpServers": {
    "ace": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://app.tryace.dev/api/mcp",
        "--transport",
        "http-only",
        "--header",
        "Authorization:${ACE_AUTH_HEADER}"
      ],
      "env": {
        "ACE_AUTH_HEADER": "Bearer ace_mcp_..."
      }
    }
  }
}
```

To test from a terminal, list the tools with `curl`:

```bash
curl -s https://app.tryace.dev/api/mcp \
  -H "Authorization: Bearer $ACE_MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

## Tools

| Tool | Parameters | What it does |
| --- | --- | --- |
| `get_incident_context` | incident (string, required): Incident ID or Ace incident reference such as INS-1018-ab12. | The complete Ace incident context: what happened, root cause with supporting and contradicting evidence, open questions, evidence timeline, topology, and every proposed or running action with its constraints and pull request. Use it before reviewing or changing code for an incident. |
| `search_incidents` | query (string, optional); status ("open" or "resolved" or "any", optional); limit (integer, 1–25, optional) | Find Ace incidents by meaning (similar causes and fixes across the organization) and by text in the headline, reference or workload name. Returns references to pass to get_incident_context. |
| `get_lessons` | incident (string, optional): Incident ID or Ace reference such as INS-1018-ab12.; query (string, optional): The problem in a sentence, to find similar incidents.; workload (string, optional): Workload name or ID.; limit (integer, 1–10, optional) | What Ace learned from verified outcomes: fixes that worked on a workload, fixes to avoid (they made an incident worse, or repeatedly did not recover), and similar past incidents with the actions taken and how each was judged. Give an incident, a description of the problem, or a workload. Use it before proposing a fix. |
| `get_operating_rules` | applies_to ("all" or "diagnosis" or "remediation" or "code_change" or "live_operation", optional): Only the rules for this kind of work (rules for everything are always included). | The workspace's operating rules: how its administrators want diagnoses, recommendations, pull requests and live operations done. Follow them. They narrow what to do and never grant permissions. |
| `get_workload_context` | workload (string, required): Workload name or ID. | A workload right now: its open incidents, its open early warnings (forecasts and capacity risks) and its changes (deploys, configuration, infrastructure) in the last 24 hours. |

Pass an incident as its Ace reference, such as `INS-1018-ab12`, or its ID, and a workload as its name or ID. Lookups only see your organization.

### get_incident_context

Returns the full incident as Markdown and as structured data, including:

- headline, workload, severity, status and a link to the incident
- what happened and what triggered it
- the root cause with its confidence, supporting and contradicting evidence, and open questions
- the evidence timeline, with source links where available
- matched services and the dependency path, when known
- notes from Ace and your engineers
- every proposed or running action, with its progress, constraints and pull request link

```json title="Arguments"
{ "incident": "INS-1018-ab12" }
```

### search_incidents

Finds incidents by meaning and by text in the headline, reference or workload name. Matches by meaning come first with a similarity score, followed by the most recent text matches with severity and status. Each result includes the reference to pass to `get_incident_context`.

Without `query`, it lists the most recent incidents. `status` defaults to `any` and `limit` defaults to 10.

```json title="Arguments"
{ "query": "orders stuck after a schema migration", "status": "resolved", "limit": 5 }
```

### get_lessons

Returns what Ace learned from verified outcomes. Pass at least one of `incident`, `query` or `workload`, and `limit` defaults to 5. The result has three parts:

- **Fixes that worked** lists fixes that recovered the workload and never made it worse, with counts.
- **Fixes to avoid** lists fixes that made an incident worse, or that failed to recover the workload at least twice and never recovered it.
- Similar past incidents, with the actions Ace took in each and how each was judged.

Fix history needs a workload, because Ace tracks fixes per workload. It takes the workload from `workload`, or from the workload of `incident`. See [How memory works](https://tryace.dev/docs/concepts/memory).

```json title="Arguments"
{ "workload": "checkout-api", "query": "p99 latency spike after deploy" }
```

### get_operating_rules

Returns your workspace's [operating rules](https://tryace.dev/docs/concepts/operating-rules) and the kinds of work each one covers. `applies_to` filters to one kind of work, and rules that apply to everything are always included.

```json title="Arguments"
{ "applies_to": "code_change" }
```

### get_workload_context

Returns a workload's open incidents and open early warnings, where each early warning is a forecast or a capacity risk with when the limit is expected to be hit. The result also lists up to 20 changes from the last 24 hours, such as deploys and configuration or infrastructure changes.

```json title="Arguments"
{ "workload": "checkout-api" }
```

## Example prompts

Each prompt lists the tools it should call, though most clients pick tools on their own once Ace is connected.

**Fix an incident with full context**

```text
Load Ace incident INS-1018-ab12 and our operating rules for pull requests.
Then fix the root cause in this repository. Don't repeat any fix that Ace
lists under "Fixes to avoid" for this incident's workload.
```

Tools: `get_incident_context`, `get_operating_rules` with `applies_to: "code_change"`, `get_lessons` with `incident`.

**Review a pull request against past incidents**

```text
Review this diff. Use Ace to find past incidents on checkout-api that touched the
same code path, and flag anything this change repeats from a fix that made an
incident worse or didn't recover it.
```

Tools: `search_incidents`, `get_lessons` with `workload`.

**Check a workload before you deploy**

```text
Before I deploy payments-worker, check Ace for open incidents, early warnings and
changes in the last day. Tell me if anything argues for waiting.
```

Tools: `get_workload_context`.

**Write a post-incident summary**

```text
Summarize Ace incident INS-1018-ab12 for our incident review: what happened, the
root cause with its evidence, what was changed, and what's still unknown.
```

Tools: `get_incident_context`.

## Security and access

- All five tools are marked read-only in their MCP annotations.
- A token belongs to the organization and reads all of its incidents, workloads and rules, whoever created it. Only admins can create, see and revoke tokens.
- Ace stores only a hash of each token, and a token expires after the period chosen when it was created, at most 365 days.
- Requests with a browser `Origin` header other than Ace's own get `403`, so call the server from agents, IDEs and CLIs.
- Ace logs each tool call with the token, the tool, the incident read and the result, and keeps the log for 90 days. **Settings** > **MCP** shows when each token was last used.
- A tool result is capped at 200,000 characters. Longer incident context is cut off and ends with a link to the incident in Ace.

> **Treat incident content as untrusted**
>
> Incident context includes alert text, log lines, error messages, Slack replies and third-party pages, any of which can contain prompt injection. Keep tool-call approval on in your client, review what the agent does with the results, and don't let incident content alone justify a code or infrastructure change.

### Revoke a token

1. In Ace, open **Settings** > **MCP**.
2. Under **Tokens**, select **Revoke** next to the token.

The next request with that token gets `401`. Revoked and expired tokens stay in the list with their status, so you can see which clients need a new one.

## Limits and errors

| Limit | Value |
| --- | --- |
| Calls per token | 120 per minute |
| Calls per organization, across all tokens | 600 per minute |
| Requests per client address | 300 per minute |
| Failed authentications per client address | 20 per minute |
| Request body | 64 KB |
| Tool result | 200,000 characters |

Each request carries one JSON-RPC message, and batches aren't supported.

| Status | Meaning | What to do |
| --- | --- | --- |
| `401` | The token is missing, malformed, revoked or expired. The body is `{"error": "Invalid Ace MCP token."}`. | Check the `Authorization: Bearer ace_mcp_...` header, and check that the environment variable is set where your client runs. If the token was revoked or has expired, create a new one. |
| `403` | The request came from a web page (`Origin` header). | Call the server from an agent, IDE or CLI. |
| `413` | The request body is larger than 64 KB. | Tool arguments are short strings, so this usually means a malformed request. |
| `429` | A rate limit was reached. The `retry-after` header gives the seconds to wait. | Wait that long before you retry. If you hit the organization limit, spread the work over time or run fewer agents at once. |

Tool errors, such as an unknown incident or a missing argument, come back as a normal tool result with `isError: true` and a message, such as `No incident INS-0000-xxxx in this organization.` An unknown tool returns JSON-RPC error `-32602`, and an unknown method returns `-32601`.

## Next steps

  - [How memory works](https://tryace.dev/docs/concepts/memory): What get_lessons and search_incidents draw on.
  - [Operating rules](https://tryace.dev/docs/concepts/operating-rules): Write the rules your agents read with get_operating_rules.
  - [Security and data](https://tryace.dev/docs/security/security-and-data): What Ace reads, keeps and protects.
