AI Agent API

MCP server

Etlworks tools are now available as MCP — connect Cursor, Claude Desktop, ChatGPT, or any MCP-compliant client and use Etlworks's AI tools natively from your IDE or chat app. Same tools as the REST Scripting API, same API key, same backend.

Endpoint at a glance

URL: https://<your-etlworks-host>/rest/v1/ai-agent/mcp
Transport: MCP Streamable HTTP (single path, POST for requests, GET405)
Auth: Authorization: Bearer YOUR_API_KEY — the same key as the REST Scripting API
Protocol versions: 2025-06-18, 2025-11-25, 2026-07-28 — the server is dual-era: it answers the legacy initialize handshake and the stateless per-request form introduced by 2026-07-28, on the same endpoint

What is MCP?

The Model Context Protocol (MCP) is an open standard from Anthropic for connecting AI applications to external tools and data. It's now supported by Cursor, Claude Desktop, ChatGPT desktop, MCP Inspector, and a growing list of other clients.

Etlworks speaks MCP natively. The MCP server is embedded inside the existing Etlworks backend — one deployable, no sidecar to run — and it exposes the same AgentTool registry that already powers in-app Simba and the REST Scripting API. It is one more way for external agents to talk to Etlworks AI tools, in addition to, not instead of, the REST API.

What you can do with it

The highest-impact tool: etlworks_assistant

Beyond the individual tools, the MCP server exposes one special tool — etlworks_assistant — that wraps Simba's full agent loop. Your client calls it with a natural-language message and Etlworks runs Simba end-to-end (RAG, multi-turn reasoning, internal tool calls) and returns the final answer. See the dedicated section below.

Prerequisites

Your endpoint URL

Throughout this guide, replace app.etlworks.com with your own host if you run a dedicated instance. The MCP endpoint is always your Etlworks base URL followed by /rest/v1/ai-agent/mcp.


Connect from Cursor

Cursor reads MCP servers from ~/.cursor/mcp.json (global) or .cursor/mcp.json in a project. Add Etlworks as a Streamable HTTP server:

~/.cursor/mcp.json
{
  "mcpServers": {
    "etlworks": {
      "url": "https://app.etlworks.com/rest/v1/ai-agent/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
  1. Save the config

    Add the block above to ~/.cursor/mcp.json. If the file already has an mcpServers object, add the etlworks entry alongside your existing servers.

  2. Restart Cursor

    Fully quit and reopen Cursor so it reloads the MCP configuration.

  3. Verify it connected

    Open Settings → MCP. The etlworks server should show a green “connected” status and list the available tools. Cursor calls tools/list to discover them.

Connect from Claude Desktop

Claude Desktop reads its config from ~/Library/Application Support/Claude/claude_desktop_config.json on macOS. There are two ways to connect, depending on your Claude Desktop version.

Native Streamable HTTP (newer versions)

claude_desktop_config.json
{
  "mcpServers": {
    "etlworks": {
      "url": "https://app.etlworks.com/rest/v1/ai-agent/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Via the mcp-remote bridge (older versions)

If your Claude Desktop build doesn't yet support remote Streamable HTTP servers directly, bridge to it with mcp-remote (runs over npx, no install needed):

claude_desktop_config.json
{
  "mcpServers": {
    "etlworks": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://app.etlworks.com/rest/v1/ai-agent/mcp",
        "--header",
        "Authorization: Bearer YOUR_API_KEY"
      ]
    }
  }
}

Restart Claude Desktop after saving. The Etlworks tools appear in the tools menu (the slider/hammer icon) in a new chat.

Connect from ChatGPT desktop (Mac)

ChatGPT desktop adds MCP servers through its GUI rather than a config file:

  1. Open connector settings

    Go to Settings → Connectors and choose Add MCP server (or “Add custom connector”, depending on your build).

  2. Enter the endpoint

    Set the server URL to https://app.etlworks.com/rest/v1/ai-agent/mcp and add an Authorization header with the value Bearer YOUR_API_KEY.

  3. Save and enable

    Save the connector and toggle it on. ChatGPT discovers the Etlworks tools via tools/list and makes them available in chat.

Try it with MCP Inspector

The MCP Inspector is the best tool for debugging a connection before you wire it into an IDE. It shows the raw protocol traffic and lets you call tools by hand.

Shell
# Launch the inspector (no install required)
npx @modelcontextprotocol/inspector
  1. Pick the transport

    In the Inspector UI, set the transport to Streamable HTTP.

  2. Enter the URL and header

    URL: https://app.etlworks.com/rest/v1/ai-agent/mcp. Add a header Authorization = Bearer YOUR_API_KEY.

  3. Connect and list tools

    Click Connect, then open the Tools tab and List Tools. You'll see the live tool set; select any tool to fill in arguments and call it.

What the wire looks like

Under the hood, a client on 2025-11-25 or earlier opens with an initialize request. Here's the same handshake with curl:

Shell
curl -s https://app.etlworks.com/rest/v1/ai-agent/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-06-18",
      "capabilities": {},
      "clientInfo": { "name": "curl", "version": "1.0" }
    }
  }'
JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-06-18",
    "capabilities": { "tools": { "listChanged": false } },
    "serverInfo": { "name": "etlworks-ai-agent", "version": "v2.0" }
  }
}

