Connect
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, 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/mcpNo 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.
{ "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.