Skip to content

mcp: failed servers are indistinguishable from unconfigured ones for the agent #62973

Open

Description

@XA21X

Summary

When a configured MCP server is in failed state it disappears completely from the agent's tool surface — the tool catalog and the session's MCP instructions context contain only connected servers, with no placeholder, error, or "configured but failed" marker anywhere. From inside a session, a failed server is literally indistinguishable from one that was never configured. The agent therefore never asks the user to reconnect; it concludes "not configured" and burns turns inventing workarounds. This is distinct from connection retry (tracked in #52237 / #53226): even a perfectly retrying client should tell the model that a configured server is currently down.

Environment

  • opencode version: v2.2.5
  • OS: Darwin 25.6.0 (darwin arm64)
  • Terminal: rio (TERM=rio, COLORTERM=truecolor)
  • Shell: /bin/zsh
  • Install/channel: latest
  • Active plugins: @cortexkit/aft-opencode, @cortexkit/opencode-magic-context, opencode-planning-with-files

Reproduction

  1. Configure at least one remote MCP server (type: "remote") and confirm it connects: opencode mcp list → ✓ connected.
  2. Cause a transient outage so its connect fails — e.g. drop DNS/VPN briefly. The server log then shows:
    level=WARN message="mcp connect failed" server=<name> status.status=failed status.error="getaddrinfo ENOTFOUND <host>"
  3. Restore the network. opencode mcp list still reports ✗ <name> failed: getaddrinfo ENOTFOUND ... (persisted state, no probe, no retry — see mcp: remote MCP servers that fail once are never retried until service restart #52237).
  4. Start a fresh agent session and ask the agent to list its available MCP servers, or to use a tool from that server.

Expected Behavior

The agent's context should list configured-but-failed servers — at minimum one line per server (name, last error, "user can reconnect via /mcps") — so the agent asks the user to fix the connection. The agent is the only party in the loop that can notice the gap during use and surface it.

Actual Behavior

The session's tool catalog and MCP instructions context contain only connected servers. There is zero trace of the failed one: no entry, no error, no marker. opencode mcp list reports the failure correctly, but that is an operator-only surface the agent never sees.

Real-world impact observed

Two configured servers (one OAuth remote HTTP server, one uvx-launched local server) both latched failed on a transient DNS outage. Network recovered within minutes; the failed state persisted for 24+ hours across fresh sessions (✗ datadog failed: getaddrinfo ENOTFOUND mcp.datadoghq.com, ✗ atlassian failed: ... error resolving DNS ... pypi.org). Agents in fresh sessions reasoned "this integration is not configured" and escalated into credential-hunting the underlying REST APIs directly — dangerous workaround behavior we had to defend against with a hard project rule banning it.

Additional Context

Activity

  1. opencodejr commented on Nov 9, 2026

    @opencodejr

    Thanks for the detailed write-up. The request: when a configured MCP server is failed (or needs_auth), the agent's context should still say it exists and is down, with its last error and a hint that the user can reconnect it via /mcps. That way the agent stops treating it as unconfigured.

    Right now this is intentional. The MCP instructions block only covers servers with tools the session can use, so a failed server is left out completely. That makes this a feature request rather than a bug, and maintainers will consider it.

    In the meantime, a small plugin can add the notice. It reads the server statuses before each model request and adds a short system note for any server that isn't connected. It type-checks against @opencode/plugin on dev, but I haven't run it in a live session. One way to install it is to save it as a local plugin, e.g. .opencode/plugins/mcp-status-notice.ts in your project or the plugins/ folder of your global OpenCode config directory:

    import { Plugin } from "@opencode/plugin"
    
    export default Plugin.define({
      id: "mcp-status-notice",
      async setup(ctx) {
        await ctx.session.hook("context", async (event) => {
          const { data: servers } = await ctx.mcp.list({ location: { directory: ctx.location.directory } })
          const lines = servers.flatMap((s) =>
            s.status.status === "failed" || s.status.status === "needs_auth"
              ? [`- ${s.name}: ${s.status.status} (${s.status.error})`]
              : [],
          )
          if (lines.length === 0) return
          event.system.push({
            type: "text",
            text: [
              "<mcp_unavailable>",
              "These MCP servers are configured but not connected, so their tools are missing:",
              ...lines,
              "Do not treat them as unconfigured or work around them. Ask the user to reconnect them (/mcps).",
              "</mcp_unavailable>",
            ].join("\n"),
          })
        })
      },
    })

    Related issues:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions