{
  "markdown": "<!-- mcp-name: io.github.obcraft/apiosk-mcp -->\n<p align=\"center\">\n  <img src=\"https://apiosk.com/logo.svg\" alt=\"Apiosk\" width=\"120\" />\n</p>\n\n# Apiosk MCP Server\n\n[![smithery badge](https://smithery.ai/badge/olivier-fovn/apiosk)](https://smithery.ai/servers/olivier-fovn/apiosk)\n\n**Buy an API call the way a person would.** Describe the job, see what can do\nit, compare the candidates on price and measured performance, choose one, and\npay for it in USDC over x402 — under limits the buyer set, enforced on every\ncall.\n\n`payments` · `x402` · `commerce` · `usdc` · `api-comparison`\n\n[![MCP Registry](https://img.shields.io/badge/MCP_Registry-io.github.obcraft%2Fapiosk--mcp-2ea44f)](https://registry.modelcontextprotocol.io)\n[![npm](https://img.shields.io/npm/v/@apiosk/mcp?label=npm%20%40apiosk%2Fmcp)](https://www.npmjs.com/package/@apiosk/mcp)\n[![PyPI](https://img.shields.io/pypi/v/apiosk-mcp?label=PyPI%20apiosk-mcp)](https://pypi.org/project/apiosk-mcp/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](#license)\n\n- **Hosted endpoint:** `https://mcp.apiosk.com/mcp` (streamable HTTP; the first data request starts OAuth when needed).\n- **Local stdio package:** `npx -y @apiosk/mcp` or `uvx apiosk-mcp`.\n- **Buyer portal:** [buy.apiosk.com](https://buy.apiosk.com) — sign in, fund a wallet, set the limits, approve a held purchase.\n\n## The eleven tools\n\nTwo paths, and the same rules on both. `apiosk` is the one-shot entrypoint for\nfast shopping: it returns the App's own top ranked runnable provider and\napproval card. An agent does not browse a menu: it reads descriptions and picks,\nso every tool here earns its place in one of the two flows.\n\n**One call**, when a single API answers the question:\n\n| Tool | What it answers | Spends |\n| --- | --- | --- |\n| `apiosk` | Return the top ranked runnable provider, exact price, required inputs and Approve/Deny card. | no |\n| `apiosk_connect` | Can this session buy? Which wallet, which policy, which limits. Returns the portal link when there is no connection. | no |\n| `apiosk_discover` | What can perform this job? Sweeps the reviewed Apiosk catalogue **and** the wider x402 ecosystem. | no |\n| `apiosk_compare` | How do the candidates perform against *my* requirements? Price, measured p95 latency, measured success rate and input fit, each offer carrying a stable `offer_id`. | no |\n| `apiosk_execute` | Run the offer the user chose, at the price they were shown. | **yes** |\n| `apiosk_approval_status` | What happened to the purchase the buyer's rules put on hold? | no |\n\n**Several calls**, when a lookup's result feeds the next call, or several facts\nare wanted about one subject:\n\n| Tool | What it answers | Spends |\n| --- | --- | --- |\n| `apiosk_plan` | 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 `plan_token`. | no |\n| `apiosk_execute_plan` | Start the plan the user approved, by `plan_token` and nothing else. | **yes** |\n| `apiosk_job_status` | Where has the running plan got to, and what happened since the last cursor? | no |\n| `apiosk_resolve_job` | Which subject was meant, when the job stopped to ask? | no |\n| `apiosk_cancel_job` | Stop dispatching further calls. Calls already sent are still settled. | no |\n\nThe plan is compiled, deduplicated and priced by the gateway, never here: a\nlookup two branches both need is bought once, and a fact you already hold\nremoves its lookup from the plan and from the price. The App and this server\nshow the same `plan_hash` and the same amount for the same intent because\nexactly one of them computes it.\n\nAnything a buyer needs that is not on this list is a link to\n[app.apiosk.com](https://app.apiosk.com), not a tool. This server holds no keys,\nprices nothing and moves no money.\n\n### The one rule\n\n`apiosk_compare` and `apiosk` return offers. **A person approves or denies the\npurchase.** The quick card states the provider and exact price and supplies the\ntwo actions; do not add a second prose confirmation. Only Approve may pass the\nsigned `offer_token`, exact `max_price_usdc` ceiling and entered inputs to\n`apiosk_execute`. Deny stops without spending.\n\nA plan is the same rule at plan scale: **one confirmation, for the whole plan,\nat the whole price.** `apiosk_plan` asks it once and returns the answer in\n`status`; `apiosk_execute_plan` asks nothing and accepts nothing but the\n`plan_token`, so it cannot build a plan, change one, or re-open a decision that\nwas already made.\n\n### How the user is asked\n\nThe choice and the approval are the same question in three renderings, built\nfrom one description of the offers, so a row is called the same thing wherever\nit appears:\n\n| Host | What the person sees |\n| --- | --- |\n| Implements MCP elicitation (Claude Code) | A native picker: `apiosk_discover` lists the runnable offers with their prices, `apiosk` asks Approve or Deny with the price on the button, `apiosk_plan` asks Approve or Deny for the whole plan at its one ceiling. The answer comes back in `chosen` / `status`. |\n| Renders UI resources (MCP Apps SEP-1865, OpenAI Apps SDK) | A card: `ui://apiosk/results-picker.html` picks an offer and collects its inputs, `ui://apiosk/connect-card.html` shows the balance and limits, `ui://apiosk/offer-card.html` approves one offer, `ui://apiosk/plan-card.html` approves one plan, `ui://apiosk/result-canvas.html` shows the result. One document serves both protocols. |\n| Neither | `presentation`, printed verbatim, and the agent asks which one they want **by name**. Never ask somebody to reply with a number. For a plan the fallback is the App approval link in `approval.approve_url`. |\n\nInteractive UI in Claude's own chat surfaces is limited to connectors approved\nfor the Connectors Directory, so the elicitation path is what a Claude user gets\ntoday and the cards are what ChatGPT and MCP-UI hosts get.\n\n### The three outcomes that are not failures\n\n`apiosk_execute` can come back without a result, and none of these should be\nretried blindly:\n\n| `status` | Meaning | Next step |\n| --- | --- | --- |\n| `approval_required` | The buyer's rules need a human to say yes. Nothing was paid and nothing was called. | Tell the user, then poll `apiosk_approval_status`. Retry only once it reports approved. |\n| `payment_required` | The balance cannot cover the call. | Call `apiosk_connect`, tell the user, stop. |\n| `limit_exceeded` | This connection's per-call or daily ceiling refused the call. | Do not retry; only the buyer can change it. |\n| `not_authorised` | The connection expired or was revoked. | Call `apiosk_connect` for the re-connect link, stop. |\n\n`apiosk_execute_plan` adds one more, and it is not a failure either:\n\n| `status` | Meaning | Next step |\n| --- | --- | --- |\n| `plan_stale` | The quote expired, the plan moved, or the fee schedule changed since the approval. Nothing was reserved. | Do not retry the token. Call `apiosk_plan` again and have the user approve the new plan and its price. |\n\n## Quick start\n\n```bash\nnpx -y @apiosk/mcp\n```\n\nThe scoped npm package is canonical:\n\n```bash\nnpm install @apiosk/mcp\n```\n\nIt exposes the same CLI binaries:\n\n```bash\nnpx -y @apiosk/mcp\napiosk-mcp\napiosk-mcp-server\napiosk\n```\n\nThe PyPI package is a launcher for it, so `uvx apiosk-mcp` starts the same\nserver as `npx -y @apiosk/mcp`.\n\nThe hosted server starts its OAuth handoff on the first `/apiosk`, discovery or\ncomparison request, then resumes the request after the buyer approves the\nconnection at [buy.apiosk.com](https://buy.apiosk.com). For local stdio, set\n`APIOSK_CONNECT_TOKEN` or call `apiosk_connect` for the connection link.\n\n## Agent configuration\n\n### Claude Desktop\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"apiosk\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@apiosk/mcp\"]\n    }\n  }\n}\n```\n\n### VS Code\n\n```bash\ncode --add-mcp '{\"name\":\"apiosk\",\"command\":\"npx\",\"args\":[\"-y\",\"@apiosk/mcp\"]}'\n```\n\nOr `.vscode/mcp.json` (VS Code uses a `servers` key):\n\n```json\n{\n  \"servers\": {\n    \"apiosk\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@apiosk/mcp\"]\n    }\n  }\n}\n```\n\nThe hosted endpoint instead of the local package:\n\n```json\n{\n  \"servers\": {\n    \"apiosk\": {\n      \"type\": \"http\",\n      \"url\": \"https://mcp.apiosk.com/mcp\"\n    }\n  }\n}\n```\n\n### Claude Code\n\n```bash\nclaude mcp add --transport http apiosk https://mcp.apiosk.com/mcp\n```\n\n### Cursor, Windsurf, Cline, Continue, Goose\n\n```json\n{\n  \"mcpServers\": {\n    \"apiosk\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@apiosk/mcp\"]\n    }\n  }\n}\n```\n\n### A local checkout\n\n```json\n{\n  \"mcpServers\": {\n    \"apiosk\": {\n      \"command\": \"node\",\n      \"args\": [\"/full/path/to/apiosk-mcp/index.mjs\"]\n    }\n  }\n}\n```\n\n### ChatGPT and other remote MCP apps\n\nUse `https://mcp.apiosk.com/mcp`. The first tool that reads provider data starts\nOAuth automatically when the session is not connected; sign-in and spending\nlimits live on the buyer portal. `apiosk_connect` remains available as the\nread-only diagnostic and reconnection entrypoint.\n\nThe OpenAI plugin package lives in `plugin/apiosk`. It combines this MCP server\nwith the `apiosk` skill, so one installation provides both the live tools and\nthe workflow instructions. The hosted server also exposes the bounded MCP\nskills extension used by OpenAI's **Scan Tools** action. A skill-only upload is\navailable from the same source at `plugin/apiosk/skills/apiosk`.\n\n## Examples\n\n### Check the connection\n\n```json\n{ \"name\": \"apiosk_connect\", \"arguments\": {} }\n```\n\nUnconnected, it returns the portal link and says plainly that nothing can be\npaid for yet. Connected, it names the wallet, the policy and the exact\nper-transaction and daily limits, so the agent can quote them to the user\nwithout a second round trip.\n\n### Find and compare\n\n```json\n{ \"name\": \"apiosk_discover\", \"arguments\": { \"query\": \"realtime USD to EUR exchange rate\" } }\n```\n\n```json\n{ \"name\": \"apiosk_compare\", \"arguments\": { \"query\": \"realtime USD to EUR exchange rate\", \"max_price_usdc\": 0.01 } }\n```\n\nEvery score carries the weights that produced it and each candidate's\ncontribution per dimension, so it can be recomputed rather than trusted.\nDimensions Apiosk has not measured are named and dropped from the weighting —\nnever scored zero.\n\n### Quick one-shot flow (`/apiosk`)\n\n```json\n{ \"name\": \"apiosk\", \"arguments\": { \"query\": \"realtime USD to EUR exchange rate\", \"max_price_usdc\": 0.01 } }\n```\n\nThe result card shows the shared ranking's top provider, the exact per-call\nprice and any required fields. **Approve** runs `apiosk_execute`; **Deny** stops\nwithout spending. In clients without MCP Apps UI, render those same two named\nchoices and wait for the user's decision.\n\n### Buy the one the user chose\n\n```json\n{\n  \"name\": \"apiosk_execute\",\n  \"arguments\": {\n    \"offer_token\": \"tok_...\",\n    \"max_price_usdc\": 0.004,\n    \"input\": { \"from\": \"USD\", \"to\": \"EUR\" },\n    \"input_parts\": {\n      \"path\": {},\n      \"query\": { \"from\": \"USD\", \"to\": \"EUR\" },\n      \"body\": {}\n    },\n    \"prompt\": \"realtime USD to EUR exchange rate\"\n  }\n}\n```\n\nThe ceiling is not decoration: the call is refused rather than paid if the real\nprice is above the number the user was shown.\n\n### Wait on an approval\n\n```json\n{ \"name\": \"apiosk_approval_status\", \"arguments\": { \"approval_id\": \"2f8656ec-e667-4c8f-a340-a8dc2ddc36bc\" } }\n```\n\n### Plan a job that needs more than one call\n\n```json\n{\n  \"name\": \"apiosk_plan\",\n  \"arguments\": {\n    \"question\": \"Is Mollie a healthy company?\",\n    \"intent\": {\n      \"subjects\": [{ \"role\": \"subject\", \"known\": { \"company.name\": \"Mollie B.V.\" } }],\n      \"required_outputs\": [\"company.profile\", \"company.financial_statements\"],\n      \"jurisdiction\": \"NL\"\n    },\n    \"max_price_usdc\": 0.25\n  }\n}\n```\n\nThe result carries the steps in the order they run, whatever the plan could not\nreach, one `total_usdc` ceiling and a signed `plan_token`. It spends nothing.\nA `company.registration.nl.kvk` in `known` removes the identity lookup from both\nthe steps and the price.\n\n### Start it, watch it, answer it\n\n```json\n{ \"name\": \"apiosk_execute_plan\", \"arguments\": { \"plan_token\": \"pt_...\" } }\n{ \"name\": \"apiosk_job_status\",   \"arguments\": { \"job_id\": \"…\", \"after\": 0 } }\n{ \"name\": \"apiosk_resolve_job\",  \"arguments\": { \"job_id\": \"…\", \"node_key\": \"n_lookup\", \"chosen\": \"30528634\" } }\n{ \"name\": \"apiosk_cancel_job\",   \"arguments\": { \"job_id\": \"…\" } }\n```\n\nStarting the same approved plan twice gives one job, not two. The job outlives\nthe conversation, and the same job is visible and manageable in the Apiosk app —\nonly cancel one when the user asks to stop.\n\n## Environment variables\n\n- `APIOSK_CONNECT_TOKEN` — a connect token from [buy.apiosk.com](https://buy.apiosk.com), naming the account and spending policy for local stdio. Hosted MCP obtains it through OAuth.\n- `APIOSK_GATEWAY_URL` — override the gateway base URL. Leave unset unless testing against staging.\n- `APIOSK_BUYER_PORTAL_URL` — override the portal link `apiosk_connect` hands back.\n- `APIOSK_MCP_OAUTH_SECRET` — signing secret for hosted OAuth codes, access tokens and refresh tokens.\n- `APIOSK_MCP_PUBLIC_BASE_URL` — this server's own public URL, used in the served discovery document.\n\nThere is no `APIOSK_PRIVATE_KEY`. This server never holds a key; the gateway\nsettles from the buyer's managed wallet.\n\n## Remote HTTP server\n\nHosted OAuth metadata and authorization routes live on the same host:\n\n- `https://mcp.apiosk.com/.well-known/oauth-authorization-server`\n- `https://mcp.apiosk.com/.well-known/oauth-protected-resource/mcp`\n- `https://mcp.apiosk.com/authorize`\n- `https://mcp.apiosk.com/token`\n- `https://mcp.apiosk.com/register`\n\nA machine-readable index of every paid x402 route published through Apiosk,\nreshaped from the gateway's own document:\n\n- `https://mcp.apiosk.com/.well-known/apiosk-routes.json` (alias `/discovery`)\n\nTest it:\n\n```bash\ncurl https://mcp.apiosk.com/health\n```\n\n```bash\ncurl https://mcp.apiosk.com/mcp -H \"Content-Type: application/json\" -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\"}'\n```\n\n## Publishing an API\n\nPublishing is not part of this server. The gateway's `/v1/apis/*` endpoints and\nthe provider portal serve it. This repository is the buyer's side of the\nconversation, and nothing else.\n\n## Development\n\n```bash\nnpm install\nnpm test        # node --test\nnpm run dev     # HTTP server on :3000\nnode index.mjs  # stdio\n```\n\n`test/surface.test.mjs` asserts the tool list is exactly the six, by name, and\nthat the published manifests agree with it. If it fails, either a tool was added\nwithout a decision or a manifest drifted — a tool name that disagrees across\n`package.json`, `server.json`, `dxt.json` and this file is a broken install.\n\n## License\n\nMIT\n",
  "bytes": 14746,
  "sha": "9e7bbf9c1933fade5cec363f1e198b514cea560c330532b38a71e0a5aa8a12de",
  "repo_slug": "obcraft/apiosk-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_obcraft_apiosk_mcp_4487c866/readme"
}