touchdesigner-manual

touchdesigner-manual

MCP server that enables AI agents to search the entire TouchDesigner wiki documentation with real citations, using a local index built from the official wiki.

Category
Visit Server

README

touchdesigner-wiki-rag

Search the entire TouchDesigner documentation from your AI agent — with real citations.

This tool builds a local search index over the official TouchDesigner wiki (docs.derivative.ca, ~2,270 articles) and exposes it to AI agents over MCP (Claude Code, Claude Desktop, Cursor, and any other MCP client). Every answer carries a Page § Section citation with a clickable URL, so you can verify what the agent tells you instead of trusting a model's memory of TouchDesigner — which is exactly how you end up with hallucinated parameter names.

You build the index yourself, on your machine, from the live wiki. This repo ships no documentation content — the docs belong to Derivative and are fetched by each user directly from docs.derivative.ca. The build takes ~45 minutes of unattended fetching (politely rate-limited) plus a few minutes of indexing, and can run entirely free with no API keys.

Why not just let the agent browse the wiki?

Three reasons this beats live browsing: hybrid retrieval (exact-term BM25 + semantic vectors, fused and reranked) finds sections a keyword search misses; the index knows TouchDesigner's operator-family trap — Noise TOP, Noise CHOP, Noise SOP, and Noise POP are four different operators, and results warn when same-named siblings exist in other families; and answers are grounded in retrieved text with citations rather than model memory.

Requirements

  • Python 3.12+ and uv
  • ~1.5 GB disk for the index
  • No API keys required for the default fully-local setup
  • Optional (better retrieval): an OpenAI key for stronger embeddings (about $1–2 one-time build cost) and HyDE query expansion; a Cohere key for stronger reranking (about $2 per 1,000 searches; free trial keys work)

Quickstart

git clone https://github.com/johnnyvincentvitale/touchdesigner-wiki-rag
cd touchdesigner-wiki-rag
uv sync
cp .env.example .env        # optional: add API keys; works fine empty

uv run python fetch.py      # ~45 min, fetches the wiki via its public API
uv run python ingest.py --rebuild   # chunks + embeds + indexes

# try it from the terminal
uv run python query.py "how do I add noise to a texture"

The embedding backend is chosen at build time — local bge-base (free, no account) by default, OpenAI text-embedding-3-large if OPENAI_API_KEY is set — and stamped into the index so queries always use the matching model. See .env.example for the details.

Already have the docs? Skip the fetch

TouchDesigner installs bundle an Offline Help mirror of the wiki. If you have it, import it instead of fetching (seconds instead of ~45 minutes):

# Windows (default install location):
uv run python fetch.py --offline-help "C:/Program Files/Derivative/TouchDesigner/Samples/Learn/OfflineHelp/https.docs.derivative.ca"

# then optionally pull only the pages edited since your mirror was generated:
uv run python fetch.py --update

uv run python ingest.py --rebuild

Notes: the mirror snapshots the wiki at your TouchDesigner release date — --update tops it up from the live API. Recent macOS builds ship the Offline Help folder empty (a known TouchDesigner issue), so Mac users should use the plain API fetch.

Configuration — what goes in .env

Nothing is required. With an empty (or absent) .env, everything runs on free local models. Keys only upgrade individual stages:

Variable What it enables Without it
OPENAI_API_KEY text-embedding-3-large embeddings (stronger dense retrieval) + HyDE query expansion local bge embeddings; HyDE disabled
COHERE_API_KEY Cohere Rerank scoring local ms-marco cross-encoder reranks
EMBED_BACKEND force local or openai embeddings explicitly inferred: openai if a key is set, else local
EMBED_MODEL different OpenAI embedding model (e.g. -3-small, cheaper/weaker) text-embedding-3-large
COHERE_RERANK_MODEL different Cohere rerank model rerank-v3.5
HYDE_MODEL different HyDE model gpt-4o-mini
OPENAI_BASE_URL route OpenAI-client calls to any compatible server (see below) api.openai.com

Two behaviors worth knowing: the embedding backend is stamped into the index at build time and queries auto-detect it, so you can't accidentally query with the wrong model — but switching backends means rebuilding (ingest.py --rebuild). And every API stage degrades visibly, never silently: no Cohere key falls back to the local reranker, an unreachable embedding API drops that search to keyword-only and says so in the response.

Going fully local (including HyDE)