Protocol 2026-07-28 (stateless, no handshake)

The 2026-07-28 revision removed initialize and notifications/initialized from the spec. There is no connection to set up and no negotiated state to carry, so each request declares for itself which protocol version and client capabilities it is using, in a reserved _meta object under params. Servers implement server/discover in place of the handshake.

The Etlworks server treats a request as modern if and only if it carries params._meta["io.modelcontextprotocol/protocolVersion"]. Anything else is handled exactly as before, so existing clients are unaffected by the upgrade.

Shell
curl -s https://app.etlworks.com/rest/v1/ai-agent/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: server/discover" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "server/discover",
    "params": {
      "_meta": {
        "io.modelcontextprotocol/protocolVersion": "2026-07-28",
        "io.modelcontextprotocol/clientCapabilities": {}
      }
    }
  }'
JSON
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "supportedVersions": ["2025-06-18", "2025-11-25", "2026-07-28"],
    "capabilities": { "tools": { "listChanged": false } },
    "instructions": "Etlworks AI Agent tools. Use tools/list to discover what is available.",
    "ttlMs": 60000,
    "cacheScope": "public",
    "resultType": "complete",
    "_meta": {
      "io.modelcontextprotocol/serverInfo": {
        "name": "etlworks-ai-agent",
        "version": "v2.0"
      }
    }
  }
}

What the server enforces and returns on the modern path:

RuleDetail
Required _meta keysio.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities. A missing or non-object clientCapabilities is 400 + -32021.
Mirrored headersMcp-Method on every request, plus Mcp-Name on tools/call. Each must equal the corresponding value in the body; a missing or mismatched header is 400 + -32020. Send MCP-Protocol-Version too — the server validates it when present and rejects an unsupported value with 400 + -32022.
Unsupported version400 + -32022, with data.supported and data.requested in the error body so a client can see what to fall back to.
Every resultCarries resultType: "complete" — this server always completes synchronously — and serverInfo under the _meta key above.
Cache directivesserver/discover returns ttlMs: 60000 and cacheScope: "public". tools/list returns ttlMs: 60000 and cacheScope: "private", because the visible tool set depends on the caller's token.
Unknown methodHTTP 404 with a -32601 body. Legacy clients still get HTTP 200 with the same error code.

Available tools

List the live tool set with tools/list:

Shell
curl -s https://app.etlworks.com/rest/v1/ai-agent/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
JSON
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "search_knowledge_base",
        "description": "Search the knowledge base for articles, documentation, and support tickets.",
        "inputSchema": {
          "type": "object",
          "properties": { "query": { "type": "string" } },
          "required": ["query"]
        },
        "annotations": { "readOnlyHint": true }
      },
      {
        "name": "etlworks_assistant",
        "description": "Ask the Etlworks AI agent (Simba) a natural-language question. Runs the full agent loop and returns the final answer.",
        "inputSchema": {
          "type": "object",
          "properties": {
            "message": { "type": "string" },
            "session_id": { "type": "string" },
            "include_tools": { "type": "boolean" },
            "system_prompt": { "type": "string" }
          },
          "required": ["message"]
        }
      }
    ]
  }
}

