MCP Server
Connect Claude, ChatGPT, Claude Code, Cursor, or any MCP-compatible agent directly to your qlim8 carbon data — 31 curated tools, 3 resources, and 3 prompts, no custom integration code needed. See the full tools reference for per-tool input/output documentation, or the quickstart for the same content in markdown.
Connect your AI chat — no code required
Regular users connect by signing in with their qlim8 account (OAuth 2.1) — no API key, no config files. Two things to know first:
- A qlim8 tenant admin must approve the connection — the consent screen is admin-only. Access is read-only by default; the admin can opt in to write access.
- Connections can be revoked anytime from Collectors → API Keys in the qlim8 app.
Claude (claude.ai, Desktop & mobile)
Custom connectors are available on all Claude plans, including Free (Free is limited to one custom connector).
- Open Settings → Connectors and click Add custom connector.
- Name it
qlim8, pastehttps://app.qlim8.com/api/mcp, and leave the OAuth client fields in Advanced settings blank (the client self-registers via Dynamic Client Registration). - Click Add, then Connect — sign in to qlim8 and approve. On Team/Enterprise, an Owner first adds the connector under Organization Settings → Connectors, then each member connects.
ChatGPT
Custom MCP connectors ("apps") require Plus, Pro, Business, Enterprise, or Edu — not available on Free.
- Open Settings → Apps → Advanced settings and enable Developer mode.
- Back under Apps, add an app: name
qlim8, MCP server URLhttps://app.qlim8.com/api/mcp, authentication OAuth (leave client credentials blank). - Save and Connect — sign in to qlim8 and approve.
Gemini
Google's Gemini app does not yet support custom MCP connectors for regular users. Technical alternatives (Gemini CLI, Gemini Enterprise) can connect to this server; a guided setup will be added here once Google ships consumer support.
Endpoint & authentication
| Property | Value |
|---|---|
| Endpoint | https://app.qlim8.com/api/mcp |
| Transport | Streamable HTTP, stateless — every request is a self-contained POST (GET → 405, DELETE → 204) |
| Auth | OAuth 2.1 (Claude/ChatGPT connectors — Dynamic Client Registration, PKCE) or the same API keys as /api/v1 — Authorization: Bearer qk_live_<key> |
| OAuth discovery | /.well-known/oauth-protected-resource (RFC 9728) · /.well-known/oauth-authorization-server (RFC 8414) |
| Protocol version | Negotiated at initialize — 2024-11-05 and newer accepted |
Developer setup (API key)
- API key — mint one at Collectors → API Keys → Generate Key in the qlim8 app. Request only the scopes you need (each tool lists its required scope below). Keys look like
qk_live_<64-hex>/qk_sandbox_<64-hex>. - MCP-compatible client — Claude Code, Claude Desktop, Cursor, or any client that supports the Streamable HTTP transport.
Claude Code (CLI)
claude mcp add --transport http qlim8 https://app.qlim8.com/api/mcp \
--header "Authorization: Bearer qk_live_<your-64-hex-key>"
Claude Desktop
Claude Desktop also supports the no-code OAuth connector above (Settings → Connectors). For key-based setups, edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"qlim8": {
"type": "http",
"url": "https://app.qlim8.com/api/mcp",
"headers": {
"Authorization": "Bearer qk_live_<your-64-hex-key>"
}
}
}
}
Restart Claude Desktop — qlim8 will appear as an MCP server. You can now ask questions like "What were our total Scope 3 emissions in 2024?" and Claude will call the appropriate tool automatically.
Cursor
Add to your Cursor MCP server settings (Settings → MCP Servers):
{
"mcp": {
"servers": {
"qlim8": {
"url": "https://app.qlim8.com/api/mcp",
"headers": { "Authorization": "Bearer qk_live_<your-64-hex-key>" }
}
}
}
}
Manual (curl)
The transport is stateless: no session handshake and no mcp-session-id header — every request stands alone. Include Accept: application/json, text/event-stream; responses arrive as a single SSE-framed message.
# List the available tools
curl -N -X POST https://app.qlim8.com/api/mcp \
-H "Authorization: Bearer qk_live_<your-key>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
# Call a tool
curl -N -X POST https://app.qlim8.com/api/mcp \
-H "Authorization: Bearer qk_live_<your-key>" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "get_emissions_summary",
"arguments": {
"from": "2024-01-01T00:00:00Z",
"to": "2024-12-31T23:59:59Z",
"group_by": "month"
}
}
}'
# Response framing (Content-Type: text/event-stream, one frame per response):
# event: message
# data: {"jsonrpc":"2.0","result":{...},"id":2}
Spec-compliant clients still send an initialize request first — that works too and is equally stateless.
Discover the tool catalog
No auth required — returns the full JSON schema of all 31 tools (plus 3 resources and 3 prompts):
curl https://app.qlim8.com/api/mcp/schema
Layer 1 — Core tools
The most common use cases for agents and analysts. Full input/output docs per tool live in the tools reference; the same data is served live at /api/mcp/schema.
| Tool | Scope | Access | What it does |
|---|---|---|---|
get_emissions_summary | emissions:read | read | Total CO2e by scope — or a monthly series with group_by:"month" |
get_emissions_by_scope3_category | emissions:read | read | Scope 3 split across the 15 GHG Protocol categories (+ unclassified bucket) |
get_emissions_by_category | emissions:read | read | CO2e by calculation category, largest first (optional scope filter) |
list_emissions | emissions:read | read | Paginated emission entries (filter scope/from/to) |
get_emission_lineage | emissions:read | read | Full lineage + factor + audit hashes for one entry |
list_activities | activities:read | read | Paginated activities (invoices/transactions) |
list_reports | reports:read | read | Generated compliance reports (VSME, CSRD) |
get_report_status | reports:read | read | Poll a report render job |
generate_report | reports:generate | write (idempotent) | Queue a report render; poll with get_report_status |
list_data_sources | data_sources:read | read | Accounting connectors, sync status, pending counts |
get_quota_status | quota:read | read | Invoice quota: limit/used/available/period/tier |
list_emission_categories | factors:read | read | Category taxonomy (DA+EN, level, parent, scope, factor) |
Layer 2 — Strategic tools
| Tool | Scope | Access | What it does |
|---|---|---|---|
list_suppliers | suppliers:read | read · Enterprise | Scope 3 suppliers + disclosure status |
get_value_chain_coverage | suppliers:read | read · Enterprise | Disclosed-spend coverage % |
get_value_chain_exposure | suppliers:read | read · Enterprise | Suppliers by trade amount, largest first |
list_targets | targets:read | read | Reduction targets |
create_target | targets:write | write | Create a reduction target |
list_emission_factors | factors:read | read | Emission factor catalog (paginated) |
get_factor_citations | factors:read | read | Entries that used a factor + sample ids |
list_scenarios | scenarios:read | read · scenarioBuilder | Reduction scenarios visible to the key |
get_scenario | scenarios:read | read · scenarioBuilder | One scenario + its tiltag |
list_tiltag | scenarios:read | read · scenarioBuilder | A scenario's tiltag (+ cost annotations) |
create_scenario_draft | scenarios:write | write · scenarioBuilder | Create a scenario (draft when created by a consultant key) |
add_tiltag | scenarios:write | write · scenarioBuilder | Add a manual tiltag to a scenario |
submit_scenario_for_review | scenarios:write | write · scenarioBuilder | (Consultant keys) draft → pending_review |
list_pcf_records | factors:read | read | Approved product carbon footprints |
list_departments | tenant:read | read | Organisational units |
get_report_attestations | reports:read | read | Consultant sign-offs for a report |
Calling an Enterprise-gated tool on a lower plan returns a structured error in-band: a normal result with isError: true and "code": "subscription.feature_required". Branch on that code and prompt the user to upgrade.
Layer 3 — Infrastructure tools
| Tool | Scope | Access | What it does |
|---|---|---|---|
list_webhooks | webhooks:read | read | Webhook subscriptions |
create_webhook | webhooks:manage | write | Create a subscription; signing_secret shown once |
get_webhook_deliveries | webhooks:read | read | 100 most recent delivery attempts |
Available events: supplier.invited, supplier.connected, target.created, report.generation_started, report.generation_completed, report.attested, usage.quota_threshold, api_key.created, api_key.revoked. Deliveries are signed with X-Qlim8-Signature: t=<unix>,v1=<hex-hmac> — see the webhook signing guide for the exact verification scheme.
Resources & prompts
| Resource URI | Type | Contents |
|---|---|---|
qlim8://emission-categories | application/json | Live category taxonomy (DA+EN names, hierarchy, default scope, factor) |
qlim8://ghg-scopes | application/json | GHG Protocol scope 1/2/3 definitions as qlim8 applies them |
qlim8://usage-guide | text/markdown | Auth, scopes, pagination, date and error conventions |
| Prompt | Arguments | What it does |
|---|---|---|
emissions_vs_target_analysis | year | Actual emissions vs reduction targets — on-track verdict |
year_over_year_review | current_year, previous_year | YoY change and the biggest movers |
value_chain_briefing | year | Scope 3 coverage + largest exposure (Enterprise) |
Error model
Tool-execution errors are returned in-band — as a normal tools/call result with isError: true and a JSON body { code, title, detail } (e.g. auth.scope_required, subscription.feature_required, resource.not_found, request.validation_failed) so the model can read it and self-correct. A scope-denied result does not echo your granted scopes — call GET /api/v1/me to see them.
Only protocol-level problems use JSON-RPC error codes:
| JSON-RPC code | Meaning |
|---|---|
-32001 | Auth / rate error — missing or invalid Bearer token, revoked key, or rate limit exceeded |
-32603 | Internal server error |
HTTP 405 on GET /api/mcp | Expected — the stateless server has no server→client stream |
HTTP 204 on DELETE /api/mcp | Expected — there is no session to close |
Note: input-validation failures arrive in-band as request.validation_failed, not as a JSON-RPC -32602.
Rate limits
The MCP server shares rate-limit buckets with the REST API (/api/v1):
| Operation | Limit |
|---|---|
| Read operations | 600 requests / minute per API key |
| Write operations | 60 requests / minute per API key |
| Sandbox keys | 10× stricter on both buckets |
The read/write split is driven by each tool's readOnlyHint annotation. In addition, a pre-auth edge IP limit (default 300 req/min/IP, env V1_EDGE_RPM) sits in front of /api/mcp and returns a JSON-RPC -32001 with Retry-After before any key is checked.
Transport & statelessness
The server runs the Streamable HTTP transport in stateless mode: every POST is self-contained, handled by a fresh protocol instance, and torn down when the response closes. There are no sessions — no mcp-session-id header, nothing that can expire, and nothing to re-establish after a deploy or restart. A stale mcp-session-id header from an older client is simply ignored. GET /api/mcp returns 405 (no standalone server→client stream) and DELETE /api/mcp returns 204 (a no-op).
Client compatibility
| Client | Notes |
|---|---|
| Claude (claude.ai, Desktop, mobile) | No-code custom connector via OAuth — all plans, incl. Free |
| ChatGPT | Custom app via Developer mode + OAuth (Plus/Pro/Business/Enterprise/Edu) |
| Claude Code | claude mcp add --transport http qlim8 https://app.qlim8.com/api/mcp --header "Authorization: Bearer qk_live_…" |
| Cursor | Full support via MCP server config |
| Mistral Le Chat | OAuth or a static qk_ bearer token |
| Replit Agent | HTTP transport supported |
| Lovable | HTTP transport supported |
| Gemini | No consumer support yet — Gemini CLI / Gemini Enterprise only |
| Custom agents | Any client that speaks JSON-RPC 2.0 over HTTP (protocol version negotiated; 2024-11-05+) |