MCP documentation
The Tauraco MCP server lets an AI assistant (Claude, an in-house agent, any client compatible with the Model Context Protocol) read a company's data, with the rights of the user who connected it and nothing more. It is read-only, with one non-destructive exception: requesting an export.
Online since 2026-11-05 (answers 401 without a token); sixteen tools, both protocol eras, proven outside production. Without a token,
https://api.tauraco.io/mcpanswers 401 with aWWW-Authenticateheader carryingresource_metadata: this is the expected answer, the one that starts your client's OAuth discovery. No Claude.ai connector has been checked in real conditions yet; the connection procedure below is unchanged.
Address
- Endpoint:
https://api.tauraco.io/mcp(Streamable HTTP transport, stateless). - Aliases online:
https://mcp.tauraco.io/mcp(since 2026-11-05) andhttps://mcp.tauraco.ai/mcp(since 2026-11-06), same server; only/mcpand/.well-known/are served there. The resource identity stayshttps://api.tauraco.io/mcp. - Protected resource (RFC 9728):
https://api.tauraco.io/.well-known/oauth-protected-resource/mcp. - Authorization server:
https://api.tauraco.io(RFC 8414 metadata at/.well-known/oauth-authorization-server).
The two protocol eras
The server is dual-era: one endpoint serves clients of the legacy era and of the modern era. A legacy client facing a modern-only server fails; that is why both are served.
| Legacy era | Modern era | |
|---|---|---|
| Revisions | 2025-11-25 and earlier | 2026-07-28 and later |
| Opening | initialize handshake then notifications/initialized | no session; optional discovery with server/discover |
| Metadata | negotiated once at initialize | carried by every request (_meta) |
| Headers | MCP-Protocol-Version after initialisation | MCP-Protocol-Version, Mcp-Method and, for tools/call, Mcp-Name required on every POST |
| Clients observed | Claude.ai (web, Desktop, mobile), Claude Code v1, MCP Inspector by default | Claude Code v2 (automatic negotiation), Python SDK 2.x in automatic mode |
A header/body mismatch in the modern era gives 400 with JSON-RPC error -32020; an unknown version gives 400 with -32022 and the data.supported list.
Authentication
- Without a token, every request gets
401withWWW-Authenticate: Bearer resource_metadata="https://api.tauraco.io/.well-known/oauth-protected-resource/mcp", scope="mcp:read". This 401 is what triggers the client's OAuth sign-in. - The client reads the resource metadata, then the authorization server metadata.
- Without an identifier, it registers through
/oauth/register(RFC 7591 dynamic registration, opened by a dedicated flag; public client, no scope before consent). Allowed redirect URIs arehttps://claude.ai/api/mcp/auth_callback,https://claude.com/api/mcp/auth_callbackand the loopback (http://localhost:<port>/…,http://127.0.0.1:<port>/…). authorization_codeflow with PKCE S256 andresource=https://api.tauraco.io/mcp: the user picks the company and accepts the scopes on the Tauraco consent page.- Token with audience
tauraco-mcp, 60 minutes, refreshable.
Every request requires mcp:read; every tool also requires its own scope. A missing scope is refused at the HTTP level with 403 and WWW-Authenticate: Bearer error="insufficient_scope", scope="mcp:read invoices:read", which lets the client ask for authorisation again. Client ID Metadata Documents (CIMD) are not supported in v1: a client that cannot do dynamic registration must use an identifier pre-registered by Tauraco.
Tools
All read-only (readOnlyHint: true) except tauraco_request_export (readOnlyHint: false, destructiveHint: false, idempotentHint: true), with typed output, paginated (limit 50 at most, cursor).
| Tool | Data | Scope on top of mcp:read |
|---|---|---|
tauraco_get_company_profile | company profile | company:read |
tauraco_list_customers | customers, without personal data | customers:read |
tauraco_list_suppliers | suppliers, without bank details | suppliers:read |
tauraco_list_invoices | customer invoices (status, customer_id, dates) | invoices:read |
tauraco_get_invoice | one invoice and its lines | invoices:read |
tauraco_list_accounting_entries | summarised journal entries | accounting:read |
tauraco_get_cash_position | cash position, masked IBANs | treasury:read |
tauraco_list_tenders | relayed public tender notices | tenders:read |
tauraco_get_tender | one notice (each read counts as a view on the markets side) | tenders:read |
tauraco_list_financing_requests | financing requests | financing:read |
tauraco_get_financing_status | a request's stage, number of offers received and of recipient banks, without amounts or rates; the same not_found refusal for a missing request or another company's request | financing:read |
tauraco_list_collateral | security interests, with a legal notice | collateral:read |
tauraco_get_collateral_status | one security interest, with a legal notice | collateral:read |
tauraco_list_exports | exports visible to the user | exports:read |
tauraco_get_export_status | status of an export | exports:read |
tauraco_request_export | creates an export (csv, xlsx, json); non-destructive, idempotent over 10 minutes | exports:write |
No tool changes an invoice, moves money, takes a financing decision or performs a legal act.
Resources
tauraco://docs/api, tauraco://docs/mcp, tauraco://schemas/datasets/{code}, tauraco://referentiels/statuts/{domaine}, tauraco://exports/formats, tauraco://guides/{slug}: documentation and schemas only, never company data.
Guarantees
- Isolation: the company comes from the grant; a
tenant_idargument or any key outside the schema is refused. A tool applies exactly the same access check as the matching REST route. - User rights: re-read on every call; a removed role or a revoked grant cuts access on the next call.
- External texts: free texts (descriptions, typed labels, relayed notices) are prefixed with
[donnée externe non vérifiée]("unverified external data") and truncated to 500 characters, so that a model does not mistake them for instructions. - Rate: the same bucket and quota as the public API for the application; without the rate service,
503. Concurrency is capped, body limited to 4 MB. - Log: every call is logged (tool, argument hash, duration, row count); the export request and refusals enter the audit log.
- Hosts and origins: allowed
Hostvaluesapi.tauraco.io,mcp.tauraco.ioandmcp.tauraco.ai(otherwise421); allowedOriginvalueshttps://claude.aiandhttps://claude.com.
Connect a client
These procedures are the clients' own. The server is open since 2026-11-05 and answers as they require (401, protected-resource metadata, dynamic registration); none has been checked end to end against Tauraco yet. Use the https://api.tauraco.io/mcp URL.
Claude.ai (individual plans: Customize › Connectors › Add custom connector; Team and Enterprise: an owner goes through Organization settings › Connectors): enter the server URL, choose automatic registration of the OAuth client, then sign in with your Tauraco account and pick the company. Claude traffic comes from 160.79.104.0/21.
Claude Code:
claude mcp add --transport http tauraco https://api.tauraco.io/mcp
claude mcp list # connection status
claude mcp login tauraco # or /mcp in an interactive session
MCP Inspector: --protocol-era legacy, auto or modern exercises each era; without a token, the command line exits with code 3 (authentication required).
Cursor and other clients: not verified. Their OAuth redirect URI must be in the allowed list, otherwise they must use an identifier pre-registered by Tauraco.
Command-line discovery
#!/usr/bin/env sh
# Découverte MCP : sans jeton, le serveur répond 401 avec l'adresse des métadonnées (RFC 9728).
# MCP discovery: without a token the server answers 401 with the metadata URL (RFC 9728).
set -eu
MCP="https://api.tauraco.io/mcp"
# 1) Ère moderne (2026-07-28) : sans état, en-têtes MCP-Protocol-Version et Mcp-Method.
curl -si -X POST "${MCP}" -H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "MCP-Protocol-Version: 2026-07-28" -H "Mcp-Method: server/discover" \
-d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}' \
| sed -n '1p;/^[Ww][Ww][Ww]-[Aa]uthenticate/p'
# 2) Métadonnées de la ressource protégée, puis du serveur d'autorisation.
curl -sS "https://api.tauraco.io/.well-known/oauth-protected-resource/mcp"
curl -sS "https://api.tauraco.io/.well-known/oauth-authorization-server"
# 3) Ère historique (2025-11-25, celle de Claude.ai) : poignée de main initialize, avec jeton.
if [ -n "${TAURACO_MCP_TOKEN:-}" ]; then
curl -sS -X POST "${MCP}" -H "Authorization: Bearer ${TAURACO_MCP_TOKEN}" \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
fi
Errors
| Situation | Response |
|---|---|
| no token, invalid or expired token | 401 + WWW-Authenticate with resource_metadata |
| revoked grant, deleted account | 401 (grant_revoked) |
| missing tool scope | 403 insufficient_scope with the full scope= |
Host not allowed | 421 |
| rate exceeded | 429 with Retry-After |
| rate service unavailable | 503 |
| business refusal inside a tool | tool result isError: true with a message, without internal details |