There are 24 tools today — 23 from the agent registry plus the synthetic etlworks_assistant. The exact set evolves as the agent stack grows, so tools/list is the authoritative source; the table below is a snapshot, not an exhaustive list.

The server sets two MCP-standard hints on each tool so well-behaved clients (Cursor especially) can skip the confirmation prompt on safe tools:

ToolHintWhat it does
search_knowledge_baseRead-onlySearch KB articles, docs, and support tickets
search_templatesRead-onlySearch flow and connection templates
search_function_templatesRead-onlySearch transformation-function templates
host_list_commandsRead-onlyList available CLI commands
composer_search_block_typesRead-onlySearch Composer block types
metadata_search_resourcesRead-onlySearch resources (connections, formats, listeners…)
metadata_search_resource_typesRead-onlySearch available resource types
mapping_lookup_metadataRead-onlyLook up source/target metadata for mappings
mapping_get_editor_contextRead-onlyRead the current mapping editor context
public_web_researchRead-onlyResearch public API docs from the web
host_cliDestructiveRun an arbitrary CLI command on the Etlworks host
import_templateMay mutateImport a flow or connection template
etlworks_assistantMay mutateRun Simba's full agent loop (see below)
… and the remaining registry tools. Call tools/list for the complete, current set.

Tools without a hint are treated as “may mutate state” — a well-behaved client will prompt for confirmation before calling them. host_cli carries destructiveHint: true because it can run arbitrary commands; configure your MCP client to respect these hints.

The etlworks_assistant tool — full Simba in one call

Most tools do one thing. etlworks_assistant does everything: it wraps Simba's entire agent loop. Your client sends a single natural-language message, the Etlworks backend runs Simba end-to-end (RAG + multi-turn reasoning + internal tool calls), and returns the final answer. This is what lets a Cursor or Claude Desktop user simply say “ask Etlworks how to do X” and get a reasoned answer with no orchestration on their side.

Input fields

FieldTypeRequiredDescription
messagestringYesThe natural-language request for Simba
session_idstringNoReuse a prior session_id to continue a conversation
include_toolsbooleanNoLet Simba use its internal tools (default true)
system_promptstringNoOverride Simba's default system prompt

Call it

Shell
curl -s https://app.etlworks.com/rest/v1/ai-agent/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "etlworks_assistant",
      "arguments": {
        "message": "How do I create a REST API connection to load JSON data?"
      }
    }
  }'

The response text ends with a session_id: line. Capture it to continue the conversation:

JSON
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "To create a REST API connection that loads JSON data:\n\n1. Go to Connections and add a new HTTP connection...\n\nsession_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      }
    ],
    "isError": false
  }
}

Continue the conversation

Pass the session_id back on the next call and Simba keeps the context:

Shell
curl -s https://app.etlworks.com/rest/v1/ai-agent/mcp \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "tools/call",
    "params": {
      "name": "etlworks_assistant",
      "arguments": {
        "message": "Now schedule that flow to run every hour.",
        "session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
      }
    }
  }'
Billing — be aware which calls cost tokens

Direct tool calls via tools/call (for example search_knowledge_base or host_cli) run inside your Etlworks instance with no extra OpenAI token cost — the same model as the REST /tools/{name}/execute endpoint. Calls to the etlworks_assistant tool run the full Simba agent and are billed normally against your AI cap (or your own OpenAI key if BYOK is configured) — same rule as in-app Simba.


REST API vs MCP — which should I use?

Both are available simultaneously, on the same API key, exposing the same tools from the same backend. Pick by how you're working:

REST Scripting APIMCP server
Use whenYou're building a server-side integration, orchestrating from your own code, or already call HTTP endpoints in a workflow.You're in an IDE or desktop AI chat (Cursor, Claude, ChatGPT) and want Etlworks tools available natively.
Surface/rest/v1/ai-agent/api/… — one endpoint per operation/rest/v1/ai-agent/mcp — one JSON-RPC endpoint
ClientYour code, or the Python / Bash / PowerShell clientsAny MCP-compliant app — no Etlworks client library needed
ToolsSame registrySame registry
AuthBearer API keyBearer API key (the same one)

Not sure? If you're writing code, use the REST API. If you're driving Etlworks from an AI client, use MCP.


Authentication & security

Every MCP request authenticates with a Bearer token — the same Etlworks API key used by the REST Scripting API. Etlworks does not issue OAuth tokens, so there is no authorization flow to complete — the key is configured manually in the client.

