---
description: "Use tdmcp from inside TouchDesigner via dotsimulate's LOPs MCP Client — point it at the hardened launcher and an in-TD agent can build and inspect your project."
---

# Use from TouchDesigner (LOPs)

dotsimulate's **LOPs "MCP Client"** runs *inside* TouchDesigner and can talk to
any MCP server. Point it at tdmcp and an agent living in your TD network can
build, wire, inspect and preview operators in that same project — closing the
loop **TD (LOPs MCP Client) → tdmcp server → the tdmcp bridge → your network.**

This is **not** an LLM-backend swap: LOPs brings its own model (OpenAI / Claude /
Ollama); tdmcp is the *tools* it calls, exactly like Claude or Cursor would.

## What you get

The LOPs client gets the **full tdmcp tool surface** — the build/inspect/preview
tools **plus** the knowledge-base tools (`get_td_classes`,
`get_td_class_details`, `get_module_help`, `search_operators`, `find_td_nodes`).
Those KB tools cover part of what dotsimulate's *dotContext* provides, so you
don't need a separate operator-reference layer alongside tdmcp.

When you connect through the recommended launcher (below), tdmcp starts in its
**`safe` profile** — the destructive tools are hidden so an autonomous in-TD
agent can't delete nodes or run unreviewed code by accident.

## Prerequisites

- The tdmcp **bridge is installed and running** inside the *same* TouchDesigner
  instance — see [install step 3, "turn on the bridge"](/guide/install#turn-on-the-bridge).
- **Node.js 20+ on your PATH** — LOPs spawns `node`.
- You have run **`npm run build`** in your tdmcp checkout, so `dist/index.js`
  exists.
- dotsimulate's **LOPs** is installed, with the MCP Client component.

## Connect (recommended: the launcher)

dotsimulate's `servers_config.json` documents `transport`, `command`, `args`,
`cwd` and `description` — but **no `env` field** — so we can't set tdmcp's
hardening variables through the config directly. tdmcp ships a tiny launcher,
`scripts/tdmcp-lops.mjs`, that sets them for you and then starts the server.
Point the LOPs client at it:

```json
{
  "mcpServers": {
    "tdmcp": {
      "transport": "stdio",
      "command": "node",
      "args": ["/abs/path/to/tdmcp/scripts/tdmcp-lops.mjs"],
      "cwd": "/abs/path/to/tdmcp",
      "description": "tdmcp — build & inspect this TouchDesigner project (hardened: safe profile)"
    }
  }
}
```

Replace `/abs/path/to/tdmcp` with the folder where you cloned tdmcp (run `pwd`
inside it). Use the **full absolute path** for both `command`/`args` and `cwd` —
LOPs resolves `cwd` differently than CLI clients, so don't rely on relative
paths. The `tdmcp-lops.mjs` launcher sets the `safe` profile for you.

## Alternative: an `env` block (if your LOPs build supports it)

dotsimulate's published schema does **not** document an `env` field, so the
launcher above is the safe default. If your LOPs build happens to pass an `env`
block through, you can instead point `args` straight at `dist/index.js` and set
the variables yourself:

```json
{
  "mcpServers": {
    "tdmcp": {
      "transport": "stdio",
      "command": "node",
      "args": ["/abs/path/to/tdmcp/dist/index.js"],
      "cwd": "/abs/path/to/tdmcp",
      "env": {
        "TDMCP_RAW_PYTHON": "off",
        "TDMCP_TOOL_PROFILE": "safe"
      },
      "description": "tdmcp — hardened for an in-TD agent"
    }
  }
}
```

If the `env` block is ignored (you'll see the destructive tools still listed),
fall back to the launcher.

## Hardening note

For an autonomous in-TD agent — no human reviewing each call — harden the
surface:

- **`TDMCP_RAW_PYTHON=off`** removes the two raw-Python tools
  (`execute_python_script`, `exec_node_method`) where the *client* authors the
  code. It is **not** a code-execution kill-switch: many higher-level tools still
  send their own *templated* Python to the bridge.
- **`TDMCP_TOOL_PROFILE=safe`** goes further and also hides destructive tools
  (node deletion, DAT rewrites, checkpoint/component/package writes, preview-asset
  writes, panic controls) — a strict superset of `RAW_PYTHON=off`. The launcher sets this for you. See
  [Environment variables](/reference/environment).
- Bridge-side arbitrary exec is now closed by default unless
  **`TDMCP_BRIDGE_TOKEN`** is configured or **`TDMCP_BRIDGE_ALLOW_EXEC=1`** is set
  in *TouchDesigner's* own environment. Keep it closed for autonomous LOPs use.

## How it works

Both the LOPs client and the tdmcp bridge live in the **same** TouchDesigner
process. The LOPs client spawns `node dist/index.js` (the tdmcp server) over
stdio; that server then talks HTTP to the bridge on `127.0.0.1:9980` — the very
same TD — which manipulates your network. No transport change is needed; stdio is
tdmcp's default. The spawned server is short-lived, tied to the MCP client's
lifecycle. See [Architecture](/reference/architecture#transports-events).

## This does NOT replace `tdmcp chat`

The [local LLM copilot](/guide/local-copilot) (`tdmcp chat`) is a *separate*
surface — tdmcp running its own local model. LOPs is a **client that consumes its
own model** (OpenAI / Claude / Ollama) and calls tdmcp's tools; it is not a
swap-in for the copilot's model backend. Use whichever fits your workflow.

## Troubleshooting

- **"node not found"** — LOPs couldn't find Node on its PATH. Install
  [Node.js 20+](https://nodejs.org) and make sure it's on the PATH the TD process
  inherits.
- **"dist/index.js not found"** — the launcher prints this to stderr when the
  build is missing. Run `npm run build` in your tdmcp folder.
- **"bridge not reachable"** — the tdmcp bridge isn't running in this TD, or it's
  on a different host/port. Re-check [install step 3](/guide/install#turn-on-the-bridge)
  and [Troubleshooting](/guide/troubleshooting).
