MCP Server
The MCP Server LOP runs a Model Context Protocol server directly inside TouchDesigner. External AI coding tools such as Claude Code, Cursor, Windsurf, and other MCP-compatible clients can connect to it and call tools that you define in a Python DAT. This makes TouchDesigner a live, tool-capable backend that AI agents can interact with in real time.
Agent Tool Integration
Section titled “Agent Tool Integration”This operator exposes 1 tool that allow Agent and Gemini Live LOPs to execute any tools defined in the user's MCP server code DAT, with schemas dynamically discovered at runtime.
Use the Tool Debugger operator to inspect exact tool definitions, schemas, and parameters.
When connected to an Agent LOP, the tools defined in the server code DAT are automatically discovered and exposed. The agent can call them just like any other LOP tool. Both synchronous and asynchronous tool functions are supported.
Key Features
Section titled “Key Features”- Streamable HTTP transport for direct connections from external MCP clients (no bridge proxy required)
- User-defined tools via Python DAT — write standard FastMCP tool definitions and the server handles the rest
- Auto port discovery — if the configured port is busy, the server automatically finds the next available one
- Server health monitoring with the Ensure Running parameter, safe to call from a Timer CHOP for persistent uptime
- Config presets — save and load different server configurations from MCP_Config, with built-in and custom presets
- One-click client setup — copy MCP config JSON or a Claude Code CLI command directly to your clipboard
Requirements
Section titled “Requirements”- Python dependencies: FastMCP, Pydantic, and aiohttp. Pulse Install Dependencies on the Install / Debug page to install them into the LOPs shared virtual environment.
- Windows: pywin32 is additionally required and installed automatically. If pywin32 registration fails, run TouchDesigner as Administrator and pulse Install Dependencies again.
Input/Output
Section titled “Input/Output”Inputs
Section titled “Inputs”None. The server operates independently. Tool definitions come from the Server Code DAT referenced on the MCP Server page.
Outputs
Section titled “Outputs”One output. When connected to an Agent LOP, the agent discovers tools from this server via GetTool() and can execute them through the internal LOPs tool system.
How It Works
Section titled “How It Works”The MCP Server loads a Python DAT containing standard FastMCP tool definitions. When you start the server, it:
- Checks that all dependencies are installed
- Loads the server code from the referenced DAT
- Finds an available port (auto-incrementing if the configured port is busy)
- Launches an HTTP server on the chosen host and port
- Pre-warms the tool cache so tools are immediately available to both external MCP clients and connected LOPs agents
External clients connect to http://<host>:<port>/mcp using the Streamable HTTP transport. The server handles the full MCP JSON-RPC protocol including initialize, tools/list, and tools/call.
Usage Examples
Section titled “Usage Examples”Starting a Server
Section titled “Starting a Server”- On the Install / Debug page, pulse Install Dependencies if this is your first time using the operator. Wait for the status to confirm all dependencies are installed.
- On the MCP Server page, confirm the Server Code DAT points to a DAT containing your FastMCP tool definitions.
- Set Transport to
streamable-httpand choose a Port (default is 18555). - Pulse Start Server. The Running indicator will turn on and the Status field will show the server address.
Connecting Claude Code
Section titled “Connecting Claude Code”- With the server running, pulse Copy Claude Code Config on the MCP Server page.
- Open a terminal where Claude Code is installed and paste the copied command. It will look like:
claude mcp add --transport http mcp_server1_TD http://127.0.0.1:18555/mcp
- Claude Code can now call any tools defined in your server code DAT.
Connecting Other MCP Clients
Section titled “Connecting Other MCP Clients”- Pulse Copy MCP Config to copy the JSON configuration block to your clipboard.
- Paste the block into your MCP client’s configuration file (e.g., Cursor’s
mcp.json, Windsurf’s settings, or any Streamable HTTP-compatible client).
Writing Server Code
Section titled “Writing Server Code”The server code DAT should contain a standard FastMCP server definition with a mcp instance. For example:
import fastmcp
mcp = fastmcp.FastMCP(name="My TD Server")
@mcp.tool()def get_scene_info() -> str: """Get information about the current TouchDesigner project.""" return f"Project: {project.name}, FPS: {project.cookRate}"
@mcp.tool()def set_background_color(r: float, g: float, b: float) -> str: """Set the background TOP color.""" bg = op('/project1/bg_top') bg.par.colorr = r bg.par.colorg = g bg.par.colorb = b return f"Background set to ({r}, {g}, {b})"The DAT has access to TouchDesigner globals (op, me, parent, project), so your tools can read and modify anything in the project.
Loading a Preset Server
Section titled “Loading a Preset Server”- On the Config page, select a server from the Current Server menu (options include
Basic,Glsl Tool,Any Script Op, and any custom servers you have saved). - Pulse Load Server. The server code DAT will be populated with the preset’s code.
- If Auto Start on Load is enabled, the server will start automatically after loading.
Saving a Custom Server
Section titled “Saving a Custom Server”- Write your tool definitions in the server code DAT.
- On the Config page, type a name into Current Server (it is a string menu, so you can type freely).
- Pulse Save Server. Your configuration is saved to MCP_Config and will appear in the menu for future use.
Persistent Server with Timer CHOP
Section titled “Persistent Server with Timer CHOP”To keep the server running reliably across long sessions:
- On the Config page, enable Start on File Load so the server starts automatically when the .toe opens.
- Connect a Timer CHOP to periodically pulse the Ensure Running parameter on the Server page. This will start the server if it is not running, or restart it if a health check fails.
Using with Agent LOPs
Section titled “Using with Agent LOPs”When the MCP Server output is wired into an Agent LOP’s tool input, the agent gains access to all tools defined in the server code. The tools appear alongside any other connected LOP tools. This is useful for giving an internal LOPs agent the same capabilities that external coding assistants have.
Troubleshooting
Section titled “Troubleshooting”Dependencies fail to install
Section titled “Dependencies fail to install”Pulse Check Dependencies on the Install / Debug page to see which packages are missing. Then pulse Install Dependencies again. If pywin32 fails on Windows, close TouchDesigner, reopen it as Administrator, and retry.
Port already in use
Section titled “Port already in use”The server automatically tries the next 10 ports if the configured one is busy. If all are taken, check for other processes using those ports and free one, or change the Port parameter to a different range.
Server starts but external client cannot connect
Section titled “Server starts but external client cannot connect”Verify the Host is set to 0.0.0.0 (accepts connections from any interface) rather than 127.0.0.1 (localhost only) if connecting from another machine. Check that your firewall allows inbound connections on the configured port.
”Dependencies not met” when starting
Section titled “”Dependencies not met” when starting”The server requires FastMCP, Pydantic, and aiohttp to be installed in the LOPs shared virtual environment. Go to Install / Debug and pulse Install Dependencies. The button will be disabled once all dependencies are satisfied.
Server code DAT missing ‘mcp’ instance
Section titled “Server code DAT missing ‘mcp’ instance”The server code must define a variable named mcp that is a fastmcp.FastMCP instance. If this variable is missing or named differently, the module loader will fail with an error in the logger.
Tools not appearing in agent
Section titled “Tools not appearing in agent”Confirm the server is running and that the MCP Server output is wired to the Agent LOP. Tools are discovered dynamically from the server’s tool cache. If the server was restarted, the tool cache is re-warmed automatically on startup.
Parameters
Section titled “Parameters”MCP Server
Section titled “MCP Server”op('mcp_server').par.Status Str - Default:
"" (Empty String)
op('mcp_server').par.Startserver Pulse - Default:
False
op('mcp_server').par.Stopserver Pulse - Default:
False
op('mcp_server').par.Restartserver Pulse - Default:
False
op('mcp_server').par.Running Toggle - Default:
False
op('mcp_server').par.Host Str - Default:
0.0.0.0
op('mcp_server').par.Port Int - Default:
18555- Range:
- 0 to 1
- Slider Range:
- 0 to 1
op('mcp_server').par.Serverdat DAT - Default:
./server_code
op('mcp_server').par.Editserverdat Pulse - Default:
False
op('mcp_server').par.Copyconfig Pulse - Default:
False
op('mcp_server').par.Copyclaudecodeconfig Pulse - Default:
False
Config
Section titled “Config”op('mcp_server').par.Loadserver Pulse - Default:
False
op('mcp_server').par.Autostart Toggle - Default:
True
op('mcp_server').par.Saveserver Pulse - Default:
False
op('mcp_server').par.Servername Str Optional custom name for config. If empty, uses operator name.
- Default:
"" (Empty String)
op('mcp_server').par.Startonload Toggle Automatically start server when .toe file is loaded
- Default:
False
Install / Debug
Section titled “Install / Debug”op('mcp_server').par.Status2 Str - Default:
"" (Empty String)
op('mcp_server').par.Installdeps Pulse - Default:
False
op('mcp_server').par.Checkdeps Pulse - Default:
False
Server
Section titled “Server”op('mcp_server').par.Ensurerunning Pulse Start server if not running, health-check if running. Safe to call from Timer CHOP.
- Default:
False
Changelog
Section titled “Changelog”v2.1.12026-03-16
- fix depdency check and pywin32 check
v2.1.02026-03-16
Initial release
v2.0.32026-03-16
- switch clipboard config to native HTTP transport (drop npx mcp-remote bridge) - update CLI copy command to use --transport http - add resources/list handler returning empty list - update MCP protocol version to 2025-11-25 - pin pydantic to ==2.11.7 for FastMCP compatibility
- Add Startonload toggle for auto-start on .toe file load - Add Ensurerunning pulse with healthcheck (task/adapter/TDAsyncIO validation) - Fix IsRunning.val bug — was comparing dependency object as bool - Add pydantic dependency requirement for FastMCP - Enable pywin32/pywintypes check on Windows - Add GetTool warning when server not running - Track was_running in storage for state persistence
- Add professional README with accurate description
- Initial commit
v2.0.22025-12-16
- Fixed MCP protocol compatibility issue with
annotations: nullin tool call responses - The MCP spec requires
annotationsto be an object or omitted entirely;nullis invalid - Tool call responses now strip out null annotation fields before returning to clients
- Resolves schema validation errors with mcp-remote and Claude Code clients
v2.0.12025-09-24
- Fixed Gemini API compatibility by removing unsupported schema fields
- Added tool schema cleaning for additionalProperties error
v2.0.02025-08-18
Major Features
- MCP Config Integration: Added centralized server configuration system with MCP_Config operator
- Load/Save Server UI: New Current Server dropdown, Load Server, and Save Server parameters for easy server management
- Auto-Start on Load: Intelligent server startup when loading new configurations (configurable)
- Connection Settings Management: Transport, host, and port settings now saved/loaded with server configs
- Built-in Server Protection: Prevents saving built-in servers to disk - they stay in TouchDesigner only
Server Management
- Smart Server Switching: Always stops current server when loading different server, prevents duplicate loads
- Port Conflict Detection: Warns users when configured ports are unavailable, falls back to stdio transport
- Docked Operator Management: Configurable removal of docked operators when loading servers (remove_docked setting)
- Server ID Normalization: User-friendly names automatically converted to valid server IDs
Built-in Server Enhancements
- Dynamic Config Tables: Auto-creates config/system_prompt DATs for new built-in servers
- Default Port Assignment: Built-in servers get appropriate default ports (18760 for GLSL, 18792 for Script Op)
- Basic Server Info DAT: Added helpful README DAT to basic server explaining usage and next steps
User Experience
- Improved Error Messages: Clear warnings for built-in server save attempts, port conflicts, and duplicate loads
- Delayed Port Warnings: 60-frame delayed warnings for port conflicts to ensure visibility
- Connection Setting Validation: Automatic port availability checking with user guidance
- File-First Architecture: Clean separation between built-in (TouchDesigner) and user (disk) servers
v1.1.12025-08-02
Critical Bug Fixes
- Fixed "No module named 'td_mcp_adapter'" error: Moved DAT module import from async context to main thread where it has proper execution context to find sibling DATs
- Fixed dependency detection issues: Replaced unreliable
__import__()checks withimportlib.metadata.version()for pip packages, ensuring consistent detection across different Python environments - Fixed sys.path conflicts: Implemented surgical venv path insertion that places LOPs venv before TouchDesigner's site-packages while respecting TD's core library paths, preventing conflicts with other Python environments (e.g., miniconda)
Technical Improvements
- Removed stale global import: Eliminated module-load-time
ADAPTER_AVAILABLEflag that could become stale after dependency installation - Enhanced dependency checking: Added
_is_adapter_available()method with explicit, self-contained dependency validation - Improved error handling: Better logging and error messages for dependency and import failures
- Safer path management: Replaced aggressive
index=0path insertion with intelligent placement before TD's site-packages
User Experience
- Eliminated need for TouchDesigner restarts: Dependency installation now works without requiring project reload
- Better cross-platform compatibility: Resolved Windows-specific import issues while maintaining macOS/Linux compatibility
- Fixed Windows dependency management: Restored pywin32 installation requirement while keeping reliable detection methods to prevent false positives
v1.1.02025-06-30
GetToolIntegration: The server now fully implements theGetToolmethod, allowing it to automatically discover and expose its user-defined tools to the TouchDesigner agent ecosystem (AgentEXT,geminilive, etc.). This enables seamless, zero-configuration tool usage by AI agents.- added a new parameter
Editserverdatto open the linked server dat file in the editor.
## Fixes
- Asynchronous Tool Discovery: Resolved a critical race condition where tools were not discoverable at startup. The server now pre-caches its tools, ensuring they are always available for synchronous inspection by agent systems.
- API Compliance: Corrected the tool schema to be fully compliant with OpenAI, Google, and
litellmstandards, fixing a series ofKeyErrorandBadRequestErrorexceptions. - Robust Tool Execution: The tool execution handler is now capable of calling both synchronous (
def) and asynchronous (async def) tool functions, preventingawaitexpression errors.