Skip to main content

MCP Server

CRAFT handles the “what” — governed, accurate data retrieval from your enterprise systems — so your AI tools and agents can focus on the “why”: validating hypotheses, identifying root causes, running what-if scenarios, and surfacing anomalies. Use resolve_term so your agent knows what “active customer” means in your warehouse before generating SQL; use execute_query to validate results; use generate_plotly_chart to surface patterns instantly. Connect Claude Code, Cursor, Goose, or a purpose-built agent to https://craft.emergence.ai/mcp and CRAFT becomes a governed data layer for any reasoning workflow. Two connection patterns: (a) interactive — IDE clients query CRAFT while you code; (b) programmatic — embed CRAFT as a tool server in an agent pipeline for hypothesis testing, root cause analysis, anomaly detection, or what-if modeling.

Server details

PropertyValue
Endpointhttps://craft.emergence.ai/mcp
TransportStreamable HTTP (MCP 2025-11-25 spec; SSE-compat path available)
AuthOAuth 2.0 PKCE (authorization code + S256, via Keycloak)
HealthGET https://craft.emergence.ai/health{"status": "ok"}

Verify the endpoint (no auth needed)

Before setting up OAuth, confirm the server is reachable with the no-auth hello_world tool:
curl -s -X POST https://craft.emergence.ai/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"hello_world","arguments":{}}}' \
| jq .
Expected response:
{"jsonrpc": "2.0", "id": 1, "result": {"content": [{"type": "text", "text": "Hello from CRAFT MCP server"}]}}
If this succeeds, network connectivity and DNS are confirmed. If you prefer a CLI tool:
npx @mcpjam/cli server doctor --url https://craft.emergence.ai/mcp

Authentication

Interactive clients (OAuth)

Supported IDE clients use the MCP OAuth 2.0 PKCE authorization flow. On first connection, the client opens a browser window to craft.emergence.ai, where you sign in with your Google or Microsoft account. The access token is stored and refreshed by the client automatically — no manual token handling required.

X-Project-ID header

All tools except hello_world require an X-Project-ID header scoping the request to your CRAFT project. Find your project ID in the CRAFT console under Settings → Project → ID. X-Project-ID selects a project scope but does not grant access — project membership is enforced server-side against your JWT’s claims. Passing an arbitrary project ID returns an authorization error if you are not a member.

Token requirements for headless callers

Programmatic callers (agents, pipelines) must obtain an access token before calling tools:
RequirementValue
Issuer (iss)https://craft.emergence.ai/keycloak/realms/emergence
Required scopesopenid profile email
Grant typeAuthorization code (interactive) or Client credentials (service account)
Token TTL~5 minutes; refresh token manages rotation for interactive clients
For service accounts and CI pipelines, see Service Accounts and Authentication.

Connect your AI client

Add the CRAFT MCP server from the CLI:
claude mcp add --transport http craft https://craft.emergence.ai/mcp \
  --header "X-Project-ID: <your-project-id>"
