Large Language ModelsGenerate imagesGenerate videos
OpenCode MCP Config: Add Servers, OAuth and Timeout Fixes
Wire MCP servers into OpenCode with the exact opencode.json fields for local and remote setups, see how OAuth sign-in works and why it stalls, and fix the timeout errors that kill tools at startup or after 60 seconds of work.
You add an MCP server to opencode.json, restart the terminal, and the tools never show up. Or they show up, the browser login opens, and the callback never lands. Or everything works until the first slow call dies with a timeout. Those three failures account for most OpenCode MCP config trouble, and each one has a short, boring fix.
This article walks through the exact fields OpenCode reads, the commands that tell you what is wrong, and the settings that end the guessing. The snippets follow the official OpenCode MCP docs as checked in October 2026, so paste them as written and change only the names, paths and URLs.
Where OpenCode Reads Its Config
OpenCode does not pick one config file and ignore the rest. It merges every source it finds, and when two sources set the same field, the later one in the order below wins. That is why a server you "removed" from the project file keeps coming back: it is still defined in your global file.
Config Locations and Merge Order
Order
Source
Best used for
1
Remote config from .well-known/opencode
Organization defaults
2
Global ~/.config/opencode/opencode.json
Servers you want everywhere
3
Path in the OPENCODE_CONFIG variable
A one-off or CI file
4
opencode.json in the project root
Repo-specific servers
5
.opencode directories
Agents, commands, plugins
6
OPENCODE_CONFIG_CONTENT variable
Inline overrides
7
Managed system settings
Rules enforced by an admin
Both JSON and JSONC (JSON with comments) work. Adding "$schema": "https://opencode.ai/config.json" at the top gives your editor autocomplete and red underlines on typos. Typos are the most common reason a server is silently ignored, so the schema line pays for itself within minutes.
💡 Tip: When a server behaves strangely, check the global file first. A stale entry there can override a perfectly good project entry.
Use Variables, Not Pasted Secrets
OpenCode substitutes two placeholders anywhere in the config. {env:NAME} reads an environment variable, and {file:path} inlines the contents of a file. Use them for every token, so the config stays safe to commit.
Relative file paths resolve from the config directory, while paths starting with / or ~ are absolute. If the variable is missing from the shell that launched OpenCode, the server never sees a valid token and answers 401, which looks exactly like a wrong token. Export the variable in the same shell, then start OpenCode from it.
Add Local and Remote Servers
Everything lives under one top-level field called mcp. Each child is a server with a name you choose, and that name becomes the prefix of its tools, so pick short, lowercase names without spaces.
A Minimal Local Server
A local server is a process OpenCode starts for you and talks to over standard input and output.
Two fields are required: "type": "local" and command. The part that trips people up is that command is an array of strings, one entry per argument, not a single shell string. Writing "command": "npx -y some-server" is the quickest way to get a server that never starts.
Environment Variables and Working Directory
Local servers often need credentials or a specific folder. environment passes variables to the child process, and cwd sets its working directory. Relative paths in cwd resolve from the workspace.
Setting "oauth": false is the right move for any server that authenticates with a static token. Without it, OpenCode treats a 401 as a signal to start an OAuth login, which is confusing when the real problem is a bad token.
Check the Result With mcp list
Run opencode mcp list after every edit. It prints each configured server and its status, so you know in two seconds whether a server connected, needs authentication or failed. Do this before you open a session and wonder why the tools are missing.
Here is the full field reference in one place:
Field
Local
Remote
What it does
type
required
required
local or remote
command
required
n/a
Array of strings that starts the process
cwd
optional
n/a
Working directory for the process
environment
optional
n/a
Variables passed to the process
url
n/a
required
Server endpoint
headers
n/a
optional
Custom HTTP headers
oauth
n/a
optional
An object, or false to turn OAuth off
enabled
optional
optional
Switch a server on or off without deleting it
timeout
optional
optional
Milliseconds, default 5000
💡 Tip: Set "enabled": false on servers you only need now and then. The entry stays in the file, and nothing loads into your session until you flip it back.
Fix OAuth Sign-In Problems
Remote servers that follow the MCP authorization flow need almost no setup. When OpenCode receives a 401, it starts OAuth by itself, registers as a client through Dynamic Client Registration (RFC 7591), opens your browser, and waits for the redirect. The resulting tokens are stored in ~/.local/share/opencode/mcp-auth.json.
How Automatic OAuth Works
For a server that supports it, the whole setup is two fields and one command.
Add the server with only type and url.
Run opencode mcp auth tracker, replacing tracker with your server name.
Approve the request in the browser tab that opens.
Run opencode mcp list and confirm the server shows as connected.
Four commands handle the full lifecycle:
Command
What it does
opencode mcp auth <name>
Starts the login flow
opencode mcp list
Shows servers and their auth status
opencode mcp logout <name>
Deletes the stored credentials
opencode mcp debug <name>
Diagnoses connection and OAuth problems
When a login that worked last week suddenly fails, the cause is usually a stale or revoked token. Run opencode mcp logout <name>, then opencode mcp auth <name> again, and you start from a clean slate.
Pre-Registered Clients and Scopes
Some providers refuse dynamic registration and want you to register an app by hand. In that case, give OpenCode the client details it would otherwise have created itself.
The scope value is a single string with scopes separated by spaces, exactly as the provider documents them. Ask for the smallest set that works. A broad scope that the provider rejects produces a login page error that says nothing useful about which scope was the problem.
Login Fails on a Remote Machine
This is the one that burns an afternoon. OpenCode listens on a local callback port while you sign in, and reports from users put the default at 19876. If OpenCode runs on a remote host over SSH, your browser on the laptop redirects to 127.0.0.1:19876 on the laptop, where nothing is listening. The approval succeeds, the callback never arrives, and the command eventually times out.
The fix is a port forward from your laptop to the remote host:
Run opencode mcp auth <name> inside that SSH session, open the printed URL in your local browser, and the callback now travels through the tunnel.
Recent builds also accept callbackPort and redirectUri inside the oauth object, for providers that require a fixed, pre-registered callback. The redirect URI must use http:// with localhost, 127.0.0.1 or [::1] and an explicit port. If you change the port, forward that same port. Check the schema in your editor before relying on either field, since older versions will not know them.
Timeout Fixes That Work
There are two different timeouts, and mixing them up wastes hours. One decides how long OpenCode waits for a server to start and list its tools. The other decides how long a single tool call may run once the server is up.
The Startup Default
The timeout field is in milliseconds and defaults to 5000 for both local and remote servers. Five seconds is fine for a small script. It is not enough for npx -y on a cold cache, because the package has to download before the server even starts. The server then shows as failed and its tools never load.
Fix it in this order:
Raise the field for that server only. Set "timeout": 15000 or 30000 on the slow entry and leave the others alone.
Remove the download. Install the package globally with npm install -g, then point command at the installed binary. Startup drops to a fraction of a second.
Test the endpoint for remote servers. Run a plain curl against the URL. If curl is slow too, the problem is network latency or the server, not your config.
Symptom
Likely cause
Fix
Fails after about 5 seconds
Default timeout
Raise it to 15000 or higher
Fails only on a fresh machine
npx downloading the package
Install it globally first
Fails only on a hotel network
Slow DNS or TLS handshake
Raise timeout, retry
When Tool Calls Die at 60 Seconds
A different error shows up later, in the middle of a session: MCP error -32001: Request timed out. That is the request timeout of the MCP client library, and many clients built on the TypeScript SDK default to 60 seconds. Raising the startup timeout does not change it for a running tool call.
Look in your build's schema for a per-request setting first. If there is none, change the tool instead of the client. Make the first tool return a job id immediately, and add a second tool that reports the job status. The model submits, gets an id, and checks back, which is the same submit-then-poll pattern that image and video generation APIs use for the same reason.
💡 Tip: Send server logs to stderr, never stdout. A local server shares stdout with the protocol, so a single stray console.log can corrupt the handshake and look like a timeout.
Debug a Server That Won't Connect
When the fix is not obvious, stop editing the config and test each layer separately.
Run the Server by Hand
Copy the command array into a terminal and run it as one line. A healthy stdio server starts and waits silently for input. If it prints an error, a missing module or a bad path, you found the problem without OpenCode in the loop. Then run opencode mcp debug <name>, which diagnoses connection and OAuth problems for that one server.
For a remote server, curl -i the URL with the same headers. A 401 means credentials, a 404 means the path, and a hang means the network.
Common Errors and Fixes
Symptom
Likely cause
Fix
Server missing from the list
Typo, or the wrong file edited
Add $schema, check the global file
Fails immediately
command is a string, or the binary is not on PATH
Use an array and an absolute path
Constant 401
Missing token variable, or OAuth expected
Export the variable, or run mcp auth
Login page never finishes
Callback cannot reach OpenCode
Forward the callback port
Tool call ends with -32001
60 second request limit
Use the job id pattern
Works in your shell, fails in OpenCode
Different PATH or environment
Set environment, use full paths
Keep Context Small Per Agent
Every connected server adds its tool descriptions to the context sent with each request. A handful of servers can eat a large share of the window before you type a word, and the model gets worse at picking the right tool when it has fifty to choose from. The OpenCode docs say as much: use MCP servers sparingly.
Disable Globally, Enable Per Agent
Tool names carry the server name as a prefix, so a glob pattern switches a whole server at once. * matches zero or more characters and ? matches exactly one.
With this setup, the builder agent sees only the filesystem tools and the planner agent sees only the tracker. Neither pays the token cost of the other server's tool list.
How to Use Claude Sonnet 5
Config bugs are tedious pattern matching: a string where an array belongs, a variable that is not exported, a port nobody forwarded. That is where a coding model earns its time. Claude Sonnet 5 on PicassoIA reads config text, error output and even screenshots, so you can paste what you see and ask what is wrong.
Paste your mcp block. Replace every token and secret with a placeholder first, then add the output of opencode mcp debug <name>.
Set the effort. The default low skips thinking and answers fastest. Use medium or high when several files interact, for example a global config overridden by a project config.
Add a system prompt once. Something like: "You review opencode.json MCP configs. Check type, command, timeout and oauth. Reply with corrected JSON only."
Attach a screenshot if you have one. The image input reads terminal errors. Raise the max image resolution when the text in the screenshot is small.
Keep max_tokens at 8192. That is the default and plenty for a few config blocks.
Verify before you paste. Check every field it suggests against the table above and the official docs.
💡 Tip: Never paste a real token into any chat box. Placeholders like TRACKER_TOKEN give the model everything it needs.
Make Your Own Images Today
Config is only half of what MCP can do. Once a coding agent can call tools, it can call image generators too. PicassoIA exposes its generators over MCP, and the server address lives on your account's MCP connections page. Any server that speaks HTTP follows the same remote pattern from this article: type, url, a header or OAuth, and a sensible timeout.
If you would rather skip the setup and just make pictures, open Picasso IA and try these text-to-image models:
Pick one, write a prompt about the thing you just configured, and compare how each model reads it. Ten minutes of experimenting teaches you more about prompt wording than an hour of reading, and every image you generate is a free rehearsal for the next one.