DEV Community

Cover image for OpenCode 2.2.6 pools your MCP connections: what pool:true saves, and what it can't
Piekwerk
Piekwerk

Posted on

OpenCode 2.2.6 pools your MCP connections: what pool:true saves, and what it can't

OpenCode shipped v2.2.6 on November 6, and the release notes read like a maintenance week aimed at people who run agents unattended. One opt-in flag for sharing MCP connections, three changes to scripted runs, a stack of quiet security fixes, and a two-second wait that addresses a race I have hit in every MCP client I have used. I read the full notes so you can decide what to flip on and what to test first. Worth noting the release lives under the anomalyco org now, the old sst/opencode path redirects there.

What pool:true actually shares

The headline change is connection pooling. Set pool: true on an MCP server in your config, and OpenCode shares one connection to that server across projects that declare the same setup, instead of starting a separate server process for each project. The stated wins in the notes are concrete and modest: you run fewer processes and start faster.

The key sits inside the regular per-server block:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "docs-search": {
      "type": "local",
      "command": ["npx", "-y", "some-mcp-server"],
      "enabled": true,
      "pool": true
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

It is opt-in per server, so nothing changes until you add the key yourself.

The token bill it doesn't pay

Pooling shares the connection, not the context. Every session that uses a pooled server still gets that server's tool schemas injected into the model's context, because the schemas ride along with the conversation, not the process. When I measured the token cost of 9 MCP servers, that schema overhead arrived before the first prompt, per session. Pooling does not touch it.

What pooling can do is cut duplicate processes if you bounce between several repos that define the same servers, and spare you repeated cold starts, since the second project attaches to a connection that is already up instead of waiting for npx to resolve again. The notes do not quantify the startup win, so I will not either. If you hoped pooling would shrink your prompts, that is not what this flag does.

Three questions before you flip it on

The notes say projects pool when they have "the same setup", and they do not spell out the conflict semantics. Before pooling a server across projects, I would check three things myself:

  1. Does the server keep state? One shared connection means one shared server process, so per-repo indexes or caches inside the server are now shared between projects. For a stateless search server that is fine. For a server that tracks where it thinks it is, verify first.
  2. Do your projects declare the server identically? Different environment variables or arguments are the obvious way two declarations stop being "the same setup". Test with a deliberately different env var and see whether you still get one process.
  3. Does the server care about its working directory? The same release expanded ~ in local MCP working directories, which is a reminder that cwd matters to local servers. A pooled process has one cwd serving several projects.

None of this is a reason to avoid the flag. It is a reason to flip it on one stateless server first and watch the process table before you pool everything.

The scripted-run trio

Three changes target opencode run directly. The --archived flag creates a session that starts archived, so CI and scripted runs stay out of your inbox, home view, and session lists, and --continue skips them. The -w flag starts the session in a fresh git worktree, with --worktree=<name> to pick the name, and it cannot be combined with --continue or --session, which makes sense given the session is meant to be disposable. Worktree isolation for scripted runs is the same pattern I rely on when running 4 agents in parallel, because two agents editing one checkout will always find each other's half-written files.

Put together, a CI invocation now looks like this:

timeout 900 opencode run --archived --worktree=ci-fix \
  "reproduce the failing test, fix it, run the suite"
echo "exit: $?"
Enter fullscreen mode Exit fullscreen mode

Note the timeout. That is not decoration, and the next section is why.

The wait with no clock

opencode run now waits for the background shell commands, subagents, and image jobs its prompt started, and lets the model respond to their results before exiting. While it waits it prints waiting for N background job(s), and with --format json you get a background_wait event you can consume in a script. This fixes the old failure mode where a run exited with a dev server or build still mid-flight and the result never landed.

Here is the trap: there is no time limit on the wait. A job that never exits, the notes name dev servers and file watchers as the examples, keeps the run open until you press Ctrl+C or send SIGTERM. In CI, that is a hanged job burning minutes until the platform kills it. The escape hatch is clean, at least. SIGTERM cancels the session and its background jobs, and the process exits 143, so a wrapper can tell "cancelled" from "finished". The timeout in the snippet above is how you buy that behavior on a schedule.

Quiet security fixes worth reading twice

Most of the fixes would never make a headline and several matter more than the features:

  • File reads and media served from the server API are now sandboxed downloads, and the server refuses cross-site browser navigations and requests from disallowed origins on /api/*. A file in your project can no longer run scripts on the server's origin.
  • webfetch and Code Mode fetch now reject URLs that contain embedded credentials, and Code Mode fetch checks every redirect against your webfetch permission rules. Redirect checking closes a real gap: a rule for one host said nothing about where that host's shortlinks forwarded you.
  • session_move now asks for external_directory permission before a session leaves the current project, so a moved session cannot quietly carry file access outside the repo it started in.
  • A new websearch.use policy action puts web search behind a permission, for configs that want it gated.

The two-second window

Before the first model call, OpenCode now waits up to 2 seconds for MCP servers that are still connecting, so tools from servers that connect quickly reach the first prompt and scripted runs. Anyone who has watched an agent's opening reply arrive missing half its tools, because the server handshake was still in flight, knows this race. Two seconds is a heuristic, not a guarantee: a server that takes ten seconds to boot still misses the window. But fast servers stop losing the start of the conversation, which is the common case.

What I'd check after upgrading

Grep your config for servers you declare in every repo and pool one stateless one first, then watch the process count while opening a second project. Add --archived and a worktree to any scripted runs, and wrap them in a timeout now, before a watcher hangs a job at 2am. If you maintain webfetch permission rules, re-test them against a redirecting URL, because the rules now cover more ground than they did last week. None of these changes is flashy. All of them change how the tool behaves when nobody is watching it, which is exactly when the interesting failures happen.

Top comments (0)