> The full index of these docs is at [llms.txt](https://u22a8.ai/llms.txt).

# MCP

Connect an MCP host to A8, and judge, teach and retract from inside a conversation with three tools.

A8’s Model Context Protocol (MCP) server lets an MCP host, such as Claude, ChatGPT or Cursor, judge, teach and retract from inside a conversation. It is the way to [teach](https://u22a8.ai/docs/a8-teaching.md) A8: your assistant writes the request, and your approval of the tool call is the commit.

The server is named A8 and served at `https://api.u22a8.ai/mcp`, over Streamable HTTP.

## 1 Connect a host

Hosts that support sign-in take you through it: you sign in with your account and pick an organization, and the server acts with your role’s permissions in it. Hosts that take a header send an [API key](https://u22a8.ai/docs/api-keys.md) as `Authorization: Bearer`, and the server acts with the key’s permissions in its organization. Each tool needs the permission listed in Table 1.

**Claude**

In Claude, open **Settings → Connectors** and select **Add custom connector**. Name it A8, enter the URL below and sign in when Claude asks.

```text
https://api.u22a8.ai/mcp
```

**ChatGPT**

In ChatGPT, turn on **Settings → Apps & Connectors → Advanced settings → Developer mode**. Then select **Create**, name the connector A8, enter the URL below and sign in when ChatGPT asks.

```text
https://api.u22a8.ai/mcp
```

**Cursor**

Add the server to `.cursor/mcp.json` in your project, or to `~/.cursor/mcp.json` for every project. Cursor reads the key from your environment:

```json
{
  "mcpServers": {
    "a8": {
      "url": "https://api.u22a8.ai/mcp",
      "headers": {"Authorization": "Bearer ${env:U22A8_API_KEY}"}
    }
  }
}
```

**Claude Code**

Add the server with a key from your environment:

```bash
$ claude mcp add --transport http a8 https://api.u22a8.ai/mcp \
    --header "Authorization: Bearer $U22A8_API_KEY"
```

To sign in with your account, add the server with the URL alone, then run `/mcp` in Claude Code.

## 2 Tools

The server has three tools, one for each thing you do with A8:

| Tool      | Does                                                     | Permission                              | Annotations             |
| --------- | -------------------------------------------------------- | --------------------------------------- | ----------------------- |
| `judge`   | Returns a verdict, an abstention or recalled examples    | `models:infer`; recall `models:explain` | Read-only               |
| `teach`   | Records the answer a request should get, or proposes one | `models:train`                          | Idempotent              |
| `retract` | Removes a taught answer from the next version            | `models:train`                          | Destructive, idempotent |

*Table 1.* The three tools. Precedents also need `models:explain`, and recall needs `models:explain` alone. Permissions are on [API keys](https://u22a8.ai/docs/api-keys.md), and on your role when you sign in.

All three take a request the same way: `input`, a string or a list of messages, and an optional `format`. A list carries a whole conversation: assistant messages are A8’s earlier responses, and A8 answers the latest user message. A8 finds the criterion and the subject in it as it does in every interface. See [API overview](https://u22a8.ai/docs/api-overview.md#continue-a-conversation). The three input schemas share these definitions:

```json
{
  "$defs": {
    "request": {
      "description": "A string, or messages as in the Responses API.",
      "oneOf": [
        {"type": "string"},
        {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "role": {
                "enum": ["system", "developer", "user", "assistant"]
              },
              "content": {"type": "string"}
            },
            "required": ["role", "content"]
          }
        }
      ]
    },
    "format": {
      "type": "object",
      "description": "A JSON Schema for the verdict."
    }
  }
}
```

### 2.1 Approval

An MCP host asks before it calls a tool that changes something. `judge` is read-only, so a host calls it freely. Approving a `teach` that carries an `answer`, or a `retract`, changes your model. A `teach` with the `input` alone returns a proposal, and your assistant records it with a second call once you agree.

## 3 judge

`judge` returns the verdict for a request, an abstention, or your taught examples when the request asks what you taught.

```json
{
  "type": "object",
  "properties": {
    "input": {"$ref": "#/$defs/request"},
    "format": {"$ref": "#/$defs/format"},
    "model": {
      "type": "string",
      "default": "a8",
      "description": "The model, its minimum accuracy as a tag: a8:95."
    }
  },
  "required": ["input"],
  "additionalProperties": false
}
```

`model` names the model and the [minimum accuracy](https://u22a8.ai/docs/a8-abstention.md) in its tag, as in every interface: `a8:95` asks for 95, and the default is 90. A pinned identifier, such as `a8-1-1:95@20260715t140322z`, holds the version and the minimum accuracy still, so a test runs against the same model every time. See [Model identifiers](https://u22a8.ai/docs/a8-model-identifiers.md).

The result’s structured content follows this output schema, and its text content carries the same object as JSON:

```json
{
  "type": "object",
  "properties": {
    "verdict": {"description": "The verdict, in the shape format gives."},
    "model": {"type": "string", "description": "The version that answered."},
    "min_accuracy": {"type": "integer"},
    "abstention": {"type": "object"},
    "precedents": {"type": "object"}
  },
  "required": ["model"]
}
```

A verdict:

```json
{
  "verdict": {"queue": "shipping"},
  "model": "a8-1-1:95@20260715t140322z",
  "min_accuracy": 95
}
```

Recorded from `a8-1-1@20260715t140322z` on 2026-10-22.

An abstention is a successful result. `verdict` is `null`, and `abstention` names the check the evidence failed:

```json
{
  "verdict": null,
  "model": "a8-1-1:95@20260715t140322z",
  "abstention": {
    "kind": "unfamiliar_subject",
    "asked": 95,
    "answerable_at": 0,
    "earned": 97,
    "missing": null
  }
}
```

Recorded from `a8-1-1@20260715t140322z` on 2026-10-22.

When the request asks for [precedents](https://u22a8.ai/docs/a8-precedents.md), the result adds a `precedents` object. A question about what you taught, such as “What have I taught you about refunds?”, returns `precedents` alone, holding up to ten of your taught examples word for word.

### 3.1 The judge tool’s description

The tool’s description tells the host how to examine A8, so “check that A8 learned our refund rule” is enough for your assistant to run a fair test. This is the description, word for word:

```text
Judge a request with A8. Returns the verdict, or an abstention where the
evidence falls below the minimum accuracy.

To check what A8 has learned, test it. Write untaught variations of the
request, edge cases included, each with the answer it should get. Judge
each one, and report the misses and the abstentions separately: a miss
lowers accuracy, and an abstention lowers coverage.

A question about what was taught, such as "What have I taught you about
refunds?", returns the taught examples.
```

Your assistant writes the variations, and A8 judges them. See [Testing](https://u22a8.ai/docs/a8-testing.md).

## 4 teach

`teach` records the answer a request should get, or proposes a request and answer from your own words.

```json
{
  "type": "object",
  "properties": {
    "input": {"$ref": "#/$defs/request"},
    "format": {"$ref": "#/$defs/format"},
    "answer": {
      "description": "The verdict to record. Leave it out to get a proposal."
    }
  },
  "required": ["input"],
  "additionalProperties": false
}
```

With an `answer`, the example is recorded once you approve the call:

```json
{
  "input": [
    {"role": "system", "content": "Which queue does the ticket belong in?"},
    {"role": "user", "content": "It arrived crushed. I want a refund."}
  ],
  "format": {
    "properties": {"queue": {"enum": ["billing", "shipping", "account"]}}
  },
  "answer": {"queue": "billing"}
}
```

```json
{
  "recorded_at": "2026-07-16T09:11:40Z",
  "replaced": false
}
```

- **`recorded_at`** is when the teach was recorded. Every version whose horizon is at or after that time includes it. See [Horizons](https://u22a8.ai/docs/a8-horizons.md).
- **`replaced`** is `true` when the same request held a different answer, which this one replaces. See [Teaching](https://u22a8.ai/docs/a8-teaching.md).

With the `input` alone, or an `input` that states what A8 should learn, `teach` returns a proposal: the request and answer A8 would record. `recorded_at` is `null`, and your assistant teaches the proposal with a second call. For a key that also holds `models:explain`, A8 frames the proposal beside the requests you taught nearest it, and reuses their criterion and format; for any other key, from the `input` alone.

```json
{
  "input": "Double-charge tickets go to billing, even when the order came late."
}
```

```json
{
  "proposal": {
    "input": [
      {"role": "system", "content": "Which queue does the ticket belong in?"},
      {
        "role": "user",
        "content": "I was charged twice for an order that arrived late."
      }
    ],
    "format": {
      "properties": {"queue": {"enum": ["billing", "shipping", "account"]}}
    },
    "answer": {"queue": "billing"}
  },
  "recorded_at": null
}
```

Recorded from `a8-1-1@20260715t140322z` on 2026-10-22.

The tool’s description, word for word:

```text
Teach A8 the answer a request should get. Call it when the user says a
verdict was wrong, or states something A8 should learn.

With an answer, the example is recorded and the next version learns it.
Teaching the same request again replaces its answer. With the input alone,
it returns a proposal: show the proposal to the user, and teach it with a
second call once they agree.

Confirm the request and the answer with the user before you call it.
```

## 5 retract

`retract` removes a taught example. It takes the request alone, word for word as it was taught.

```json
{
  "type": "object",
  "properties": {
    "input": {"$ref": "#/$defs/request"},
    "format": {"$ref": "#/$defs/format"}
  },
  "required": ["input"],
  "additionalProperties": false
}
```

```json
{
  "retracted": true
}
```

The next version is fitted from your remaining examples. Versions fitted before keep the retracted example, so a pinned version answers as it did. `retracted` says whether the request held a taught answer to remove. To find the exact request, ask `judge` what you taught; recall lists it.

The tool’s description, word for word:

```text
Remove a taught example, so the next version is fitted from the examples
that remain. Call it when the user says an example was taught by mistake.

Find the exact request first: ask judge what was taught, and use the
example word for word.

Confirm the request with the user before you call it.
```

## 6 Errors

A call that fails returns a result with `isError` set to `true`. Its text names the field, the rule it broke and the value that passes:

```json
{
  "isError": true,
  "content": [
    {
      "type": "text",
      "text": "This request needs the models:train permission."
    }
  ]
}
```

Each condition matches a status code of the other interfaces:

| Condition                                                    | Status elsewhere                       |
| ------------------------------------------------------------ | -------------------------------------- |
| The key lacks the permission the tool needs                  | `403`                                  |
| The organization lacks access to A8                          | `403`                                  |
| `model` names a version outside your organization’s horizons | `404`                                  |
| `input` is empty, or `model`’s tag is outside `0` to `99`    | `400`                                  |
| The pinned version is still being fitted                     | `503`                                  |
| A8 filtered the request for harmful content                  | `200`, in each interface’s filter slot |

*Table 2.* Tool errors and the status each matches. The bodies of those statuses are on [Errors](https://u22a8.ai/docs/errors.md).

With reasoning on, A8 filters some requests whose text is harmful, such as hate speech, violence or self-harm. MCP reports a filtered request as a failed call: `judge` and `teach` return a result with `isError` set and the text `This request was filtered for harmful content.` A filtered `teach` leaves your examples as they were.

## Next steps

- [Teaching](https://u22a8.ai/docs/a8-teaching.md): How to teach and retract through MCP, when a teach lands in your organization’s model and what it changes.
- [Testing A8](https://u22a8.ai/docs/a8-testing.md): Test what A8 learned the way you would test a student, with new questions, known answers, accuracy and coverage, on a pinned version.
- [API keys](https://u22a8.ai/docs/api-keys.md): Create an API key, grant its permissions, authenticate requests with it and revoke it.
