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
npm install -g opencode-ai
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.5-122B-A10B-FP8",
"provider": {
"mittwald": {
"npm": "@ai-sdk/openai-compatible",
"name": "mittwald AI Hosting",
"options": {
"baseURL": "https://llm.aihosting.mittwald.de/v1",
"apiKey": "sk-..."
},
"models": {
"Qwen3.5-122B-A10B-FP8": {
"name": "Qwen3.5-122B-A10B-FP8",
"reasoning": true,
"tool_call": true,
"limit": { "context": 245760, "output": 32768 }
},
"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. --standalone runs against a
private server instead of the shared background service — useful if opencode run
produces no output (see troubleshooting below).
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.envis optional."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"],
"env": {
"DIRECTUS_URL": "https://your-directus-instance.com",
"DIRECTUS_TOKEN": "your-directus-token"
},
"enabled": true
},
"opensearch": {
"type": "local",
"command": ["uvx", "opensearch-mcp-server-py"],
"env": {
"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.5-122B-A10B-FP8 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. --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.
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.
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.