MCP server
Ocost is also a Model Context Protocol server: Claude Desktop, Claude Code, Cursor and other assistants search your documents, read them as ocost.document.v1, ask for your figures and send files, with your API key; claude.ai and ChatGPT connect as the person who allows them.
Address and key
https://api.ocost.io/public/mcp
Authorization: Bearer ocost_sk_<id>_<secret>- Transport: Streamable HTTP, stateless; every request stands alone.
https://app.ocost.io/public/mcpis the same server. - Key: an API key from Settings › API, in every request's
Authorizationheader. Without a valid one:401withWWW-Authenticate: Bearer. Revoking works at once. Your Ocost sign-in is not a key. - One key per assistant, with only the scopes it needs, so you see its last use and can revoke it alone.
- Apps that add servers only through OAuth (the connectors of claude.ai and ChatGPT on the web) need no key: Connect claude.ai or ChatGPT.
Tools
The files' tools are the API's routes; the others are the tools Ocost's own chat answers with, the same ones, under the same rights.
| Tool | Scope | Does |
|---|---|---|
search_documents | search:read | What documents say, as a table: one row per document with its page and passage. match: exact (every document holding the text as written, never a look-alike), keywords, meaning, hybrid (the default; by the words when meaning is unavailable, notes: keywords_only). Arguments: query; optionally document_id, kinds, family, company_id, project_id, site_id, issued_since, issued_until, due_since, due_until, gross_min, gross_max, direction (incoming, outgoing), status (open, paid), category (an ECLASS code), limit. |
find_category | figures:read | Words in any of Ocost's languages ("Lebensmittel", "cleaning") to ECLASS codes, the best first: code, level, name, segment; for query_figures' class or search_documents' category. Argument: words. |
search | search:read | For ChatGPT's deep research and company knowledge: query → results of id, title, url (the document's page in Ocost). |
fetch | search:read | A search result whole: id → id, title, text (its pages, up to four), url, metadata. |
read_document | documents:read | One document's pages as its file says them, up to four pages and 12,000 characters. Arguments: document_id, optionally pages. |
get_document | documents:read | Like GET /public/v1/documents/{document_id}: a document as ocost.document.v1. Argument: document_id. |
find_documents | documents:read | Documents newest first, optionally of one kind, family or company_id, with number, company, direction, date, gross and status. |
find_contracts | documents:read | Contracts with their side, party, term, notice, recurring amounts; optionally one company_id's. |
find_company | documents:read | Suppliers and customers whose name contains name, with their ids. |
find_project | documents:read | Projects whose name contains name, with their ids. |
company_documents | documents:read | A company's documents both ways. Argument: company_id. |
invoice_detail | documents:read | One invoice as its page shows it: amounts, due date, discount, its order and trail. Argument: invoice_id. |
open_decisions | documents:read | The open decisions of the person who connected (OAuth only): a key made in Settings has no person. |
get_file | documents:read | Like GET /public/v1/files/{file_id}: status, reason, documents. Argument: file_id. |
list_files | documents:read | Like GET /public/v1/files, oldest change first. Arguments: status, updated_since, cursor, limit. |
company_profile | figures:read | A company's year: bought and sold, terms both ways, what is open, how long each side took to pay. Argument: company_id. |
project_overview | figures:read | A project's plan against spent and committed, by supplier and month, and its documents. Argument: project_id. |
query_figures | figures:read | Adds up records for a chart, a comparison or a count, as a table: a source, a measure, one or two group_by (ECLASS classes at every level, cost types), filters, a year, compare (previous period or year), top_n, matching (the documents a search finds). Its description lists every source and field. |
top_companies | figures:read | The top suppliers or customers by net over a period in plain words ("2025", "Q3 2025", "last year"; the last 12 months by default), in an ECLASS category too: rank, company, net, gross, share, documents, the rest and a total row. |
spend_over_time | figures:read | Net by month, quarter or year over a period, every bucket (zeros too), by company or category as a column each; the last row the totals. |
largest_documents | figures:read | The largest documents by gross over a period, a list: rank, number, company, issued, net, gross; every invoice to pay unless a kind is asked. |
payables_due | figures:read | What to pay when to keep Skonto, as a table: unpaid supplier invoices due in a window (this_week, next_7_days, next_14_days, next_30_days, this_month) or from since to until, each with its due day, Skonto deadline and saving. Nothing is overdue while no bank account is connected. |
vat_preview | figures:read | A USt-Voranmeldung preview for a period (2026-10, 2026-Q4) by Kennzahl (81, 86, 66, 61, 46/67, 89/93, …), each with its invoices (kz). A preview for the tax adviser, never a filing. |
check_invoice | documents:read | § 14 UStG fields and the e-invoice check of one or many supplier invoices (document_ids, company_id, issued dates): what is missing and what costs the input VAT deduction. |
find_anomalies | figures:read | Duplicate invoices, a supplier's bank account changed, a price above its order's, from since to until (the last 90 days), each with its documents. For a person to check, never acted on. |
supplier_profile | figures:read | A supplier in one call (company_id): spend by month and class, terms and Skonto, how fast you pay, open items, the price history of its top items, its documents and contracts. |
export_table | exports:write | A table as Excel (xlsx) or CSV: send back a table's query (tool and args, unchanged) and a title; Ocost asks it again for all rows (up to 50 000) and answers a signed link, valid 30 minutes, as text and as a resource_link. |
make_datev_export | exports:write | The DATEV export (EXTF Buchungsstapel, an overview and the receipts as one ZIP) of starts_on to ends_on, days of one fiscal year, with a signed link. Only through the owner's or the accountant's own connection. |
send_file | documents:write | Like POST /public/v1/files. Arguments: filename, content_base64 (the bytes in base64), optionally external_ref. |
- Answers are JSON, as text and as
structuredContent, each tool with itsoutputSchema; every tool butsend_file,export_tableandmake_datev_export(which make a file) is marked read-only. Lists and tables saytotal(total_rows) andtruncated: narrow the question, or page through files withlist_files'cursor. - Tables and charts: the lists and
query_figurescome with an interactive table or chart (MCP Apps,ui://ocost/tableandui://ocost/chart) in apps that show them, such as claude.ai and ChatGPT; every other app reads the same JSON. Their links open the record in Ocost and nothing else. - What a document says comes inside
<document-text source="…">…</document-text>, each line marked¦: words written by others, to read as data, never as instructions; quote them without the marks. - The API's limits apply: calls a minute per scope (Limits and errors), 25 MB per file before base64, the same formats, resent bytes read and counted once, each document read counted against your plan.
- Refusals (missing scope, not found, too many calls) come as the tool's error: the problem's JSON with
statusandtype, or the reason in words. Another business's id is not found. - No tool deletes, approves or orders, since an assistant may misread. Use
DELETE /public/v1/files/{file_id}or Ocost. - No URLs:
send_filetakes bytes, never a link. It answers the file only; whether it was new and the documents left are inPOST /public/v1/filesand Settings › Plan. - Requests are capped at 4 MB, except for keys with
documents:write, which may send a file's base64. Past it:413. - Every call is recorded (the tool, its arguments cut short, how many records it answered, how it ended; never a document's words): the owner and the accountant see a key's last calls in Settings › API.
Scopes and who the tools act as
| Scope | Allows |
|---|---|
search:read | search_documents, search, fetch |
documents:read | reading documents, files, contracts, companies, projects, invoices, decisions |
figures:read | company_profile, project_overview, query_figures, top_companies, spend_over_time, largest_documents, find_category, payables_due, vat_preview, find_anomalies, supplier_profile |
exports:write | export_table, make_datev_export |
documents:write | send_file |
- A key made in Settings acts as the business: every document outside the Trash, no people's papers (pay, health), no person's own decisions. Only the owner makes one with
figures:read. - A connection made through OAuth (claude.ai, ChatGPT) acts as the person who allowed it: their roles, what they see in Ocost's chat and nothing more. An accountant's connection reads no CFO figures. A person who leaves, or is no longer the owner or the accountant, ends their connections at their next call.
- HR papers stay in Ocost: no key or connection ever reads people's papers (pay, health, sick notes), whoever allowed it; they are read in Ocost itself.
Claude Code
claude mcp add --transport http ocost https://api.ocost.io/public/mcp \
--header "Authorization: Bearer $OCOST_KEY"claude mcp list then shows ocost connected. To share it in a repository, put it in .mcp.json with the key from each developer's environment, never in the file:
{
"mcpServers": {
"ocost": {
"type": "http",
"url": "https://api.ocost.io/public/mcp",
"headers": { "Authorization": "Bearer ${OCOST_KEY}" }
}
}
}Claude Desktop
Add Ocost to claude_desktop_config.json (Settings › Developer › Edit Config). mcp-remote forwards the requests with the header and needs Node.js.
{
"mcpServers": {
"ocost": {
"command": "npx",
"args": [
"-y",
"mcp-remote@0.15.2",
"https://api.ocost.io/public/mcp",
"--header",
"Authorization:${OCOST_AUTH}"
],
"env": { "OCOST_AUTH": "Bearer ocost_sk_…" }
}
}
}Restart Claude Desktop; the tools are under the tools button. Keep Authorization:${OCOST_AUTH} free of spaces: some clients split arguments there.
Cursor
In ~/.cursor/mcp.json, or .cursor/mcp.json in a project:
{
"mcpServers": {
"ocost": {
"url": "https://api.ocost.io/public/mcp",
"headers": { "Authorization": "Bearer ${env:OCOST_KEY}" }
}
}
}Connect claude.ai or ChatGPT
Apps that add MCP servers only through OAuth, such as the connectors of claude.ai and ChatGPT on the web, need no key: you sign in to Ocost and allow the access.
- Add a connector: in claude.ai under Settings › Connectors › Add custom connector, in ChatGPT as a custom connector in developer mode. Only the URL
https://api.ocost.io/public/mcp; leave the client ID and secret empty. - Sign in: the app opens Ocost. Sign in as always. If you belong to several businesses, pick the right one under Another business.
- Allow: Ocost shows which app wants access, where it goes back to, and the scopes to tick: search documents, read them, read figures, make exports, send files. The owner and the accountant may allow it, as they may make a key; the app then acts as that person, with their rights.
- The app gets an API key of its own with the scopes ticked, "<App> (Connector)" in Settings › API, with its last use. Revoke it there and the app is disconnected at once.
- Ocost's logo shows on the connector; if it still shows a placeholder, connect it again.
- Its access token holds for an hour, then the app gets a new one with its refresh token. 30 days unused end the connection; connect the app again then.
- For developers: OAuth 2.1 with PKCE (S256); the metadata at
https://api.ocost.io/.well-known/oauth-protected-resource/public/mcp(RFC 9728) andhttps://app.ocost.io/.well-known/oauth-authorization-server(RFC 8414); Client ID Metadata Documents and Dynamic Client Registration; redirect URIs https only, exactly as registered.
Any MCP client
- URL:
https://api.ocost.io/public/mcp - Transport: Streamable HTTP (
POST, JSON answers; no SSE stream, no session id) - Header:
Authorization: Bearer ocost_sk_…
To list the tools:
curl -sS https://api.ocost.io/public/mcp \
-H "Authorization: Bearer $OCOST_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2025-11-25" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Example: an Odoo developer
An Odoo developer writing the module from Connecting Odoo, with a key holding search:read and documents:read, asks in Claude Code:
Developer: Find the invoice from Büromöbel Schmidt for the office chairs and show me which fields of
account.moveand its lines each value fills.Assistant calls
find_company(name: "Büromöbel Schmidt"), thensearch_documents(query: "Bürostuhl",company_id: …,kinds: ["invoice"]), finds invoice BS-7790, callsget_documentand answers:seller.vat_idfinds thepartner_id,numberis theref,issue_datetheinvoice_date,due_datetheinvoice_date_due; each of the twolinesbecomes aninvoice_line_idsentry withquantity,priceasprice_unitandvat_ratefinding the purchase tax;totals.gross, 3946.04, checks Odoo's total.Developer: Any credit notes from them since January?
Assistant calls
find_documents(kind: "credit_note",company_id: …): none since January.