Connect

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, 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

text
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.

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.

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.

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.

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.