Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@CanvasXpress MCP ServerCreate a violin plot of gene expression by cell type using Tableau colors"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
CanvasXpress MCP Server
Natural language → CanvasXpress JSON configs, served over HTTP on port 8100.
Describe a chart in plain English and get back a ready-to-use CanvasXpress JSON config object. No CanvasXpress expertise required.
"Clustered heatmap with RdBu colors and dendrograms on both axes"
"Volcano plot with log2 fold change on x-axis and -log10 p-value on y-axis"
"Violin plot of gene expression by cell type, Tableau colors"
"Survival curve for two treatment groups"
"PCA scatter plot colored by Treatment with regression ellipses"How it works
Your description is matched against few-shot examples using semantic vector search (sqlite-vec)
The top 6 most relevant examples are included as context (RAG)
The full canvasxpress-LLM knowledge base is embedded in the system prompt (RULES, SCHEMA, DECISION-TREE, MINIMAL-PARAMETERS)
Claude generates a validated CanvasXpress JSON config
If headers are provided, all column references in the config are validated against them
The config is returned ready to pass to
new CanvasXpress()
Setup
1. Python environment
python3.11 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt2. Build the vector index (one-time)
python build_index.pyEmbeds all examples in data/few_shot_examples.json into data/embeddings.db.
Re-run whenever you update the examples file.
If you skip this step the server still works — it falls back to text similarity matching and logs a warning.
3. Set your Anthropic API key
export ANTHROPIC_API_KEY="sk-ant-..."4. Start the server
python src/server.pyServer starts at: http://localhost:8100/mcp
To run on a different port:
MCP_PORT=9000 python src/server.pyServer starts at: http://localhost:9000/mcp
Then point your test clients at the new port:
MCP_URL=http://localhost:9000/mcp python test_client.py
MCP_URL=http://localhost:9000/mcp perl test_client.pl
MCP_URL=http://localhost:9000/mcp node test_client.mjsDebug mode
To see the full reasoning trace for every request — retrieval results, prompt, token usage, raw LLM response, parsed config, and header validation:
CX_DEBUG=1 python src/server.pyEach request prints 6 steps to stderr:
── STEP 1 — RETRIEVAL ── query matched, 6 examples in 8ms
── STEP 2 — PROMPT ── system 4821 chars, user 2103 chars
── STEP 3 — LLM CALL ── 1243ms, 3847 input tokens, 89 output tokens
── STEP 4 — RAW RESPONSE {"graphType": "Violin", ...}
── STEP 5 — PARSED CONFIG graphType: Violin, keys: [...]
── STEP 6 — VALIDATION ── ✅ All column references validTest clients
Three test clients are included. Each accepts an optional description and either comma-separated headers or a JSON array of arrays (first row = column names).
All three clients accept the same arguments in any order after the description:
A comma-separated string → treated as column headers
A JSON array of arrays → treated as data (first row = headers)
A JSON object → treated as
column_typesmapping
Python
# Default — built-in sample data + types
python test_client.py
# Headers only
python test_client.py "Violin plot by cell type" "Gene,CellType,Expression"
# Headers + column types
python test_client.py "Scatter plot" "Gene,Expression,Treatment" '{"Gene":"string","Expression":"numeric","Treatment":"factor"}'
# Full data array
python test_client.py "Heatmap" '[["Gene","S1","S2","Treatment"],["BRCA1",1.2,3.4,"Control"]]'
# Data array + column types
python test_client.py "Heatmap" '[["Gene","S1","Treatment"],["BRCA1",1.2,"Control"]]' '{"Gene":"string","S1":"numeric","Treatment":"factor"}'Perl
# Default — built-in sample data + types
perl test_client.pl
# Headers only
perl test_client.pl "Volcano plot" "Gene,log2FC,pValue"
# Headers + column types
perl test_client.pl "Scatter plot" "Gene,Expression,Treatment" '{"Gene":"string","Expression":"numeric","Treatment":"factor"}'
# Full data array + types
perl test_client.pl "Heatmap" '[["Gene","S1","Treatment"],["BRCA1",1.2,"Control"]]' '{"Gene":"string","S1":"numeric","Treatment":"factor"}'Node.js
# Default — built-in sample data + types
node test_client.mjs
# Headers only
node test_client.mjs "Scatter plot by Treatment" "Gene,Sample1,Treatment"
# Headers + column types
node test_client.mjs "Scatter plot" "Gene,Expression,Treatment" '{"Gene":"string","Expression":"numeric","Treatment":"factor"}'
# Full data array + types
node test_client.mjs "Heatmap" '[["Gene","S1","Treatment"],["BRCA1",1.2,"Control"]]' '{"Gene":"string","S1":"numeric","Treatment":"factor"}'Response format
All clients return the same structure:
{
"config": {
"graphType": "Heatmap",
"xAxis": ["Gene"],
"samplesClustered": true,
"variablesClustered": true,
"colorScheme": "RdBu",
"heatmapIndicator": true
},
"valid": true,
"warnings": [],
"invalid_refs": {},
"headers_used": ["Gene", "Sample1", "Sample2", "Treatment"],
"types_used": {"Gene": "string", "Sample1": "numeric", "Sample2": "numeric", "Treatment": "factor"}
}Field | Description |
| The CanvasXpress JSON config — pass directly to |
|
|
| List of column validation warnings (empty if valid) |
| Map of config key → missing column names |
| The column names actually used for validation (extracted from |
| The |
Tools
Tool | Description |
| Main tool — plain English + headers → validated JSON config |
| All 70+ chart types organised by category |
| Explains any CanvasXpress config property |
| Required parameters for a given graph type |
generate_canvasxpress_config arguments
Argument | Type | Required | Description |
| string | ✅ | Plain English chart description |
| string[] | ❌ | Column names — e.g. |
| array[][] | ❌ | CSV-style array of arrays — first row must be column headers. Takes precedence over |
| object | ❌ | Map of column name → type. Valid types: |
| float | ❌ | LLM creativity 0–1 (default 0.0) |
Adding more few-shot examples
Edit data/few_shot_examples.json — each example needs a description and a config:
{
"id": 67,
"type": "Scatter2D",
"description": "Scatter plot with loess smooth fit and confidence bands",
"config": {
"graphType": "Scatter2D",
"xAxis": ["X"],
"yAxis": ["Y"],
"showLoessFit": true,
"showConfidenceIntervals": true
}
}Then rebuild the index:
python build_index.pyThe server scales to 3,000+ examples with no performance impact thanks to sqlite-vec semantic search (~10ms retrieval regardless of corpus size).
Configuration
Env var | Default | Description |
| — | Required. Your Anthropic API key |
|
| Host to bind to |
|
| Port to listen on |
|
| Set to |
|
| Sentence-transformers model for indexing |
Knowledge base
All prompt content sourced from neuhausi/canvasxpress-LLM:
File | Used for |
| Axis rules, decoration rules, sorting constraints |
| Full parameter definitions, types, options, defaults |
| Graph type selection logic |
| Required parameters per graph type |
Project structure
canvasxpress-mcp/
├── src/
│ └── server.py # FastMCP HTTP server
├── data/
│ ├── few_shot_examples.json # Few-shot examples (add more here)
│ └── embeddings.db # sqlite-vec index (built by build_index.py)
├── build_index.py # One-time vector index builder
├── test_client.py # Python test client
├── test_client.pl # Perl test client
├── test_client.mjs # Node.js test client (Node 18+)
├── requirements.txt
└── README.mdThis server cannot be installed
Resources
Looking for Admin?
Admins can modify the Dockerfile, update the server description, and track usage metrics. If you are the server author, to access the admin panel.