Getting our MCP server into Claude’s connector directory
What Claude’s connector directory flagged on our MCP server, the missing token audience that broke sign-in, and the scopes ChatGPT needed.
On this page
Temlavo's MCP server is listed in Claude's connector directory (opens in a new tab). I submitted it on 25 October 2026, and it was published two days later. It has three tools: one submits an invoice for extraction, one reads the result and its checks, and one reads page usage.
The submission portal reads your tools from the live server and flags problems before you submit. It flagged two things in our tools, and its compliance step made me rewrite two tool descriptions. Separately, getting Claude and then ChatGPT to sign in took a fix each. Here is each one: what the message said and what we changed.
What the portal checks
You submit a remote server to the Connectors Directory through the developer portal at claude.ai/directory/manage (opens in a new tab). The portal connects to your server and syncs its tools. It then asks for listing details, how users sign in, a test account for reviewers, and seven policy acknowledgments. Anthropic's submission guide (opens in a new tab) lists every step. Our findings came from the tools step and the compliance step.
“Add a type to this parameter”
The portal marked three parameters as "to fix": document_id, idempotency_key and accounting_entity_id. All three reuse shared definitions from our API contract, so the tool schema pointed at the definition with $ref and left type out, because the definition already states it:
"document_id": {
"description": "The document to read, as `submit_invoice` returned it.",
"$ref": "#/$defs/DocumentId"
}That is valid JSON Schema, but the portal reads a parameter's type without following $ref. The fix was to repeat the target's type next to the reference:
"document_id": {
"description": "The document to read, as `submit_invoice` returned it.",
"$ref": "#/$defs/DocumentId",
"type": "string"
}We only do this in the schemas MCP clients receive. The OpenAPI document and the invoice.v1 schema still state each type in one place.
“Missing title annotation”
This one came as a suggestion. Each tool already had a title, but the portal also looks for title inside annotations, which the MCP spec defines as a separate field. Our annotations now repeat it:
{
"name": "get_usage",
"title": "Get account usage",
"annotations": {
"title": "Get account usage",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": true,
"openWorldHint": false
}
}The portal sorts tools into read-only and write from readOnlyHint, so set it and destructiveHint deliberately. Our submit tool is a write, but it isn't destructive, and it is idempotent: retrying with the same key and file returns the same document.
Tool descriptions describe, they don't instruct
One compliance acknowledgment says tool descriptions contain no instructions about model behavior, other tools, or external instruction sources. Two of ours did. The submit tool told the model to generate and keep a key for retries, not to ask users for technical IDs, and to retrieve the document next. The usage tool told it not to call usage automatically before every submission.
I rewrote the submit tool's description as facts: it returns a document ID once processing has started, and a retry with the same key and file returns the existing document instead of creating a new one. The key's parameter description says the client generates it once and reuses it for every retry. From the usage tool I simply removed the instruction.
A 401 on every call after sign-in
This one came before the submission, when I first connected Claude in production. Sign-in completed and Claude received a token, but every call to /mcp came back 401.
The token had no aud claim. Our server only accepts tokens issued for its own resource URL, https://api.temlavo.com/mcp, so it refused them, correctly. The fix was on the authorization server: turning on the setting that puts the audience in access tokens (in Clerk, Include Audience), then reconnecting the connector. The server's check stayed as it was.
If you see this, decode the access token and look at aud before you loosen anything. It should match the resource in your protected resource metadata.
Claude's OAuth client: scopes and callback URLs
Claude offered no scope choice for the connector and requested all three application scopes our server lists, so the OAuth client it uses has to allow all three. Ours also allows offline_access, for refresh tokens. It is a public client with PKCE and no secret, registered with Claude's two callback URLs:
https://claude.ai/api/mcp/auth_callback
https://claude.com/api/mcp/auth_callbackThat is also the client the directory holds for Temlavo. In the portal's authentication step I entered its client ID and no secret.
ChatGPT and invalid_scope
ChatGPT identifies itself with a Client ID Metadata Document: its client ID is a URL to a JSON file describing the client, so there is nothing to pre-register. Once we turned on support for those documents, ChatGPT's sign-in failed with invalid_scope, first for openid and then for email.
ChatGPT requests the OpenID scopes your issuer advertises, and OpenAI's auth docs (opens in a new tab) say to enable every advertised scope for the client. Ours advertises openid, email and profile, so we allowed all three. That means an app you approve receives your email address and name, and the privacy notice now says so.
What “listed” means
Anthropic scans each submission automatically and, by default, lists it as a Community connector. Community connectors aren't verified by Anthropic; Verified is a separate label with its own process, described in connector verification (opens in a new tab). So we say Temlavo is listed in the directory, not that it's verified.
Try it
Add Temlavo to Claude (opens in a new tab) from the listing, or follow the MCP guide for ChatGPT, Claude Code and other clients. The announcement post has a sample invoice to try.
Try the API in the playground
Compare sample invoices with their extracted fields, checks and full API responses. No account needed.
More from the blog
Why I built Temlavo
Temlavo extracts invoice data and tells your code which invoices not to trust. Here is why I built it that way, and what it deliberately does not do.
Extract invoices from Claude with the Temlavo MCP server
Connect Temlavo to Claude or another MCP client and ask in plain language: extract this invoice, does it need review, how many pages are left.
How to validate extracted invoice totals: rounding, tolerances and tax
The rules I use to check that extracted invoice amounts add up: lines, subtotal, tax rounding, total tax, total and amount due, with code to copy.