Apiosk MCP Server
Apiosk MCP Server
Buy an API call the way a person would. Describe the job, see what can do it, compare the candidates on price and measured performance, choose one, and pay for it in USDC over x402 — under limits the buyer set, enforced on every call.
payments · x402 · commerce · usdc · api-comparison
Hosted endpoint:
https://mcp.apiosk.com/mcp(streamable HTTP; the first data request starts OAuth when needed).Local stdio package:
npx -y @apiosk/mcporuvx apiosk-mcp.Buyer portal: buy.apiosk.com — sign in, fund a wallet, set the limits, approve a held purchase.
The eleven tools
Two paths, and the same rules on both. apiosk is the one-shot entrypoint for
fast shopping: it returns the App's own top ranked runnable provider and
approval card. An agent does not browse a menu: it reads descriptions and picks,
so every tool here earns its place in one of the two flows.
One call, when a single API answers the question:
Tool | What it answers | Spends |
| Return the top ranked runnable provider, exact price, required inputs and Approve/Deny card. | no |
| Can this session buy? Which wallet, which policy, which limits. Returns the portal link when there is no connection. | no |
| What can perform this job? Sweeps the reviewed Apiosk catalogue and the wider x402 ecosystem. | no |
| How do the candidates perform against my requirements? Price, measured p95 latency, measured success rate and input fit, each offer carrying a stable | no |
| Run the offer the user chose, at the price they were shown. | yes |
| What happened to the purchase the buyer's rules put on hold? | no |
Several calls, when a lookup's result feeds the next call, or several facts are wanted about one subject:
Tool | What it answers | Spends |
| What would answering this take, in what order, and what is the one price for all of it? Returns the steps, what it cannot reach, and a signed | no |
| Start the plan the user approved, by | yes |
| Where has the running plan got to, and what happened since the last cursor? | no |
| Which subject was meant, when the job stopped to ask? | no |
| Stop dispatching further calls. Calls already sent are still settled. | no |
The plan is compiled, deduplicated and priced by the gateway, never here: a
lookup two branches both need is bought once, and a fact you already hold
removes its lookup from the plan and from the price. The App and this server
show the same plan_hash and the same amount for the same intent because
exactly one of them computes it.
Anything a buyer needs that is not on this list is a link to app.apiosk.com, not a tool. This server holds no keys, prices nothing and moves no money.
The one rule
apiosk_compare and apiosk return offers. A person approves or denies the
purchase. The quick card states the provider and exact price and supplies the
two actions; do not add a second prose confirmation. Only Approve may pass the
signed offer_token, exact max_price_usdc ceiling and entered inputs to
apiosk_execute. Deny stops without spending.
A plan is the same rule at plan scale: one confirmation, for the whole plan,
at the whole price. apiosk_plan asks it once and returns the answer in
status; apiosk_execute_plan asks nothing and accepts nothing but the
plan_token, so it cannot build a plan, change one, or re-open a decision that
was already made.
How the user is asked
The choice and the approval are the same question in three renderings, built from one description of the offers, so a row is called the same thing wherever it appears:
Host | What the person sees |
Implements MCP elicitation (Claude Code) | A native picker: |
Renders UI resources (MCP Apps SEP-1865, OpenAI Apps SDK) | A card: |
Neither |
|
Interactive UI in Claude's own chat surfaces is limited to connectors approved for the Connectors Directory, so the elicitation path is what a Claude user gets today and the cards are what ChatGPT and MCP-UI hosts get.
The three outcomes that are not failures
apiosk_execute can come back without a result, and none of these should be
retried blindly:
| Meaning | Next step |
| The buyer's rules need a human to say yes. Nothing was paid and nothing was called. | Tell the user, then poll |
| The balance cannot cover the call. | Call |
| This connection's per-call or daily ceiling refused the call. | Do not retry; only the buyer can change it. |
| The connection expired or was revoked. | Call |
apiosk_execute_plan adds one more, and it is not a failure either:
| Meaning | Next step |
| The quote expired, the plan moved, or the fee schedule changed since the approval. Nothing was reserved. | Do not retry the token. Call |
Quick start
npx -y @apiosk/mcpThe scoped npm package is canonical:
npm install @apiosk/mcpIt exposes the same CLI binaries:
npx -y @apiosk/mcp
apiosk-mcp
apiosk-mcp-server
apioskThe PyPI package is a launcher for it, so uvx apiosk-mcp starts the same
server as npx -y @apiosk/mcp.
The hosted server starts its OAuth handoff on the first /apiosk, discovery or
comparison request, then resumes the request after the buyer approves the
connection at buy.apiosk.com. For local stdio, set
APIOSK_CONNECT_TOKEN or call apiosk_connect for the connection link.
Agent configuration
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"apiosk": {
"command": "npx",
"args": ["-y", "@apiosk/mcp"]
}
}
}VS Code
code --add-mcp '{"name":"apiosk","command":"npx","args":["-y","@apiosk/mcp"]}'Or .vscode/mcp.json (VS Code uses a servers key):
{
"servers": {
"apiosk": {
"command": "npx",
"args": ["-y", "@apiosk/mcp"]
}
}
}The hosted endpoint instead of the local package:
{
"servers": {
"apiosk": {
"type": "http",
"url": "https://mcp.apiosk.com/mcp"
}
}
}Claude Code
claude mcp add --transport http apiosk https://mcp.apiosk.com/mcpCursor, Windsurf, Cline, Continue, Goose
{
"mcpServers": {
"apiosk": {
"command": "npx",
"args": ["-y", "@apiosk/mcp"]
}
}
}A local checkout
{
"mcpServers": {
"apiosk": {
"command": "node",
"args": ["/full/path/to/apiosk-mcp/index.mjs"]
}
}
}ChatGPT and other remote MCP apps
Use https://mcp.apiosk.com/mcp. The first tool that reads provider data starts
OAuth automatically when the session is not connected; sign-in and spending
limits live on the buyer portal. apiosk_connect remains available as the
read-only diagnostic and reconnection entrypoint.
The OpenAI plugin package lives in plugin/apiosk. It combines this MCP server
with the apiosk skill, so one installation provides both the live tools and
the workflow instructions. The hosted server also exposes the bounded MCP
skills extension used by OpenAI's Scan Tools action. A skill-only upload is
available from the same source at plugin/apiosk/skills/apiosk.
Examples
Check the connection
{ "name": "apiosk_connect", "arguments": {} }Unconnected, it returns the portal link and says plainly that nothing can be paid for yet. Connected, it names the wallet, the policy and the exact per-transaction and daily limits, so the agent can quote them to the user without a second round trip.
Find and compare
{ "name": "apiosk_discover", "arguments": { "query": "realtime USD to EUR exchange rate" } }{ "name": "apiosk_compare", "arguments": { "query": "realtime USD to EUR exchange rate", "max_price_usdc": 0.01 } }Every score carries the weights that produced it and each candidate's contribution per dimension, so it can be recomputed rather than trusted. Dimensions Apiosk has not measured are named and dropped from the weighting — never scored zero.
Quick one-shot flow (/apiosk)
{ "name": "apiosk", "arguments": { "query": "realtime USD to EUR exchange rate", "max_price_usdc": 0.01 } }The result card shows the shared ranking's top provider, the exact per-call
price and any required fields. Approve runs apiosk_execute; Deny stops
without spending. In clients without MCP Apps UI, render those same two named
choices and wait for the user's decision.
Buy the one the user chose
{
"name": "apiosk_execute",
"arguments": {
"offer_token": "tok_...",
"max_price_usdc": 0.004,
"input": { "from": "USD", "to": "EUR" },
"input_parts": {
"path": {},
"query": { "from": "USD", "to": "EUR" },
"body": {}
},
"prompt": "realtime USD to EUR exchange rate"
}
}The ceiling is not decoration: the call is refused rather than paid if the real price is above the number the user was shown.
Wait on an approval
{ "name": "apiosk_approval_status", "arguments": { "approval_id": "2f8656ec-e667-4c8f-a340-a8dc2ddc36bc" } }Plan a job that needs more than one call
{
"name": "apiosk_plan",
"arguments": {
"question": "Is Mollie a healthy company?",
"intent": {
"subjects": [{ "role": "subject", "known": { "company.name": "Mollie B.V." } }],
"required_outputs": ["company.profile", "company.financial_statements"],
"jurisdiction": "NL"
},
"max_price_usdc": 0.25
}
}The result carries the steps in the order they run, whatever the plan could not
reach, one total_usdc ceiling and a signed plan_token. It spends nothing.
A company.registration.nl.kvk in known removes the identity lookup from both
the steps and the price.
Start it, watch it, answer it
{ "name": "apiosk_execute_plan", "arguments": { "plan_token": "pt_..." } }
{ "name": "apiosk_job_status", "arguments": { "job_id": "…", "after": 0 } }
{ "name": "apiosk_resolve_job", "arguments": { "job_id": "…", "node_key": "n_lookup", "chosen": "30528634" } }
{ "name": "apiosk_cancel_job", "arguments": { "job_id": "…" } }Starting the same approved plan twice gives one job, not two. The job outlives the conversation, and the same job is visible and manageable in the Apiosk app — only cancel one when the user asks to stop.
Environment variables
APIOSK_CONNECT_TOKEN— a connect token from buy.apiosk.com, naming the account and spending policy for local stdio. Hosted MCP obtains it through OAuth.APIOSK_GATEWAY_URL— override the gateway base URL. Leave unset unless testing against staging.APIOSK_BUYER_PORTAL_URL— override the portal linkapiosk_connecthands back.APIOSK_MCP_OAUTH_SECRET— signing secret for hosted OAuth codes, access tokens and refresh tokens.APIOSK_MCP_PUBLIC_BASE_URL— this server's own public URL, used in the served discovery document.
There is no APIOSK_PRIVATE_KEY. This server never holds a key; the gateway
settles from the buyer's managed wallet.
Remote HTTP server
Hosted OAuth metadata and authorization routes live on the same host:
https://mcp.apiosk.com/.well-known/oauth-authorization-serverhttps://mcp.apiosk.com/.well-known/oauth-protected-resource/mcphttps://mcp.apiosk.com/authorizehttps://mcp.apiosk.com/tokenhttps://mcp.apiosk.com/register
A machine-readable index of every paid x402 route published through Apiosk, reshaped from the gateway's own document:
https://mcp.apiosk.com/.well-known/apiosk-routes.json(alias/discovery)
Test it:
curl https://mcp.apiosk.com/healthcurl https://mcp.apiosk.com/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Publishing an API
Publishing is not part of this server. The gateway's /v1/apis/* endpoints and
the provider portal serve it. This repository is the buyer's side of the
conversation, and nothing else.
Development
npm install
npm test # node --test
npm run dev # HTTP server on :3000
node index.mjs # stdiotest/surface.test.mjs asserts the tool list is exactly the six, by name, and
that the published manifests agree with it. If it fails, either a tool was added
without a decision or a manifest drifted — a tool name that disagrees across
package.json, server.json, dxt.json and this file is a broken install.
License
MIT