The default keyless setup is already local except HyDE, which simply disables itself. To run HyDE on a local model, point the OpenAI client at any OpenAI-compatible server — Ollama or LM Studio:

# .env
OPENAI_API_KEY=anything-nonempty        # satisfies the client; never sent anywhere real
OPENAI_BASE_URL=http://localhost:11434/v1
HYDE_MODEL=llama3.2                     # any model you've pulled locally
EMBED_BACKEND=local                     # keeps embeddings on bge — required!

EMBED_BACKEND=local is load-bearing here: without it, setting OPENAI_API_KEY flips embeddings to the OpenAI backend, which would then be aimed at your local server expecting a model it doesn't serve. A small local HyDE model is rougher than gpt-4o-mini, but HyDE only fires on low-scoring searches and only keeps its result when it scores better — so the downside is bounded. (This recipe follows the OpenAI SDK's documented OPENAI_BASE_URL behavior but hasn't been exercised against a live Ollama by the author — issue reports welcome.)

"Local" models still download once from Hugging Face on first use (no account needed) and are cached after that; the wiki fetch itself needs the network once. After the index is built, the keyless setup searches fully offline.

Hook it up to your agent

Claude Code:

claude mcp add --scope user touchdesigner-manual -- uv run --directory /ABSOLUTE/PATH/TO/touchdesigner-wiki-rag python server.py

Any other MCP client — stdio server config:

{
  "mcpServers": {
    "touchdesigner-manual": {
      "command": "uv",
      "args": ["run", "--directory", "/ABSOLUTE/PATH/TO/touchdesigner-wiki-rag", "python", "server.py"]
    }
  }
}

What the agent gets

Tier Tool Returns
L0 browse_manual(query, family, limit) section map — cheap orientation, discovers the wiki's own vocabulary
L1 search_manual(query, family, limit) reranked passages with Page § Section + URL citations
L2 read_page(title, section) full page as markdown

Plus resources: manual://index (corpus stats and freshness) and manual://operators/{family} (operator roster per family).

family accepts TOP, CHOP, SOP, DAT, MAT, COMP, or POP to scope a search to one operator family.

How retrieval works

  1. BM25 over SQLite FTS5, Porter-stemmed — exact operator and parameter names
  2. Dense vector search over Chroma — paraphrased and conceptual questions
  3. Reciprocal Rank Fusion combines both rankings
  4. Rerank — Cohere Rerank if a key is configured, local ms-marco cross-encoder otherwise (automatic fallback, works offline)
  5. Adaptive HyDE — if the top rerank score is low (a reliable "retrieval missed" signal), an LLM writes a hypothetical answer in the wiki's vocabulary and retrieval re-runs on that. Fires only when needed, only with an OpenAI key, and only keeps the result if it scores better.

Two guardrails ship in every response: a family warning when a result's operator has same-named siblings in other families, and a low-confidence warning when scores suggest retrieval missed — so an agent reports "not found" instead of inventing an answer, and never concludes a feature doesn't exist just because retrieval came back empty.

Keeping the index fresh

The wiki changes continuously. Responses warn when pages have been edited since your index was built (checked against the wiki's recentchanges feed, cached hourly, skipped silently when offline). To update:

uv run python fetch.py --update     # re-fetches only pages edited since last fetch
uv run python ingest.py --rebuild   # rebuilds the index

Known issues

  • Every operator page carries an identical "Common Operator Info Channels" boilerplate section; those chunks can pollute results on hard queries.
  • The --offline-help importer is tested against synthetic MediaWiki static pages, not yet against a real TouchDesigner install's mirror (the author's macOS build ships it empty). If the import misses pages on your install, please open an issue with a sample HTML file.
  • Four title-variant pages (e.g. Palette:webRTC Ext vs Palette:WebRTC Ext) collide in the page cache on case-insensitive filesystems; their partner pages are indexed, so coverage impact is negligible.
  • Rerank/HyDE score thresholds were calibrated on a small held-out query set; they're adjustable in retrieval.py (THRESHOLDS).
  • ingest.py is full-rebuild-only; with OpenAI embeddings that re-costs ~$1–2 per rebuild. The local backend rebuilds for free.

Content ownership

All documentation content belongs to Derivative. This repository contains no wiki content — only code that fetches it from the public API into a private, local index, the same way a browser or TouchDesigner's built-in help fetches it. Please keep the polite rate limits in fetch.py intact.

License

MIT — see LICENSE. Applies to the code in this repository only, not to TouchDesigner or its documentation.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured