π€ Tellia MCP β
Use Tellia from Claude Desktop or Claude Code β list/read/write workspaces, run admin reviews, and inspect drafts, all via natural-language prompts.
The Tellia MCP server exposes our backend to LLM clients through the Model Context Protocol. Reviewers and engineers point Claude at it once and then drive Tellia from chat: "list drafts to review for Beauvignac", "flag record 6a18β¦ as bug, the transcript says 4 ha not 4000", "create a workspace called Operations".
This page is the setup + usage guide. For the architecture (transports, impersonation, session model, deploy), see how it works.
What you can do β
| Capability | Tools |
|---|---|
| Identity & impersonation | tellia_whoami, tellia_act_as, tellia_stop_impersonating |
| Browse | tellia_list_companies, tellia_list_users, tellia_list_workspaces, tellia_list_records, tellia_get_* |
| Author records | tellia_create_record, tellia_update_record, tellia_delete_record, tellia_bulk_* |
| Workspaces | tellia_create_workspace, tellia_update_workspace, tellia_describe_workspace |
| Call review | tellia_list_drafts_to_review, tellia_get_draft, tellia_review_records |
tellia_describe_workspace is the right starting point before authoring records into an unfamiliar workspace β it returns a JSON Schema for the workspace's fields payload, including the {value, refId} envelope for reference fields and the GeoJSON layout for geometry.
Getting an API key β
Two flavours:
- Super-admin key (
isSuperAdmin: true) β sees everything, can impersonate any company user. Use for admin reviews, cross-company tooling. Mint via the Admin UI (/data/api-keys) orPOST /api-keysas a super-admin Firebase user. - Company-scoped key (
companyId: <id>) β bound to a single company. Use for partner integrations or automations that should not leave one tenant.
The key is returned once at creation (rawKey, format tia_β¦). Store it like a password.
Setup β Claude Desktop β
Claude Desktop spawns MCP servers as local subprocesses. Since our server runs over HTTP (so reviewers don't have to clone the repo and run Node), Desktop needs the mcp-remote bridge, which forwards stdio β HTTP and attaches the API key as a header.
Open Claude Desktop β Settings β Developer β Edit Config. Add (or merge into) mcpServers:
{
"mcpServers": {
"tellia": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://<mcp-server-url>/mcp",
"--header",
"x-api-key:tia_..."
]
}
}
}Pick the right URL:
| Environment | URL |
|---|---|
| Local dev (against your tunnel) | https://<your-subdomain>-mcp.dev.review-time.info/mcp |
| Staging (Railway) | https://<railway-domain>/mcp |
Save the file β fully quit Claude Desktop (βQ on macOS, not just close the window) β relaunch. First launch downloads mcp-remote via npx (one-time, a few seconds).
In a new chat, click the π connectors icon β tellia should be listed as Connected. Smoke-test:
"Call
tellia_whoami."
You should see your identity + super-admin flag.
OAuth wizard
If Claude Desktop's GUI Add Custom Connector wizard asks for OAuth client id/secret, close it. Our auth is header-based (x-api-key); the OAuth flow is for hosted MCP servers like Linear or Slack. Edit the JSON file directly β the GUI doesn't currently expose custom headers.
Setup β Claude Code β
Same idea, simpler config. From the repo root, add a project-local .mcp.json (already gitignored):
{
"mcpServers": {
"tellia": {
"type": "stdio",
"command": "node",
"args": ["/abs/path/to/tell-ia-solutions/apps/agri-mcp/dist/index.js"],
"env": {
"TELLIA_API_URL": "http://localhost:3888",
"TELLIA_API_KEY": "tia_..."
}
}
}
}This uses the stdio entry of the MCP server β no mcp-remote shim, no HTTP server needed. Run pnpm --filter @tellia-solutions/mcp build once, then claude mcp list should show tellia β Connected.
You can also point Claude Code at the HTTP server (staging or your tunnel) using type: "http" + headers.x-api-key β works in recent Claude Code versions.
Common flows β
Impersonate a company user β
Super-admin keys have no memberships. Most company-scoped reads and all writes require impersonating into a tenant first.
"List companies, pick Beauvignac, list its users, and start acting as the first admin."
Claude calls tellia_list_companies β tellia_list_users β tellia_act_as. From then on, every tool call in the session runs as that user β reads are scoped, writes are authored by them. tellia_stop_impersonating reverts to the bare key.
Review a draft β
"List the next 5 drafts that need review for the company I'm impersonating, open the first one, and walk me through whether each record is consistent with the transcript and attachments."
Claude calls tellia_list_drafts_to_review β tellia_get_draft. The draft response includes the transcript, the parseResults (records extracted from the call), and attachments with ready-to-fetch viewUrl β Claude can read image attachments directly. Claude proposes a verdict per record. You must explicitly approve each verdict in chat before Claude calls tellia_review_records. The tool description forbids auto-validation.
Statuses are validated (record matches transcript/attachments) or bug (it does not β supply notes describing the inconsistency). The draft's validation.status recomputes from the latest review of each record.
Bulk-import records β
"Here's a CSV with 80 fields. Create the matching records in the Parcellaire workspace under val de gascogne."
Claude calls tellia_describe_workspace first to learn the field shape, then tellia_bulk_create_records. For the Fields workspace (key=tellia:fields), the paired Field document is created alongside each ParseResult. Above 50 records on the generic path, the call returns a jobId β poll with tellia_get_bulk_import_status.
Cross-reference records β
When writing a value into a reference-typed field, use the envelope:
{ "value": "Display name", "refId": "<target record internalReferenceId>" }refId must be the target record's internalReferenceId, not its _id. Both are returned by tellia_list_records / tellia_get_record β always pick internalReferenceId. _id breaks on re-import and dedup. tellia_describe_workspace shows this requirement in the JSON Schema for any reference field.
Troubleshooting β
| Symptom | Likely cause | Fix |
|---|---|---|
| π menu empty after restart | Config file path / JSON syntax error | Verify ~/Library/Application Support/Claude/claude_desktop_config.json parses; check ~/Library/Logs/Claude/mcp.log |
mcp-remote error 500 | Local MCP server not running | pnpm mcp from repo root |
mcp-remote error 404 (frp HTML) | Tunnel up but no local backend | Same β start pnpm mcp |
Internal server error on init | NestJS DI broken (tsx not emitting decorator metadata) | Use the provided dev script (tsc --watch + node --watch), not raw tsx |
Only super-admin API keys may impersonate | Wrong key type | Mint a super-admin key, or use the company-scoped key directly |
recordIds do not belong to the impersonated user's company | Cross-tenant write attempted | tellia_act_as into the right company first |
| Tool descriptions stale in chat | Claude Desktop cached old MCP capabilities | βQ + relaunch Desktop |
For everything else, the MCP server logs every request to stdout β watch the pnpm mcp terminal during a call. The backend also logs each call via the API-key audit log (api_key_audit_logs collection, viewable in the Admin UI).