Use Plotwork with open and self-hosted models
How to run Plotwork's MCP tools with an open model, such as gpt-oss, Qwen, Gemma, or Llama, served by Ollama, LM Studio, vLLM, or llama.cpp, through an MCP client such as Goose, Cline, Continue, or the OpenAI Agents SDK. It is for anyone who wants diagrams drawn by a model that runs on their own hardware.
TL;DR
| Question | Answer |
|---|---|
| Does Plotwork work with open models? | Yes. The MCP server is the same for every model. The model needs tool calling and enough context. |
| What should I change first? | The context. Ollama runs most models at 4,096 tokens on a GPU with less than 24 GB, which is too small for any agent. Set 16,384 or more. |
| Which tools should I list? | The core profile: set PLOTWORK_TOOLS=core. It lists the eight workflow tools in about 1,700 tokens instead of about 17,500 for all eighteen. |
| Which model did best? | On 2026-10-20, gpt-oss-20b passed all four of our tasks with the core profile and gemma4:12b passed three, at a 16,384-token context. See Results. |
| Can I run it with no network at all? | Yes. Run the model locally and Plotwork from the npm package, or from the self-hosted image, which makes no outbound request. |
| Which hardware? | gpt-oss-20b runs on a 16 GB GPU. gpt-oss-120b needs about 80 GB of GPU memory, so serve it with vLLM on a data-center GPU or use a cloud provider. |
1. Serve the model
Every server below speaks the OpenAI Chat Completions API, which every MCP client in this guide can call. Pick a model that supports tool calling.
| Server | Endpoint | Context |
|---|---|---|
| Ollama | http://localhost:11434/v1 | 4,096 tokens by default on a GPU with less than 24 GB of memory (32,768 from 24 GB, 256k from 48 GB). The /v1 endpoint cannot change it per request, so set it on the server or in a Modelfile, below. |
| LM Studio 0.3.17 or later | http://localhost:1234/v1 | Set the context length when you load the model. |
| vLLM | http://<host>:8000/v1 | The model's own, limited by GPU memory. |
llama.cpp llama-server | http://localhost:<port>/v1 | -c 32768. Pass --port, because the default changed between releases. |
Raise Ollama's context for every model:
OLLAMA_CONTEXT_LENGTH=32768 ollama serveOr make a model with a larger context and call it by name:
FROM gpt-oss:20bPARAMETER num_ctx 32768ollama create gpt-oss-32k -f Modelfileollama ps # the CONTEXT column shows what a loaded model runs withServe gpt-oss with tool calling on vLLM:
vllm serve openai/gpt-oss-20b --tool-call-parser openai --enable-auto-tool-choice# gpt-oss-120b on one 80 GB GPUvllm serve openai/gpt-oss-120b --tool-call-parser openai --enable-auto-tool-choice --gpu-memory-utilization 0.95 --max-num-batched-tokens 1024Serve a GGUF model with tool calling on llama.cpp:
llama-server --jinja -hf bartowski/Qwen2.5-7B-Instruct-GGUF:Q4_K_M -c 32768 --port 80802. Choose the core profile
The server lists its tools to the client on every connection, and the client hands the list to the model before any work starts. All eighteen tools, with their descriptions and schemas, are about 36,600 characters as the model sees them (about 9,100 tokens), and the server instructions add about 5,100. A model with a 16,384-token context then has a few thousand tokens left for the task, the language reference, and the answers.
The core profile lists eight tools with short descriptions and short input schemas, about 6,900 characters with its instructions (about 1,700 tokens):
| Tool | What it does |
|---|---|
suggest_diagram | Ranks the kinds of diagram for a request and gives a starter that parses. |
get_diagram_syntax | Returns the language of one kind, with a tested example. |
draw_diagram | Checks the source and draws it, with every error's line, column, and hint. |
edit_diagram | Changes a diagram with typed operations. |
import_source | Builds a diagram from SQL, OpenAPI, Terraform, docker-compose, Kubernetes, and more. |
convert_mermaid | Converts one Mermaid diagram. |
sync_markdown | Draws every diagram fence of a Markdown document. |
map_icons | Finds the icons for many service names at once. |
The tools answer exactly as they do in the full profile; only what the list says about them changes. The pattern tools, plan_document_diagrams, and the single tools are left out, because one of these eight covers each of them.
| Set it | How |
|---|---|
| npm package | The environment variable PLOTWORK_TOOLS=core, or the argument --tools core. |
| Self-hosted image | PLOTWORK_TOOLS=core on the container. Any other value stops the start. |
Use core for a model with a context of 32,768 tokens or less, or one that picks the wrong tool from a long list. Use the full profile, the default, for a model with a large context that you want to use the patterns and single tools. PLOTWORK_TOOLS and --tools need a release of @buun_group/plotwork-mcp published after 2026-10-20. An older release ignores the variable and lists every tool, and refuses --tools, so the examples below set the variable.
3. Connect a client
Each snippet starts the npm package with npx. Status says whether we ran it ourselves on 2026-10-20 or checked it against the client's documentation only.
Goose
~/.config/goose/config.yaml:
GOOSE_PROVIDER: ollamaGOOSE_MODEL: gpt-oss:20bextensions: plotwork: type: stdio name: plotwork enabled: true cmd: npx args: ["-y", "@buun_group/plotwork-mcp@0.1.0-beta.10"] envs: PLOTWORK_TOOLS: core timeout: 300Set OLLAMA_HOST when Ollama runs on another machine. Status: checked against the Goose configuration docs (opens in a new tab), not run.
Cline and Roo Code
Open MCP Servers, then Configure MCP Servers, and add the server. Roo Code reads the same shape from .roo/mcp.json in a project, with alwaysAllow in place of autoApprove.
{ "mcpServers": { "plotwork": { "command": "npx", "args": [ "-y", "@buun_group/plotwork-mcp@0.1.0-beta.10" ], "env": { "PLOTWORK_TOOLS": "core" }, "disabled": false, "autoApprove": [] } }}In the settings, choose the API provider Ollama (http://localhost:11434) or LM Studio (http://localhost:1234), then the model. Status: checked against the Cline MCP docs (opens in a new tab), not run.
Continue
config.yaml. Continue runs MCP tools in agent mode only.
name: Localversion: 0.0.1schema: v1models: - name: gpt-oss provider: ollama model: gpt-oss:20b capabilities: - tool_usemcpServers: - name: plotwork type: stdio command: npx args: ["-y", "@buun_group/plotwork-mcp@0.1.0-beta.10"] env: PLOTWORK_TOOLS: coreStatus: checked against the Continue MCP docs (opens in a new tab), not run.
LM Studio
In the Program tab, choose Install, then Edit mcp.json:
{ "mcpServers": { "plotwork": { "command": "npx", "args": [ "-y", "@buun_group/plotwork-mcp@0.1.0-beta.10" ], "env": { "PLOTWORK_TOOLS": "core" } } }}Status: LM Studio's MCP docs (opens in a new tab) say the file follows Cursor's mcp.json; not run.
OpenAI Agents SDK
Python, with the model on Ollama and tracing off, so nothing is sent to OpenAI:
import asynciofrom agents import Agent, AsyncOpenAI, OpenAIChatCompletionsModel, Runner, set_tracing_disabledfrom agents.mcp import MCPServerStdio
set_tracing_disabled(True)model = OpenAIChatCompletionsModel(model="gpt-oss:20b", openai_client=AsyncOpenAI(base_url="http://localhost:11434/v1", api_key="ollama"))
async def main(): async with MCPServerStdio( name="plotwork", params={"command": "npx", "args": ["-y", "@buun_group/plotwork-mcp@0.1.0-beta.10"], "env": {"PLOTWORK_TOOLS": "core"}}, ) as server: agent = Agent(name="Diagrams", instructions="Draw diagrams with Plotwork.", model=model, mcp_servers=[server]) print((await Runner.run(agent, "Draw the sign-in sequence of a web app.")).final_output)
asyncio.run(main())Status: checked against the Agents SDK docs (opens in a new tab), not run.
Codex CLI
~/.codex/config.toml:
oss_provider = "ollama"
[mcp_servers.plotwork]command = "npx"args = ["-y", "@buun_group/plotwork-mcp@0.1.0-beta.10"]env = { PLOTWORK_TOOLS = "core" }startup_timeout_sec = 30codex exec --oss --local-provider ollama -m gpt-oss:20b "Draw the sign-in sequence of a web app and save it to signin.diagram"Status: run on 2026-10-20 with Codex CLI 0.154.0 and Ollama 0.30.6, and it did not work. Codex started the server and listed its tools, but it sends a server's tools to the model as one group, and Ollama passed that group to gpt-oss as a single function named plotwork with no parameters, so the model could call no Plotwork tool. The run also needs a context above Ollama's default: at 4,096 tokens, Codex's own prompt fills it. Use another client until Codex and Ollama agree on grouped tools.
A client of your own
An MCP client that bridges to an OpenAI-compatible model turns each listed tool into a function: the tool's name, its description, and its input schema as parameters. Every Plotwork input schema is an object with plain types, flat nullable unions, and short enums, with no $ref, oneOf, or allOf, which Ollama, llama.cpp, vLLM, and LM Studio all read. OpenAI's strict mode needs every object closed, so the tools that take an open map of keys (settings, a pattern's slots, an edit's options) must be sent with strict: false; in the core profile that is edit_diagram alone.
4. Run it fully offline
The npm package makes no network request by default, so a local model and npx already keep diagram text on your machine once the package is installed. For a team, run the self-hosted image next to the model server: one container with MCP over Streamable HTTP at /mcp, no outbound request, and no telemetry. Start it with PLOTWORK_TOOLS=core and point a client that speaks Streamable HTTP at http://<host>:3106/mcp with Authorization: Bearer <token>.
Results
We ran each model on four tasks through the stdio server on 2026-10-20: a sign-in sequence diagram saved to a file, a Mermaid flowchart converted, an AWS architecture with real AWS icons, and a Terraform snippet imported with import_source. A task passes when the saved file is valid, of the right kind, and meets the task's own check. Each cell is one run at temperature 0 with at most twelve model replies, on Ollama 0.30.6 and an RTX 5080 with 16 GB, at a 16,384-token context. Four tasks is a small sample: one run in either direction moves a model by a quarter, so read these as a guide, not a ranking.
| Model | Size on disk | Core profile | Full profile | Notes |
|---|---|---|---|---|
| gpt-oss:20b | 13 GB | 4 of 4 | 2 of 4 | Followed the hints to a valid diagram. With the full profile it once sent a tool call Ollama could not parse, and once saved source it had not checked. |
| gemma4:12b | 7.6 GB | 3 of 4 | 2 of 4 | Dropped a quote when it copied an imported diagram into the file. With the full profile it gave up on two tasks after repeated errors, without saving a file. |
| qwen3.5:9b | 6.6 GB | 3 of 4 | 1 of 4 | Escaped line breaks twice (\\n) in the AWS task until it ran out of turns. |
| qwen2.5-coder:14b | 9.0 GB | 0 of 4 | 0 of 4 | Writes tool calls as JSON in a code block, which Ollama does not read as a call. Use qwen2.5 or qwen3 instead. |
| llama3 (8B) | 4.7 GB | 0 of 4 | 0 of 4 | Ollama refuses tools for this model. |
| llama3.2:3b | 2.0 GB | 0 of 4 | 0 of 4 | Calls tools, but too often with the wrong arguments or as text. |
At Ollama's default 4,096-token context, gpt-oss:20b and gemma4:12b passed no task with either profile: the full tool list alone is longer than the context, so the model saw a cut prompt and made no call, and with the core profile the first answer from get_diagram_syntax filled what was left. At 32,768 tokens gpt-oss:20b passed 3 of 4 with the core profile and 2 of 4 with the full one.
What the runs changed: the parse errors these models made most now say what to write, each in one error (a Mermaid arrow such as -->>, a quote or line break escaped twice, a node type used as the statement, a second header line, a title line, an option on a line of its own, a group or actor with no label), and the core profile tells the model to save only source a tool has called valid. On the same tasks, the core profile went from 7 to 10 passes of 16 for the four models that call tools (gpt-oss, gemma, qwen3.5, and llama3.2, which passed none either time), and the full profile stayed at 5 of 16.
See also
| Doc | Why |
|---|---|
| Connecting an agent | Client settings for Claude Code, Cursor, VS Code, and Claude Desktop |
| MCP server | Every tool, and how the local and hosted servers differ |
| Self-hosting the engine | The container for running Plotwork inside your network |
| Writing with an agent | The loop a model follows to write, check, and draw a diagram |
| Tool reference | The full schema of every tool |