# MCP tools

> Every tool the MCP server gives an agent — what it takes, returns and costs. Setting it up is in Connect your agent.

Forma speaks [Model Context Protocol](https://modelcontextprotocol.io), so an
agent can reach an oracle without you writing an integration for it. Six
tools, the same guarantees as the HTTP API, and the same prices.

## The endpoint

```
https://mcp.formalogic.io/mcp
```

**No API key needed.** Your client signs in with your Forma account (OAuth) the
first time it calls a tool. For a client that cannot do OAuth, an API key sent as
a bearer token works too. Hosted, so the tools an agent sees are always the
current ones. Setup for each client is in [Connect your agent](https://docs.formalogic.io/connect).

## The tools

### forma_status()

Which Forma account this session is signed in as. Free.

Ask for this first when a connection has just been set up. `list_oracles`
answers identically for every caller, so a working connection and one signed in
to someone else's account look the same through it; this answers with something
only a live, authenticated session can know.

```json
{ "org_id": "org_01M2G6ZW…", "plan": "free", "requests_per_minute": 10, "features": [] }
```

### list_oracles()

Every oracle available to your account, with each one's `formats`,
`default_format` and `drawable_formats` (the ones `show_figure` can draw). Free. Call it before guessing a name — the catalogue is the
contract and it grows.

### ask_oracle(oracle, intent, format?, allow_generated_data?)

| Argument | |
|---|---|
| `oracle` | a name from `list_oracles` |
| `intent` | what you want, described normally — not a template, not a specification — with the values to plot |
| `format` | optional; defaults to that oracle's own. Pick one of `drawable_formats` when the person should see it |
| `allow_generated_data` | optional, charts only; `true` accepts illustrative values when the intent gives none |

Forma does not fetch data. The agent puts the values in `intent`, fetching them
first if the person wants real numbers; a chart request without them is refused
with `DATA_REQUIRED`, unbilled.

The answer is checked against the oracle's rules before it is returned, so
`status` is a verdict rather than a guess: `valid` with a `result` and a
`verified_by` citation, `invalid` where the check refused it and said why, or
`error` which is ours, unbilled, and worth retrying. See
[Verdicts](https://docs.formalogic.io/verdicts).

### show_figure(figure_token, format?)

| Argument | |
|---|---|
| `figure_token` | the `figure.token` from an `ask_oracle` answer, passed exactly as given |
| `format` | `png` (the default), which can be looked at, or `svg`, returned as text for saving to a file |

Draws a `valid` answer whose `figure.drawable` is true, so the person sees the
chart or drawing and not only its source. An answer that cannot be drawn says why
in `figure.reason`. Free: the answer was already paid for.

### whats_new(since?)

What changed for callers — endpoints, oracles, tools — newest first. `since` is
an optional `YYYY-MM-DD`; pass the `latest` from an earlier call to see only what
arrived after it. Free. The same entries are in the [Changelog](https://docs.formalogic.io/changelog).

### send_feedback(sentiment, message, oracle?, request_id?)

| Argument | |
|---|---|
| `sentiment` | `positive`, `negative` or `neutral` |
| `message` | why, in a sentence or two; up to 2000 characters |
| `oracle` | optional; the oracle it is about |
| `request_id` | optional; the answer it is about. Left empty, the latest `ask_oracle` answer made with the same credential is used, when it was for the same oracle |

Tells the people who build Forma what worked and what did not. Free. See
[News and feedback](https://docs.formalogic.io/news-feedback).

## Errors an agent can act on

Every failure comes back as an `error` object with a `kind`, so a model can
branch instead of the tool call dying.

| `kind` | Meaning |
|---|---|
| `unauthorized` | Not signed in, or the sign-in or key is unrecognised, revoked or expired — a human has to act |
| `quota_exceeded` | The allowance is spent; signing in again or switching keys will not help |
| `not_found` | No such oracle — call `list_oracles` |
| `invalid_request` | The request or the requested format was refused; `context` names the valid ones |
| `upstream_unavailable` | A service the oracle depends on is briefly unavailable. Waiting is the right next move |
| `backend_unreachable` | Network or DNS, after retries |

Every error also carries `retryable` — whether waiting could change the answer —
and `request_id`, the id stamped on the failure. Quote the `request_id` when
reporting a problem; it identifies the call in our logs.

Transient failures are retried before anything is returned, so a `kind` that
reaches your agent is one worth acting on.

## Cost

Identical to the HTTP API. `forma_status` and `list_oracles` are free;
`ask_oracle` costs the oracle's credits and the answer says what it cost. See
[Limits and credits](https://docs.formalogic.io/limits).
