Skip to content

nats mcp tool kinds

Kadyapam edited this page Jun 2, 2026 · 1 revision

nats and mcp tool kinds

Added in noetl-tools 2.15.0 (nats) and 2.16.0 (mcp) — both are dispatched through the worker's existing dynamic ToolRegistry with no per-variant match arms in the worker code itself.

nats (2.15.0 / noetl/tools#12)

Bridges playbook steps to NATS JetStream, Key-Value store, and Object Store operations.

Playbook config shape

tool:
  kind: nats
  auth: my_nats_credential        # credential alias → { url, user?, password?, token? }
  operation: kv_get               # kv_get | kv_put | kv_delete | kv_keys | kv_purge |
                                  # object_get | object_put | object_delete | object_list |
                                  # object_info | js_publish | js_get_msg | js_stream_info
  bucket: my_bucket
  key: my_key

The credential alias is resolved via ctx.get_secret(alias) (keychain lookup) and must contain at minimum a url field. Inline url / user / password / token fields are also accepted directly in the config for simpler cases.

No subscriptions or pull operations — those would hold a worker slot while waiting for an external event, which violates the execution model (agents/rules/execution-model.md). Use JetStream push-to-subject patterns from a playbook-level callback step instead.

Return shape

{
  "status": "success",
  "operation": "kv_get",
  "bucket":    "my_bucket",
  "key":       "my_key",
  "value":     "stored-value"
}

Credential wiring

Set up via NOETL_KEYCHAIN_ENV_VARS (see worker credentials):

NOETL_KEYCHAIN_ENV_VARS=MY_NATS_CRED
MY_NATS_CRED='{"url":"nats://host:4222","user":"alice","password":"s3cret"}'

Playbook step:

tool:
  kind: nats
  auth: MY_NATS_CRED
  operation: kv_put
  bucket: session-cache
  key: "{{ execution_id }}"
  value: "{{ payload | tojson }}"

mcp (2.16.0 / noetl/tools#13)

Bridges playbook steps to MCP (Model Context Protocol) servers over JSON-RPC 2.0 + HTTP with optional SSE response parsing.

Playbook config shape

tool:
  kind: mcp
  endpoint: "http://localhost:8080/mcp"   # direct endpoint, OR
  server: kubernetes                       # key for NOETL_MCP_<SERVER>_ENDPOINT env var
  method: tools/call                       # tools/call | tools/list | health | <other>
  tool: get_pods                           # required for tools/call
  arguments:                               # required for tools/call
    namespace: default
  timeout: 30                              # seconds (default 60)

Endpoint resolution (priority order)

  1. config.endpoint (or config.url / config.server_url / config.base_url)
  2. NOETL_MCP_<SERVER>_ENDPOINT env var keyed by config.server slug
  3. NOETL_MCP_URL fallback env var

Return shape

{
  "status": "ok",
  "server": "kubernetes",
  "endpoint": "http://localhost:8080/mcp",
  "method": "tools/call",
  "tool": "get_pods",
  "arguments": { "namespace": "default" },
  "text": "...",
  "result": { ... }
}

On error: { "status": "error", "error": "<message>" }.

Session lifecycle

Each tool invocation POSTs an initialize request to get an Mcp-Session-Id header. Subsequent calls within the same invocation reuse that session id. Servers that omit the header are treated as stateless (no error).

Dispatch path in the worker

Both tool kinds follow the same worker dispatch path as all other kinds:

NATS pull → CommandExecutor::execute
  → ToolRegistry::execute_from_config(&ToolConfig { kind: "nats" | "mcp", ... })
  → NatsTool::execute | McpTool::execute
  → call.done event (inline / durable / shm fallback chain)

The tool_kind is the only discriminator. CommandExecutor carries no per-kind match arms — adding a new kind to noetl-tools and bumping the dep is the entire wiring.

Observability

noetl_worker_dispatch_duration_seconds{tool_kind="nats"} and {tool_kind="mcp"} appear in /metrics after the first dispatch of each kind. The histogram label is dynamic, so no metrics code changes are needed when new tool kinds land.

Related