Factuarea APIDevelopers
Fixed

MCP: clearer errors, ChatGPT sign-in and steadier tool lists

MCP tools report business errors again, OAuth accepts private_key_jwt for clients like ChatGPT, tools/list cursors last 24 hours and four old contact tool names are retired on 15 November 2026.

We have spent some time connecting the MCP server to real clients and fixed what got in their way. Everything below applies to the public server and to the local stdio server. See the protocol guide, connecting a client and the tool catalog.

  • Business errors from tools are back. A tool that failed for a business reason used to reach the client as a result with the generic text "An internal server error occurred.", which gave an agent nothing to act on. Now a business rule, a missing resource, a conflict or a validation failure returns the JSON-RPC error -32008: error.message is the v1 code, error.data.code is that same code (for example task_not_found, invoice_not_found or task_label_name_in_use), error.data.http_status gives the category and a hint in Spanish says what to do. A missing permission is -32005 insufficient_scope (403), an invalid credential is -32001 invalid_token (401), and an unexpected failure is -32603 internal_error (500) without exposing the internal message. See errors.
  • private_key_jwt for clients identified by a metadata document. Clients such as ChatGPT or Claude, whose client_id is an HTTPS URL, can authenticate at /api/oauth/token, /revoke and /introspect with a JWT signed with RS256 or ES256, using a key published at the jwks_uri of their document. The metadata at /.well-known/oauth-authorization-server announces it. When /oauth/authorize cannot accept a document, it answers invalid_client with a readable error_reason and, in a browser, shows a screen that explains the problem in Spanish, English and Catalan. Dynamic registration still accepts only none and client_secret_basic. The details are in clients identified by a metadata document.
  • tools/list cursors last 24 hours. They used to expire after 120 seconds. A cursor is now tied to the identity that received it (the API key, or the company, user and OAuth client), so renewing the access token with the refresh token does not invalidate it. If the visible catalog changes between pages, the server returns the first page of the current catalog instead of an error.
  • The first page carries the whole catalog. Without per_page, a single response includes every tool (the default page is large enough for the whole public catalog, about 552 tools), so a client that does not paginate sees all of them and no nextCursor.
  • Four old contact tool names are retired on 15 November 2026. Until then search_clients, find_client_by_tax_id, create_client and bulk_create_clients still work in tools/call and point to search_contacts, find_contact_by_tax_id, create_contact and bulk_create_contacts. They are not listed in tools/list, and each response carries _meta["io.factuarea/deprecation"] with the successor and the date. After that date they answer as unknown tools. See the note in the catalog.