Or add it to .mcp.json in your project root (or ~/.claude.json for user-scope):
{
  "mcpServers": {
    "craft": {
      "type": "http",
      "url": "https://craft.emergence.ai/mcp",
      "headers": {
        "X-Project-ID": "<your-project-id>"
      }
    }
  }
}
The OAuth browser flow triggers automatically on first tool call. Token refresh is handled by Claude Code.
Find your project ID in the CRAFT console under Settings → Project → ID.
Add to .cursor/mcp.json in your project (or ~/.cursor/mcp.json globally):
{
  "mcpServers": {
    "craft": {
      "type": "http",
      "url": "https://craft.emergence.ai/mcp",
      "headers": {
        "X-Project-ID": "${env:CRAFT_PROJECT_ID}"
      }
    }
  }
}
Set CRAFT_PROJECT_ID as a shell environment variable — Cursor expands ${env:VAR} at runtime. The OAuth browser window opens on first use.
Create .vscode/mcp.json in your project:
{
  "inputs": [
    {
      "type": "promptString",
      "id": "craft-project-id",
      "description": "Your CRAFT project ID"
    }
  ],
  "servers": {
    "craft": {
      "type": "http",
      "url": "https://craft.emergence.ai/mcp",
      "headers": {
        "X-Project-ID": "${input:craft-project-id}"
      }
    }
  }
}
VS Code prompts for the project ID once and stores it securely. OAuth handles the access token automatically.
If tool calls fail silently, headers may not be forwarded — a known issue in some VS Code versions (#264095). Workaround: replace the type/url block with mcp-remote:
{
  "servers": {
    "craft": {
      "command": "npx",
      "args": [
        "mcp-remote@latest",
        "https://craft.emergence.ai/mcp",
        "--header",
        "X-Project-ID: <your-project-id>"
      ]
    }
  }
}
Note: mcp-remote handles the OAuth flow locally rather than delegating it to the server.
Add to ~/.config/goose/config.yaml:
extensions:
  craft:
    name: craft
    type: http
    url: https://craft.emergence.ai/mcp
    enabled: true
    headers:
      X-Project-ID: "${CRAFT_PROJECT_ID}"
Set CRAFT_PROJECT_ID in your environment. Alternatively, run goose configure, select Remote Extension (Streamable HTTP), and the interactive wizard will prompt you for the URL and any custom headers. OAuth triggers on first connection.

Interactive charts — MCP Apps extension

generate_plotly_chart returns both a raw plotly_json response (all clients) and an embedded interactive UI resource for clients that support the MCP Apps protocol. The embedded resource is a sandboxed iframe containing the full Plotly chart with a modebar — including an SVG download button — rendered inline alongside the chat without switching tabs. The interactive iframe is enabled by default (MCP_APPS_ENABLED=true). No client-side configuration is required; supported clients detect and render it automatically. Clients that support MCP Apps interactive chart rendering (verified 2026-05-28):
ClientMCP AppsNotes
Cursor 2.6+Desktop IDE; renders interactive Plotly iframe inline
VS Code Copilot Chat v1.109+Browser-rendered panel with modebar
GooseDesktop app; renders iframes inline
PostmanRenders in Postman canvas; good for dev/testing
MCPJamInspector UI; best for debugging chart output
Claude Code (CLI)Terminal — no browser context; receives raw plotly_json
Claude Code and other non-Apps clients receive the raw plotly_json response. Render it locally with plotly.io.show(fig) in Python or Plotly.newPlot(...) in JavaScript. To disable the embedded resource globally, set MCP_APPS_ENABLED=false on the Talk2Data service.

Developer tools

Use these tools to test and debug CRAFT’s MCP server during development, especially the MCP Apps / Plotly rendering path.
MCPJam is a dedicated MCP inspector — web app (no install), desktop app, or CLI. It supports the MCP Apps extension and renders interactive Plotly charts inline.Web app or desktop: Add a server with URL https://craft.emergence.ai/mcp, enable OAuth, and set X-Project-ID in the headers field:
{
  "name": "craft",
  "type": "http",
  "url": "https://craft.emergence.ai/mcp",
  "headers": { "X-Project-ID": "<your-project-id>" },
  "useOAuth": true
}
CLI: Run a health check and OAuth flow validation:
npx @mcpjam/cli server doctor \
  --url https://craft.emergence.ai/mcp \
  --header "X-Project-ID: <your-project-id>"
MCPJam provides full JSON-RPC trace visibility and guided OAuth conformance checks (DCR, PKCE, CIMD) — useful for validating the MCP server before shipping tool changes.
Postman can act as an MCP host (client), connecting to external MCP servers — distinct from Postman’s own MCP server for managing Postman resources.Go to Settings → MCP Hosts → Add and configure:
  • URL: https://craft.emergence.ai/mcp
  • Auth: OAuth (recommended) or access token
  • Headers: X-Project-ID: <your-project-id>
Postman supports the MCP Apps extension — Plotly charts appear inline in the Postman canvas. Once you have a working configuration, use Postman’s Export MCP config button to generate a ready-to-paste config for Claude Code, Cursor, or VS Code.

Calling CRAFT from an external agent

Any MCP-compatible agent framework can use CRAFT as a tool server, bringing governed data access to any reasoning pipeline.
Requires pydantic-ai-slim[fastmcp] and fastmcp:
from fastmcp import Client
from fastmcp.client.transports import StreamableHttpTransport
from pydantic_ai import Agent
from pydantic_ai.toolsets.fastmcp import FastMCPToolset

transport = StreamableHttpTransport(
    url="https://craft.emergence.ai/mcp",
    headers={
        "Authorization": "Bearer <token>",
        "X-Project-ID": "<your-project-id>",
    },
)
toolset = FastMCPToolset(Client(transport))
agent = Agent("anthropic:claude-opus-4-8", toolsets=[toolset])

async def main():
    result = await agent.run(
        "What databases are available? Generate SQL to count active customers."
    )
    print(result.output)
MCPServerHTTP is deprecated — use FastMCPToolset with StreamableHttpTransport.
Headless callers need a programmatic access token. Obtain one via a Keycloak service account (client credentials grant). See Service Accounts for setup.

Available tools

Catalog tools

Always available — provide governed access to your project’s data catalog.
ToolRequired parametersReturns
hello_worldServer greeting; confirms connectivity (no auth required)
list_databasesresource_uri — data connection UUIDDatabase metadata list
get_schemaresource_uri, fqn — 2 segments = database, 3 = schema, 4 = tableFull entity schema including columns and types
search_schemaquery — Elasticsearch-style text queryMatching metadata entries across the project

Talk2Data tools

Available when the deployment includes the Data Insights solution. See Data Connections to connect your data sources.
ToolRequired parametersReturns
generate_sqlquestion (natural language), database (connection UUID), schema (object with schema_name)sql, explanation, assumptions
execute_querysql (SELECT statements only), databasecolumns, rows, row_count, truncated
resolve_termterm — business term (e.g., “ARR”, “churn rate”)definition, related_columns, sql_pattern
generate_plotly_chartdata (tabular), chart_type (bar, line, scatter, pie, …)Plotly JSON figure spec (plotly_json) + interactive iframe for MCP Apps clients
sample_dataresource_uri, table_fqndatabase.schema.tablecolumns, rows (up to 100 rows preview)
execute_query only accepts SELECT statements — DDL, DML, and admin functions are rejected. generate_sql delegates to the Text2SQL A2A agent; the first call in a session may take 3–8 s (cold start), subsequent calls ~1–2 s. generate_plotly_chart emits per-stage MCP progress notifications (parse → validate → render → verify) forwarded as A2A status events — visible in clients that display progress.

Per-project allowlist and governance

CRAFT enforces a per-project tool allowlist — each project defines which tools each agent identity may call. This is the key difference between the CRAFT MCP gateway and a raw FastMCP server. Configure allowlists in Platform → Authorization (RBAC model) and Platform → Agents (agent identity → allowlist mapping). Denied calls return a structured error:
{
  "ok": false,
  "error": {
    "code": "tool_not_allowed",
    "message": "Tool 'generate_sql' is not in the allowlist for this agent identity"
  }
}
Every tool call — allowed or denied — writes an audit event to the governance event log. Each event records:
  • Timestamp, agent identity, tool name, project ID
  • Input parameters (PII-scrubbed per governance policy)
  • Result status (allowed / denied / error)
Query audit events via Audit Log. Tool calls are tracked separately from LLM completions and do not flow through the LiteLLM gateway. See LLM Gateway for the complementary table.

Errors and limits

ConditionHTTPMCP error codeRemediation
Missing Authorization header401missing_authorizationComplete the OAuth flow; verify token is fresh
Missing X-Project-ID header400missing_projectAdd X-Project-ID header with your project UUID
Tool not in allowlist403tool_not_allowedAsk project admin to add tool to allowlist
Non-SELECT SQL in execute_query422validation_errorOnly SELECT statements are permitted
Text2SQL agent unavailable503upstream_unavailableRetry; generate_sql depends on the Talk2Data A2A agent
Query row limit hit200Response includes "truncated": true; add a LIMIT or more selective WHERE clause to fit within 500 rows
Limits:
  • execute_query: server-enforced cap of 500 rows; truncated: true in response when exceeded
  • sample_data: up to 100 rows (limit parameter; default 10)
  • generate_sql: first call may take 3–8 s (Text2SQL agent cold-start); subsequent calls ~1–2 s

Next steps

LLM Gateway

The complementary gateway for LLM completions — model allowlist, rate limits, and cost attribution.

Data Connections

Connect your data sources to enable Talk2Data tools.

Release Notes

Track new tools, breaking changes, and platform updates.