---
title: MCP tools
description: The 15 tools the looot MCP server exposes, the common error shape, and a typical agent flow through discover, run and balance.
---

<WorksIn />

looot runs an MCP server at `https://api.looot.ai/mcp` over Streamable HTTP. Sign in with the
browser (OAuth, no token to copy):

```bash
claude mcp add looot https://api.looot.ai/mcp --transport http
```

Then run `/mcp`, pick looot, and authenticate. Headless clients add
`--header "Authorization: Bearer $LOOOT_TOKEN"` to the same command instead. See [Connect](/connect).

A customer sign-in sees exactly 15 tools.

## Tools

| Tool | Free or paid | Read-only | What it does |
| --- | --- | --- | --- |
| [`search`](/mcp-tools/search) | Free | Yes | Find endpoints for a job in plain words or by filter. |
| [`search_catalog`](/mcp-tools/search-catalog) | Free | Yes | Ranked full-text search over every endpoint, with job expansion. |
| [`catalog_overview`](/mcp-tools/catalog-overview) | Free | Yes | What the catalog covers, as categories, platforms and jobs. |
| [`discover`](/mcp-tools/discover) | Free | Yes | Search up to 5 eligible endpoints with relevance and evidence scoring. |
| [`discover_smart`](/mcp-tools/discover-smart) | Paid | No | Judge a shortlist against a plain-English use case with one small AI call. |
| [`inspect`](/mcp-tools/inspect) | Free | Yes | Return an endpoint's exact input/output schema, price and a run template. |
| [`run`](/mcp-tools/run) | Paid | No | Run an endpoint, a job, or a workflow, and spend prepaid credit. |
| [`runs_get`](/mcp-tools/runs-get) | Free | Yes | Get one run's status, result and cost. |
| [`runs_list`](/mcp-tools/runs-list) | Free | Yes | List runs for this workspace, cursor-paginated. |
| [`runs_cancel`](/mcp-tools/runs-cancel) | Free | No | Cancel a queued or running run. |
| [`runs_evidence`](/mcp-tools/runs-evidence) | Free | Yes | Every attempt made for a run: status, latency, receipt id, cost. |
| [`balance`](/mcp-tools/balance) | Free | Yes | This workspace's available and reserved balance. |
| [`top_up`](/mcp-tools/top-up) | Free | No | Get a Stripe Checkout link to add prepaid credit. |
| [`capability_request`](/mcp-tools/capability-request) | Free | No | Ask for a provider or job the catalog does not cover yet. |
| [`my_tools`](/mcp-tools/my-tools) | Free | Yes | List this workspace's tenant tools and whether each is callable. |

"Free" means the call itself costs nothing; `run` still spends credit when the endpoint it runs
has a price. `discover_smart` is the one tool that always costs a small amount on top of any
endpoint it leads you to run, because it makes its own paid AI call to judge candidates.

`run` and `runs_cancel` are the only two tools with `destructiveHint: true` in their tool
annotations, because they change state: they spend money or stop a run in flight. The
other 13 are read-only or additive.

## Errors

Every tool error, whatever produced it, comes back the same way: `isError: true` on the MCP
result, with `structuredContent.data` shaped `{code, message, retryable, requestId}`. Read
`code` to branch, and show the customer `message`, which already states the fix when there is
one.

Bad arguments get `code: "validation_error"`. A missing or wrong-typed field names that field in
`message`, for example `q: Invalid input: expected string, received undefined`. An argument the
tool does not accept is refused by name too, with the arguments it does accept listed alongside
it in `acceptedArguments`.

A call can still fail after admission. `run` and `runs_get` can both return `status: "failed"`
inside a successful, non-error MCP call: the tool call itself worked, but the run it describes
did not settle successfully. Always check `status` and `error` on the run as well as whether the
tool call errored. See [Run errors](/errors/run-errors) and [MCP errors](/errors/mcp-errors).

## The text and structured content

Every tool answer carries two equivalent copies of the same data: a `content[0].text` string of
compact JSON (no indentation, to keep it short for a model's context) and a `structuredContent.data`
object holding the same values already parsed. Read whichever your client surfaces; they never
disagree.

## A typical flow

1. **Find a job**

    Call `search` or `search_catalog` with a plain-English description ("verify an email
    address") to get one or more `endpointId` values for the job.

2. **Check the price and schema**

    Call `inspect` with the `endpointId` to see its exact input schema and
    `estimatedMaxCost` before spending anything.

3. **Check your balance**

    Call `balance`. A new workspace starts at $0. If it is short, call `top_up` for a
    payment link and wait for the customer to pay.

4. **Run it**

    Call `run` with the `endpointId`, the `input` the schema requires, and a fresh
    [`idempotencyKey`](/concepts/idempotency). Add `wait` to get the settled result back inline.

5. **Follow up**

    If you did not wait, poll `runs_get` with the returned `runId`. `runs_evidence` shows
    every attempt made; `runs_cancel` stops a run still queued or running.

See [Connect](/connect) to wire the server into your agent, and [Jobs](/concepts/jobs) for how
jobs and endpoints relate.

<Related />
