Skip to content

πŸ€– 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 ​

CapabilityTools
Identity & impersonationtellia_whoami, tellia_act_as, tellia_stop_impersonating
Browsetellia_list_companies, tellia_list_users, tellia_list_workspaces, tellia_list_records, tellia_get_*
Author recordstellia_create_record, tellia_update_record, tellia_delete_record, tellia_bulk_*
Workspacestellia_create_workspace, tellia_update_workspace, tellia_describe_workspace
Call reviewtellia_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) or POST /api-keys as 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:

json
{
  "mcpServers": {
    "tellia": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://<mcp-server-url>/mcp",
        "--header",
        "x-api-key:tia_..."
      ]
    }
  }
}

Pick the right URL:

EnvironmentURL
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):

json
{
  "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:

json
{ "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 ​

SymptomLikely causeFix
πŸ”Œ menu empty after restartConfig file path / JSON syntax errorVerify ~/Library/Application Support/Claude/claude_desktop_config.json parses; check ~/Library/Logs/Claude/mcp.log
mcp-remote error 500Local MCP server not runningpnpm mcp from repo root
mcp-remote error 404 (frp HTML)Tunnel up but no local backendSame β€” start pnpm mcp
Internal server error on initNestJS 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 impersonateWrong key typeMint a super-admin key, or use the company-scoped key directly
recordIds do not belong to the impersonated user's companyCross-tenant write attemptedtellia_act_as into the right company first
Tool descriptions stale in chatClaude 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).