MCP Server¶
dartwork-mpl includes a built-in Model Context Protocol (MCP) server that lets AI coding assistants — such as Claude Code, Cursor, Windsurf, and any MCP-compatible client — access library documentation, style guides, and helper tools inside the chat context.
Quick setup¶
A typical install-and-wire-up takes under a minute. The flow is:
Install
dartwork-mplwith the[mcp]extra.Drop a small JSON config into your AI client.
Restart the client (or start a fresh chat).
1. Install the package with MCP extras¶
The [mcp] extra pulls in fastmcp (>=2.13.3,<4) and httpx. After install, the
console script dartwork-mpl-mcp is on your PATH.
# pip
pip install "dartwork-mpl[mcp]"
# uv (project-scoped)
uv add "dartwork-mpl[mcp]"
# uv pip (env-scoped)
uv pip install "dartwork-mpl[mcp]"
Confirm the entry point is wired up:
which dartwork-mpl-mcp
# → /…/site-packages/bin/dartwork-mpl-mcp (or similar)
2. Configure your AI client¶
Add to ~/.claude.json (global) or <project>/.claude/mcp_servers.json
(per-project; takes precedence for that workspace):
{
"mcpServers": {
"dartwork-mpl": {
"command": "dartwork-mpl-mcp"
}
}
}
That’s the entire config when dartwork-mpl-mcp is on PATH. If you want
to pin to a specific virtualenv, use the absolute path to the script:
{
"mcpServers": {
"dartwork-mpl": {
"command": "/abs/path/to/.venv/bin/dartwork-mpl-mcp"
}
}
}
Add to ~/.cursor/mcp.json (global) or <project>/.cursor/mcp.json
(per-project):
{
"mcpServers": {
"dartwork-mpl": {
"command": "dartwork-mpl-mcp"
}
}
}
Windsurf uses the same JSON shape as Cursor. Add to
~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"dartwork-mpl": {
"command": "dartwork-mpl-mcp"
}
}
}
Add to ~/.gemini/antigravity/mcp_config.json:
{
"mcpServers": {
"dartwork-mpl": {
"command": "dartwork-mpl-mcp",
"env": {}
}
}
}
If you are hacking on dartwork-mpl from a checkout instead of installing
from PyPI, run the entry point through uv run --directory:
{
"mcpServers": {
"dartwork-mpl": {
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/dartwork-mpl",
"--extra",
"mcp",
"dartwork-mpl-mcp"
]
}
}
}
--extra mcppulls infastmcp/httpxfrom the optional[mcp]dependency set. Without it,dartwork-mpl-mcpexits early with aModuleNotFoundError: fastmcpeven though the directory is correct.
This works for every client above — only the file location of the JSON changes.
Any client that speaks the MCP stdio transport can launch the server directly:
dartwork-mpl-mcp
# or, when working from a checkout:
uv run --directory /path/to/dartwork-mpl dartwork-mpl-mcp
# or via the module:
python -m dartwork_mpl.mcp.server
3. Restart the client¶
Most clients only re-read MCP config on startup. Quit and relaunch (or start a fresh chat) before running the verification steps below.
Verify the setup¶
Once configured, you should be able to confirm the server from inside your client and from the terminal.
Inside the client¶
Ask the assistant something only the server can answer, for example:
“List the MCP resources you can read from
dartwork-mpl.” → it should mentiondartwork-mpl://guide/agent-entry,…/policy, palette/style URIs, etc.“Use the
dartwork-mplMCP server to give me the hex code fordc.ocean2.” → triggersget_color_value.
If the assistant says it has no MCP server named dartwork-mpl, see Troubleshooting.
Claude Code specifics¶
Claude Code exposes connected MCP servers in its UI and in chat metadata. After a successful connection you should see dartwork-mpl listed as an available MCP server in the session header.
Cursor specifics¶
Cursor surfaces MCP servers under Settings → Cursor Settings → MCP. The entry should show a green “connected” indicator.
From the terminal (smoke test)¶
You can hand-roll an initialize JSON-RPC request to the server over stdio:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}}}' \
| dartwork-mpl-mcp
Expected response (key fields):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"resources": { "subscribe": false, "listChanged": false },
"tools": { "listChanged": true },
"prompts": { "listChanged": false }
},
"serverInfo": { "name": "dartwork-mpl", "version": "..." }
}
}
From Python¶
from dartwork_mpl.mcp.server import mcp
print(mcp.name) # → "dartwork-mpl"
print(mcp) # FastMCP instance info
First use¶
Now that the server is reachable, here are the highest-value calls to try first. Each one is a tiny smoke test that also doubles as a useful real-world action.
Pull the agent entry point. Ask the assistant to fetch the
dartwork-mpl://guide/agent-entryresource. This is the SSOT decision tree — once it is in context, the assistant will write standards-compliant code (dm.figsize(width, aspect),simple_layout, named colors, etc.) by default.Lint a code snippet. Paste a small matplotlib script and ask:
“Use the
lint_dartwork_mpl_codeMCP tool on this snippet.”You should get back a structured list of antipatterns (
figsize=,tight_layout(), raw hex colors, …) with suggested fixes.Resolve a color. Ask:
“What’s the hex for
tw.emerald500? Use theget_color_valueMCP tool.”The tool round-trips through the live palette registry — no guessing or hallucinated hex codes.
Generate a plot from a description. Try the
create_plotprompt:“Use the
create_plotMCP prompt: a tornado chart comparing energy savings across five buildings, Korean labels.”The prompt steers the assistant to read the relevant template, palette, and policy resources before emitting code.
If all four work, the integration is fully operational.
Troubleshooting¶
Symptom |
Likely cause |
Fix |
|---|---|---|
|
The |
Reinstall with the extra ( |
|
|
|
Server starts but client shows no resources / tools |
Client picked up an older config, or |
Restart the client. Double-check the absolute path. Inspect the client’s MCP log for connection errors. |
|
The unrelated |
Always invoke |
|
The bundled |
Reinstall the package; verify |
|
A breaking |
Pin |
Works in terminal but not in the client |
The client launches the command in a different shell / |
Use the absolute path to |
What can MCP do?¶
When the dartwork-mpl MCP server is connected, your AI assistant gains access to resources, tools, and prompts without you having to copy-paste documentation.
Resources¶
Read-only data that the AI assistant can retrieve on demand.
URI |
Description |
|---|---|
|
Agent entry point — decision tree + always-true facts (start here) |
|
Policy: width, aspect, layout, color, font, save |
|
Machine-readable lint catalog (the lint engine source) |
|
Intent → function-call cookbook (per plot type) |
|
Migration map — removed/renamed names and their replacements |
|
List of public dartwork-mpl callables (from |
|
Signature + first paragraph of docstring for a given public name |
|
Full list of registered colors with hex codes ( |
|
Sorted list of all fonts available to matplotlib |
|
Available mplstyle preset names |
|
Content of a specific mplstyle preset file |
|
Available plot template types |
|
Boilerplate Python script for a specific plot type |
|
Deprecated alias for |
|
Deprecated alias for |
Tools¶
Callable functions the AI assistant can invoke during a conversation.
Tool |
Description |
|---|---|
|
Fetch any raw file from GitHub (README, CHANGELOG, examples, etc.) |
|
Get the hex code for a dartwork-mpl or matplotlib color name |
|
Blend two colors and return the resulting hex code |
|
List color families ( |
|
Analyze Python code for dartwork-mpl best practices and antipatterns |
|
Same as above, returning structured JSON for programmatic consumption |
|
Apply safe identifier-level rewrites ( |
|
Rewrite 0.3-era source toward 0.4 idioms (safe substitutions + TODO hints) |
|
Rank the 18 bundled AI plot templates against a free-text intent |
|
Execute a bundled template in a subprocess and return the rendered PNG (base64 or path) for inline preview |
|
Validate whether a data structure matches a plot type’s requirements |
|
Execute a script in an isolated subprocess and return the |
|
Get a structured summary of all capabilities, presets, and templates |
Prompts¶
Interactive prompt templates that guide the AI through multi-step tasks.
Prompt |
Description |
|---|---|
|
Generate a complete dartwork-mpl script from a natural language description |
|
Review and fix a script for dartwork-mpl style compliance |
Practical use-cases¶
Here are specific examples of how an AI assistant behaves differently when the dartwork-mpl MCP server is connected:
Zero-shot accurate coding
You ask: “I need a bar chart for a Korean research paper.”
MCP in action: The assistant reads the
agent-entryresource and immediately outputs correct code callingdm.style.use('lang-kr')followed byplt.subplots(figsize=dm.figsize(...)).
Automated layout debugging
You ask: “I used simple_layout but my legend is overlapping the plot.”
MCP in action: The assistant reads the
policyresource, understands the library’s specific constraints, and provides the exact code to fix the issue.
Live color lookup
You ask: “What’s the hex code for dc.ocean2?”
MCP in action: The assistant calls
get_color_value("dc.ocean2")and returns the exact hex code — no guessing.
Code quality check
You ask: “Review my plotting script for dartwork-mpl best practices.”
MCP in action: The assistant uses the
lint_dartwork_mpl_codetool to check for antipatterns (e.g.,figsize=,tight_layout(),plt.subplots()) and suggests fixes.
Guided plot creation
You ask: “Create a tornado chart comparing energy savings.”
MCP in action: The assistant uses the
create_plotprompt with thetornadotemplate fromdartwork-mpl://templates/tornadoto generate a complete, standards-compliant script.
Data validation before plotting
You ask: “Plot this data as a heatmap.”
MCP in action: The assistant calls
validate_plot_data("heatmap", ...)to verify the data structure is correct before generating the plot code.