adding-external-mcp ยท git:20260820.8a8a851 ยท 2026-08-20 ยท sha256 936b3cfaafc17ee7

adding-external-mcp git:20260820.8a8a851A

Immutable. This exact content is served forever at /api/v1/blob/936b3cfaafc17ee7.

---
name: adding-external-mcp
description: >
  The authoritative reference for adding a NEW external MCP server to Tlamatini
  universal MCP client layer. Covers the full lifecycle: catalog import, transport
  selection, activation, runtime provisioning, diagnosis, verification, and
  troubleshooting. READ THIS BEFORE calling external_mcp_import, before editing
  external_mcps.json, or before activating a new server.
metadata:
  openclaw:
    emoji: "๐Ÿ”Œ"
  tlamatini:
    runtime: in-process
    requires_tools:
      - "external_mcp_import"
      - "external_mcp_set_active"
      - "external_mcp_status"
      - "external_mcp_doctor"
      - "external_mcp_wait"
      - "external_mcp_list_tools"
      - "external_mcp_call"
      - "external_mcp_reconnect"
      - "external_mcp_runtime_status"
      - "external_mcp_runtime_install"
      - "chat_agent_mcp_doctor"
    requires_mcps: []
    budget:
      max_iterations: 15
      max_seconds: 300
      max_tokens: 32000
    permissions:
      filesystem:
        read:
          - "Tlamatini/agent/external_mcps.json"
          - "Tlamatini/agent/external_mcp_manager.py"
          - "Tlamatini/agent/external_mcp_defaults.py"
          - "Tlamatini/agent/runtime_provisioner.py"
        write:
          - "Tlamatini/agent/external_mcps.json"
      shell: []
      network: allow
      db: deny
    inputs:
      - { name: server_key, type: string, required: true,
          description: "Unique catalog key for the server (kebab-case or snake_case)." }
      - { name: server_config, type: object, required: true,
          description: "The mcpServers JSON spec for the server (command/args/env/transport/url/headers)." }
      - { name: activate, type: boolean, required: false,
          description: "Whether to activate the server immediately after import (default: false)." }
      - { name: verify, type: boolean, required: false,
          description: "Whether to run external_mcp_doctor + external_mcp_wait + external_mcp_list_tools after activation (default: true)." }
    outputs:
      - { name: import_status, type: string, required: true,
          description: "Result of the import operation (imported/updated/already_exists/error)." }
      - { name: activation_status, type: string, required: true,
          description: "Result of the activation operation (activated/capped/failed/skipped)." }
      - { name: doctor_report, type: object, required: false,
          description: "The external_mcp_doctor diagnostic report if verify=true." }
      - { name: tools_discovered, type: array, required: false,
          description: "List of tool names exposed by the server if verify=true." }
    triggers:
      keywords:
        - "add external mcp"
        - "new external mcp"
        - "import mcp"
        - "add mcp server"
        - "external mcp"
        - "mcp catalog"
        - "activate mcp"
        - "mcp server"
        - "external_mcps.json"
        - "mcp transport"
        - "stdio mcp"
        - "http mcp"
        - "sse mcp"
        - "websocket mcp"
        - "npx mcp"
        - "uvx mcp"
        - "docker mcp"
      file_globs:
        - "Tlamatini/agent/external_mcps.json"
        - "Tlamatini/agent/external_mcp_manager.py"
        - "Tlamatini/agent/external_mcp_defaults.py"
        - "Tlamatini/agent/runtime_provisioner.py"
        - "**/.mcp.json"
        - "**/mcp*.json"
---

# Adding External MCP โ€” canonical reference

The full, ground-truth procedure for adding a NEW external MCP server to
Tlamatini universal MCP client layer. This skill makes Tlamatini
autonomously capable of adding, configuring, activating, and verifying any
external MCP server โ€” robustly and bullet-proof.

## What this skill does

Enables Tlamatini to add ANY external MCP server to her universal MCP client
layer โ€” the system that lets her use tools from arbitrary MCP servers
declared in a JSON catalog (external_mcps.json), with no code per server.

## Architecture overview

```
external_mcps.json (catalog) --> external_mcp_manager.py --> ext__<server>__<tool>
      |
      |-- _StdioMcpClient (local child)
      |-- _StreamableHttpMcpClient (HTTP)
      |-- _SseMcpClient (legacy SSE)
      |-- _WebSocketMcpClient (WS)
      |
      |-- external_mcp_defaults.py (code-owned defaults: memory, sequential-thinking)
      |-- runtime_provisioner.py (private npx/uvx/node provisioning)
```

**Key constants:** MAX_ACTIVE = 5 | _SUPPORTED_TRANSPORTS = {stdio, streamable-http, sse, websocket}

## Procedure โ€” adding a new external MCP server

### Step 1 โ€” Classify the server transport

Determine which transport the MCP server uses:

| Transport | When to use | Config key |
|---|---|---|
| stdio | Local child process (npx, uvx, docker, python) | command + args |
| streamable-http | HTTP endpoint (modern MCP servers) | url |
| sse | Legacy Server-Sent Events endpoint | url |
| websocket | WebSocket endpoint | url |