HTTP
Authorization: Bearer YOUR_API_KEY

API-key management is identical to the REST API — most users generate their own under Preferences → Security → API key, and admins manage keys for any user under Settings → Users → select the user → Security → API key. The key inherits the generating user's role and tenant scope, so an MCP client can never do more than that user could.

Origin allowlist

For browser-based MCP clients, you can restrict which web origins may connect with the ai.mcp.allowed.origins property (comma-separated). Leaving it empty disables the Origin check (the default).

Locking down what MCP clients can do

Three operator-controlled properties on the Etlworks backend gate the most powerful tools. All default to true, so a fresh deploy exposes everything; set one to false and that tool disappears from tools/list and tools/call returns “Tool not found”:

Properties
ai.mcp.expose.host_cli=true         # gate the host_cli tool
ai.mcp.expose.import_template=true   # gate the import_template tool
ai.mcp.expose.assistant=true         # gate the etlworks_assistant synthetic tool
ai.mcp.allowed.origins=              # comma-separated allowlist; empty = no Origin check
Admin tip

To offer read-only research and template search to MCP clients but keep CLI execution and template imports out of reach, set ai.mcp.expose.host_cli=false and ai.mcp.expose.import_template=false. Those tools then never appear to any MCP client.

Stateless & replicated

The MCP server is stateless. It does not issue an Mcp-Session-Id, so it works behind a load balancer with multiple replicas — no session affinity required. (Conversation continuity for etlworks_assistant is carried by the session_id in the tool arguments, not by transport-level session state.) Each request stands on its own, authenticated by its Bearer token.

As of 2026-07-28 this is also what the protocol asks for. That revision removed sessions, the GET stream endpoint, and stream resumability from MCP outright, so a design that started as an implementation choice is now the specified behaviour. A session header sent by an older client is ignored.

Troubleshooting

SymptomLikely cause & fix
401 UnauthorizedMissing or wrong Bearer token. Check the Authorization header and that the key's user has API access enabled.
Connection refused / timeoutWrong host or port. Confirm the base URL and that the instance is reachable over HTTPS from your machine.
405 Method Not Allowed on a browser visitExpected — the endpoint answers GET with 405 and Allow: POST. MCP requests are POST. Protocol 2026-07-28 removed the GET stream endpoint, so 405 is the required behaviour.
A tool isn't in tools/listIts exposure flag is false. Check ai.mcp.expose.host_cli / ai.mcp.expose.import_template / ai.mcp.expose.assistant.
tools/call returns “Tool not found”Same cause — the tool is gated off by its exposure flag, or the name is misspelled. Discover exact names with tools/list.
Batch request rejected (-32600)JSON-RPC batching was removed in spec 2025-06-18. Send one request per call.

The error codes follow standard JSON-RPC: -32700 (parse error), -32600 (invalid request), -32601 (method not found), -32602 (invalid params), -32603 (internal error). Requests on protocol 2026-07-28 can also return the MCP-reserved codes -32020 (header mismatch), -32021 (missing client capability), and -32022 (unsupported protocol version).

What's not implemented

The Etlworks MCP server implements tools and tool-calling. The implemented JSON-RPC methods are server/discover, initialize, notifications/initialized, ping, tools/list, and tools/call.

Not built

These are in the spec and we haven't built them, so don't spend time looking for them: MCP resources, prompts, sampling, elicitation, subscriptions/listen, multi-round-trip input_required results, progress notifications, pagination cursors, and outputSchema / structuredContent. They may arrive later if there's demand — they're not broken, just not built yet.

Removed from the protocol

Three items used to be listed as gaps here and are no longer part of MCP at all: sessions, the server-initiated GET SSE stream, and stream resumability. The 2026-07-28 revision removed them from the spec, and over HTTP a client now cancels by closing the response stream rather than by sending a notification. Their absence here is the specified behaviour, not a deferred feature.

OAuth

Authentication is a static Authorization: Bearer Etlworks API key. Etlworks does not offer OAuth 2.1 discovery (RFC 9728 protected-resource metadata), which is why one-click web connectors that rely on OAuth auto-configuration cannot register themselves — configure the API key manually in the client, as the setup sections above show.


Next steps