opencode with mittwald AI Hosting
opencode is a command-line coding agent that supports
OpenAI-compatible providers through the @ai-sdk/openai-compatible adapter, so
mittwald AI Hosting needs no special handling.
Installation
opencode 2.x and 1.x are published as different npm packages:
# opencode 2.x
npm install -g @opencode/cli
# opencode 1.x
npm install -g opencode-ai
Both versions install the same opencode command, so they can't be installed side by side.
Remove a 1.x installation before you install 2.x.
Check the install:
opencode --version
Pointing opencode at mittwald AI Hosting
opencode reads configuration from either location:
- Global:
~/.config/opencode/opencode.json - Per project:
opencode.jsonin the project root
{
"$schema": "https://opencode.ai/config.json",
"model": "mittwald/Qwen3.8-27B-NVFP4",
"provider": {
"mittwald": {
"npm": "@ai-sdk/openai-compatible",
"name": "mittwald AI Hosting",
"options": {
"baseURL": "https://llm.aihosting.mittwald.de/v1",
"apiKey": "sk-..."
},
"models": {
"Qwen3.8-27B-NVFP4": {
"name": "Qwen3.8-27B-NVFP4",
"reasoning": true,
"tool_call": true,
"limit": { "context": 256000, "output": 32768 }
},
"Qwen3.6-35B-A3B-FP8": {
"name": "Qwen3.6-35B-A3B-FP8",
"reasoning": true,
"tool_call": true,
"limit": { "context": 256000, "output": 32768 }
},
"gpt-oss-120b": {
"name": "gpt-oss-120b",
"reasoning": true,
"tool_call": true,
"limit": { "context": 131072, "output": 32768 }
},
"GLM-OCR": {
"name": "GLM-OCR",
"tool_call": false,
"limit": { "context": 131072, "output": 4096 }
}
}
}
}
}
Replace sk-... with your AI Hosting API key. You create it in the AI-Hosting
section of your mStudio project — see
Gaining access. An mStudio API
token from your profile settings is a different credential and will not work here.
Verifying the connection
opencode run --auto "Create a file called hello.txt containing the word hello, then read it back."
Expected: opencode writes the file, reads it back, and reports the contents. Run this in
a scratch directory — the agent writes files where you start it. A plain question would
succeed even with tool_call missing, which is why the check writes a file.
Without --auto, you need to approve the file write before it happens. --auto
auto-approves permissions that are not explicitly denied. In opencode 2.x, --standalone
runs against a private server instead of the shared background service — useful if
opencode run produces no output (see troubleshooting below). opencode 1.x has
no background service and no --standalone flag.
Usage
# Explain unfamiliar code
opencode run "explain how session handling works in this project"
# Make a change
opencode run "add email validation to the registration form"
# Optimise
opencode run "optimize the database queries in user_service.py"
MCP servers
MCP servers are declared in the top-level mcp object. Each entry is one of two
shapes:
"type": "local"—commandis an array: the executable followed by its arguments.environmentis optional and sets environment variables for the server."type": "remote"—urlpoints at an MCP endpoint.
{
"mcp": {
"context7": {
"type": "remote",
"url": "https://mcp.context7.com/mcp",
"enabled": true
},
"fetch": {
"type": "local",
"command": ["uvx", "mcp-server-fetch"],
"enabled": true
},
"playwright": {
"type": "local",
"command": ["npx", "-y", "@playwright/mcp"],
"enabled": true
},
"sequential-thinking": {
"type": "local",
"command": [
"npx",
"-y",
"@modelcontextprotocol/server-sequential-thinking"
],
"enabled": true
},
"directus": {
"type": "local",
"command": ["npx", "-y", "@directus/content-mcp"],
"environment": {
"DIRECTUS_URL": "https://your-directus-instance.com",
"DIRECTUS_TOKEN": "your-directus-token"
},
"enabled": true
},
"opensearch": {
"type": "local",
"command": ["uvx", "opensearch-mcp-server-py"],
"environment": {
"OPENSEARCH_URL": "https://localhost:9200",
"OPENSEARCH_USERNAME": "your-opensearch-username",
"OPENSEARCH_PASSWORD": "your-opensearch-password"
},
"enabled": true
},
"typo3": {
"type": "local",
"command": [
"mw",
"app",
"exec",
"--quiet",
"--installation-id=a-XXXXX",
"vendor/bin/typo3",
"mcp:server"
],
"enabled": true
},
"mittwald": {
"type": "remote",
"url": "https://mcp.mittwald.de/mcp",
"enabled": true
}
}
}
For the mittwald server's authentication and token lifecycle, see MCP Integration. The TYPO3, Directus and OpenSearch servers authenticate through the environment variables shown above.
Plugins and skills
Plugins are listed in the plugin array:
{
"plugin": ["opencode-scheduler"]
}
Skills go in ~/.config/opencode/skills/, one directory per skill.
Agent packs add preconfigured subagents, each of which can point at its own model.
Routing subagents to Qwen3.6-35B-A3B-FP8 while the main agent stays on
Qwen3.8-27B-NVFP4 with thinking on (the model's default) keeps long sessions responsive,
since subagent work is mostly search and summarising.
Troubleshooting
opencode run produces no output and writes no file
opencode run is non-interactive, and depending on the build it may return nothing —
no output, no file, no error — rather than reporting what went wrong. In opencode 2.x,
--standalone runs the command against a private server instead of the shared background service,
which is worth trying if a run produces nothing; this is the documented purpose of the
flag, not a guarantee it resolves the issue for every installation. If opencode run
still doesn't confirm the connection, fall back to the interactive TUI (run opencode
with no subcommand) and send the same prompt there.
The agent answers but never edits a file or runs a command
The model is missing "tool_call": true in its models entry.
The agent keeps repeating the same tool call
The agent reads the same files again and again and never gets to an edit. By default opencode
doesn't stop such a loop, and every iteration counts against your token quota. Set a step limit
for each agent in opencode.json:
{
"agent": {
"build": { "steps": 30 },
"plan": { "steps": 30 }
}
}
steps is the maximum number of agentic iterations. When the agent reaches it, opencode asks the
model to summarise its work instead of making another tool call.
The limit ends a loop but doesn't prevent it. Loops happen mostly with thinking off. With
Qwen3.8-27B-NVFP4, switch thinking on for planning and tool work, see
Agent loops in non-thinking mode.
An MCP server never starts
Check the entry shape. A local server needs command as an array, not a string with
a separate args field — a string command with args is Claude Desktop's format,
and opencode ignores it silently rather than erroring.
If the server starts but fails to authenticate, check the name of the variables key. opencode
expects environment. It drops an env key without a warning, so the server starts without
its credentials.
npx reports a 404 for an MCP package
Verify the package name. The context7 server is published as
@upstash/context7-mcp — the similarly named @context7/mcp-server does not exist
on npm.
Next steps
- Hermes Agent — another CLI agent
- Pi — a third
- IDE Integration — agents inside an editor
- MCP Integration — manage mittwald infrastructure from the agent
- Agent skills — add workflow guidance
Disclaimer
Third-party tools, MCP servers and external links are provided for convenience without endorsement or warranty. Use them at your own risk, review licenses and privacy policies, and scope access conservatively (least privilege). Avoid sending sensitive data to external services unless required and permitted.