If the server provides a .mcp.json or equivalent config, copy it directly โ€”
the catalog uses the same mcpServers shape as Claude Code.

### Step 2 โ€” Build the server config

The server config is a JSON object with these fields:

```json
{
  "command": "npx",
  "args": ["-y", "@some/mcp-server"],
  "env": { "API_KEY": "your-key-here" },
  "transport": "stdio",
  "description": "Optional human-readable description"
}
```

For network transports:

```json
{
  "url": "https://mcp-server.example.com/mcp",
  "transport": "streamable-http",
  "headers": { "Authorization": "Bearer your-token" },
  "description": "Remote MCP server"
}
```

### Step 3 โ€” Import the server into the catalog

Call external_mcp_import with the server config:

```
external_mcp_import(servers_json={"mcpServers": {"my-server": <config>}})
```

Or pass a JSON string. The server is ADDED to the catalog but NOT activated.
If the key already exists, it is UPDATED (not duplicated).

### Step 4 โ€” (Optional) Diagnose before activating

Call external_mcp_doctor(server_key="my-server") to run a static triage:
- Detects transport type
- Checks if command is on PATH
- Identifies placeholder secrets
- Reports blockers and next steps

Alternatively, use chat_agent_mcp_doctor for the canvas-agent version.

### Step 5 โ€” Activate the server

Call external_mcp_set_active(server_keys=["my-server"]) or pass a
comma-separated string. This:
- Caps at MAX_ACTIVE=5 (silently drops excess, reports capped: true)
- Spawns the child process (stdio) or opens the network connection
- Performs the MCP initialize handshake -> tools/list
- Wraps each remote tool as ext__<server>__<tool>

### Step 6 โ€” Wait for the server to be ready

Call external_mcp_wait(server_key="my-server", timeout_seconds=120) to
BLOCK until the server is connected and exposing tools. This is essential
for:
- First-run Docker image pulls (can take minutes)
- Cold npx/uvx downloads
- Slow network servers

### Step 7 โ€” Verify the server

Call external_mcp_status() to confirm the server shows status: ready and
tool_count > 0. Then call external_mcp_list_tools(server_key="my-server")
to enumerate the exposed tools.

### Step 8 โ€” Test a tool call

Call external_mcp_call(server_key="my-server", tool_name="<tool>",
arguments={...}) to test one tool directly. Or, in a Multi-Turn run, call
the bound ext__my-server__<tool> tool directly.

## Runtime provisioning (zero-config)

Tlamatini automatically provisions the package managers an MCP server needs:
- npx/npm/node โ€” downloaded into Tlamatini private per-user runtime
- uv/uvx โ€” same private provisioning
- pnpm โ€” same

No administrator rights, no system PATH change. Check with
external_mcp_runtime_status(). Install manually with
external_mcp_runtime_install(tools=["npx"]).

## Shipped defaults (do NOT re-add)

Two servers ship with every installation, INACTIVE by design:
- memory โ€” persistent knowledge graph (9 tools)
- sequential-thinking โ€” structured reasoning (1 tool)

If a user deleted one, it stays deleted (tombstone). Re-importing explicitly
clears the tombstone.

## Common pitfalls

- **MAX_ACTIVE=5**: the 6th server is silently dropped. Deactivate one first.
- **Secrets in env**: external_mcps.json holds real secrets. Never commit
  it. Run regen_secrets.py --mode push-able before pushing.
- **Transport mismatch**: a stdio server needs command+args; a network
  server needs url. Mixing them fails at connect time.
- **npx on Windows**: Tlamatini rewrites npx.cmd to node.exe <npx-cli.js>
  automatically โ€” no shell needed.
- **Docker MCP**: docker run -i --rm mcp/redis works but requires Docker
  Desktop running.
- **Zero tools after connect**: the server connected but exposed 0 tools.
  The system auto-relists it. Call external_mcp_reconnect to force a retry.
- **Cooldown**: a failed server enters a 60s negative cache. Wait or call
  external_mcp_reconnect to force-retry immediately.

## LLM Reflection connection

This skill was created as part of a research task on **LLM Reflection** โ€” the
technique where language models evaluate and improve their own outputs through
iterative self-correction. Tlamatini self-healing layer (agent/self_healing.py)
is itself an implementation of LLM Reflection: it retries failed model calls
with different tactics, narrates recovery live, and never hangs or discards
work. See references/llm_reflection_research.md for the full research findings.

## References

- references/llm_reflection_research.md โ€” LLM Reflection research findings
- references/external_mcp_catalog_format.md โ€” detailed catalog format guide
- references/transport_guide.md โ€” transport configuration reference
- references/troubleshooting.md โ€” troubleshooting and diagnostics

## Output

```json
{
  "import_status": "imported|updated|already_exists|error",
  "activation_status": "activated|capped|failed|skipped",
  "doctor_report": {},
  "tools_discovered": []
}
```