# Deployment How to ship `tdmcp` three ways: as a **Docker** container (HTTP transport), as a **Claude Desktop Extension** (`.mcpb`, stdio), and to **npm**. > **TouchDesigner is never containerized.** It always runs natively on the host > with its Web Server DAT bridge listening on `127.0.0.1:9980` (see the repo > `README.md` and `td/README.md` for the bridge setup). All deployment targets > below are just different ways to run the *MCP server*, which then talks to > that host-resident bridge over HTTP. --- ## 1. Docker / Docker Compose In a container the server **must** use the HTTP transport. The default `stdio` transport only works when the MCP client spawns the server as a local child process; it cannot cross the container boundary. The image therefore defaults to `TDMCP_TRANSPORT=http` on port `3939`, and reaches TouchDesigner on the host via `host.docker.internal`. ### Compose (recommended) ```bash docker compose up --build ``` This builds the `Dockerfile`, publishes `3939:3939`, and maps `host.docker.internal` to the host gateway so the container can reach the host-resident TouchDesigner bridge. Override the bridge location in the `environment:` block of `docker-compose.yml` if TD listens elsewhere. ### Plain Docker ```bash docker build -t tdmcp-server . docker run --rm -p 3939:3939 \ --add-host host.docker.internal:host-gateway \ -e TDMCP_TD_HOST=host.docker.internal \ -e TDMCP_TD_PORT=9980 \ tdmcp-server ``` The MCP HTTP endpoint is then available on `http://localhost:3939`. Point an HTTP-capable MCP client at it. > **host.docker.internal notes.** On Docker Desktop (macOS/Windows) this name > resolves automatically. On Linux you need the `--add-host` flag (plain Docker) > or the `extra_hosts` entry (Compose) shown above. If TouchDesigner runs on a > *different* machine, set `TDMCP_TD_HOST` to that machine's IP instead. --- ## 2. Claude Desktop Extension (`.mcpb`) Claude Desktop spawns the server locally, so the extension uses the **stdio** transport (no `TDMCP_TRANSPORT` override needed). TouchDesigner still runs on the same host; the extension exposes its host/port as user-configurable settings. > `.mcpb` (MCP Bundle) is the current Desktop-extension format; it was previously > called `.dxt`. Legacy `.dxt` bundles still install in Claude Desktop, but new > builds ship `.mcpb`. ### Build the bundle ```bash npm run build # populate dist/ first npm run build:mcpb # (or: node scripts/build-dxt.mjs) ``` `build-dxt.mjs` uses the official packer when available and otherwise falls back to a system `zip`. The packer was renamed from `@anthropic-ai/dxt` (CLI `dxt`, format `.dxt`) to `@anthropic-ai/mcpb` (CLI `mcpb`, format `.mcpb`); the script prefers `npx @anthropic-ai/mcpb pack` and falls back to the legacy `@anthropic-ai/dxt`, then `zip`. (The legacy `dxt` CLI predates manifest spec 0.3 and rejects the `manifest_version` key, so install `@anthropic-ai/mcpb` to use the official packer.) It writes `tdmcp.mcpb` to the repo root and prints install instructions. ### Install 1. Open Claude Desktop → **Settings → Extensions**. 2. **Install from file** (or drag in) `tdmcp.mcpb`. 3. Set **TouchDesigner host/port** if they differ from the defaults (`127.0.0.1` : `9980`), then enable the extension. The manifest lives at `dxt/manifest.json`. It declares a `node` server with `entry_point: dist/index.js` and surfaces `TDMCP_TD_HOST` / `TDMCP_TD_PORT` via `user_config`, injected into the server env as `${user_config.*}`. --- ## 3. Publish to npm The package is public and published as the scoped npm package `@dpantani/tdmcp`. The unscoped `tdmcp` name is blocked by npm's similarity policy, so releases must stay on the scoped package. ```bash npm run build npm publish --access public ``` ### Existing `package.json` release guards - `prepublishOnly` guarantees a fresh build and a passing test suite run before anything is published. - Scoped npm packages default to restricted access, so `publishConfig.access` and the manual command both keep the release public. - The GitHub tag-release workflow publishes the `.mcpb` GitHub Release asset but leaves npm manual by default. It only auto-publishes npm when repository variable `TDMCP_AUTO_NPM_PUBLISH=true` and `NPM_TOKEN` are both configured.