[BUG] mcp__ide__getDiagnostics available in CLI (integrated terminal) but missing from VSCode extension panel

Status Closed — not planned
Reported on v2.1.87
Maintainer reply None cached
Activity 7 comments · opened Mar 30, 2026 · closed Jul 11, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Summary

mcp__ide__getDiagnostics is available when running Claude Code CLI from VSCode's integrated terminal, but is completely absent from the deferred tools list when running via the native VSCode extension panel. The entire ide MCP namespace is missing.

What Should Happen?

mcp__ide__getDiagnostics should be available in the extension panel, since the IDE MCP server is started by the extension itself.

Error Messages/Logs

try listing mcp__ide available pls

> Nothing. The mcp__ide__* namespace simply doesn't exist in this session's tool registry. Confirmed still broken.


[info] From claude: 2026-03-30T02:28:04.977Z [DEBUG] ToolSearchTool: keyword search for "ide diagnostics", found 0 matches

Steps to Reproduce

  1. Open a TypeScript project in VSCode with the Claude Code extension active
  2. Open the Claude Code extension panel
  3. Ask Claude to use mcp__ide__getDiagnostics — tool is not available
  4. The ide MCP namespace is entirely absent from the deferred tools list
  5. Open VSCode's integrated terminal and run claude CLI
  6. mcp__ide__getDiagnostics is available and works correctly

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.87

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code integrated terminal

Additional Information

The IDE MCP server IS running (confirmed via lock file):

$ ls -t ~/.claude/ide/*.lock | head -1
~/.claude/ide/17340.lock

$ cat ~/.claude/ide/17340.lock
{"pid":713,"workspaceFolders":["/Users/username/..."],
"ideName":"Visual Studio Code","transport":"ws",
"runningInWindows":false,"authToken":"..."}

The extension panel knows it's running inside VSCode:

CLAUDE_CODE_ENTRYPOINT=claude-vscode
CLAUDECODE=1
CLAUDE_AGENT_SDK_VERSION=0.2.87

But it does not set the two env vars needed for IDE MCP server discovery:

ENABLE_IDE_INTEGRATION=   (empty)
CLAUDE_CODE_SSE_PORT=     (empty)

These env vars are only injected into integrated terminal contexts. The CLI in the terminal picks them up and connects to the IDE MCP server; the extension panel cannot discover it.

Workarounds attempted

| Approach | Result |
|---|---|
| claude-code.claudeProcessWrapper shell script that reads lock file and exports env vars | Env vars did not propagate — extension panel likely doesn't use the wrapper |
| mcp__ide__* explicitly allowed in .claude/settings.json and .claude/settings.local.json | No effect — tools are never registered |
| VSCode window reload | No effect |
| settings.json env field | Only accepts static strings; port is dynamic per session |

Working workaround

Use Claude CLI from VSCode's integrated terminal instead of the extension panel.

Additional context

  • Other MCP servers work in the extension panel (mcp__chakra-ui__*, mcp__plugin_playwright_playwright__*, mcp__zeplin__*)
  • The typescript-lsp plugin's LSP tool works correctly in the extension panel
  • No PreToolUse hooks block mcp__ide__* tools
  • No .mcp.json config exists

View original on GitHub ↗

7 Comments

alexilyaev · 4 months ago

Having the same issue in Cursor

  • Works in "Claude Code: Open in Terminal"
  • Doesn't work in "Claude Code: Open in Side Bar"
IliyaBrook · 3 months ago

I have the same issue: when running the plugin in extension mode it simply does not call Use mcp__ide__getDiagnostics. The one built into VS Code Copilot handles this without any problem, and in terminal mode it also works. Please fix this; without the functionality, when the agent has access to all diagnostic data for the code, using this extension becomes meaningless.

majelbstoat · 2 months ago

Yeah, still an issue, still annoying. "The LSP says X doesn't exist. {waits} Maybe it's stale. {waits} It's stale, moving on". There's a perfectly valid real-time LSP _right there_!

github-actions[bot] · 1 month ago

Closing for now — inactive for too long. Please open a new issue if this is still relevant.

npapadacis · 3 days ago

In case it's useful for anyone my workaround to get claude to see the problems pane was to create a node powered MCP shim.

  1. Create files below
  2. Run npm i @modelcontextprotocol/sdk ws in the tooling folder.
  3. Start a new claude session (.mcp.json only read on session start) and check /mcp shows vscode-problems.

You can then ask claude to check it with a slash command /vscode-problems (or just tell it the server exists and to check when you want it to)

.mcp.json in project root

{
  "mcpServers": {
    "vscode-problems": {
      "command": "node",
      "args": ["./tooling/vscode-problems-mcp.mjs"]
    }
  }
}

tooling/vscode-problems-mcp.mjs

// Works with VS Code + Claude Code extension (tested with v2.1.246) to read the Problems panel for the current workspace. Can be used as a CLI or as an MCP tool.
// tooling/vscode-problems-mcp.mjs
// npm i @modelcontextprotocol/sdk ws
import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import { fileURLToPath } from "node:url";
import WebSocket from "ws";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";

const IDE_DIR = path.join(os.homedir(), ".claude", "ide");
const norm = (p) => p.replace(/\\/g, "/").toLowerCase().replace(/\/$/, "");

function findLock(cwd) {
  if (!fs.existsSync(IDE_DIR)) return null;
  const target = norm(cwd);
  const locks = fs.readdirSync(IDE_DIR).filter((f) => f.endsWith(".lock"));
  for (const f of locks) {
    try {
      const data = JSON.parse(fs.readFileSync(path.join(IDE_DIR, f), "utf8"));
      const match = (data.workspaceFolders || []).some((w) => {
        const n = norm(w);
        return target === n || target.startsWith(n + "/");
      });
      if (match) return { port: path.basename(f, ".lock"), token: data.authToken };
    } catch {
      /* skip malformed lock */
    }
  }
  return null;
}

function fetchDiagnostics(lock, timeoutMs = 10000) {
  return new Promise((resolve, reject) => {
    const ws = new WebSocket(`ws://127.0.0.1:${lock.port}`, {
      headers: { "x-claude-code-ide-authorization": lock.token },
    });
    const timer = setTimeout(() => {
      ws.terminate();
      reject(new Error("timed out"));
    }, timeoutMs);
    const done = (fn, arg) => {
      clearTimeout(timer);
      try {
        ws.close();
      } catch {}
      fn(arg);
    };

    ws.on("open", () =>
      ws.send(
        JSON.stringify({
          jsonrpc: "2.0",
          id: 1,
          method: "initialize",
          params: {
            protocolVersion: "2025-06-18",
            capabilities: {},
            clientInfo: { name: "vscode-problems-shim", version: "1.0.0" },
          },
        })
      )
    );

    ws.on("message", (buf) => {
      let msg;
      try {
        msg = JSON.parse(buf.toString());
      } catch {
        return;
      }
      if (msg.id === 1) {
        ws.send(JSON.stringify({ jsonrpc: "2.0", method: "notifications/initialized" }));
        ws.send(
          JSON.stringify({
            jsonrpc: "2.0",
            id: 2,
            method: "tools/call",
            params: { name: "getDiagnostics", arguments: {} },
          })
        );
      } else if (msg.id === 2) {
        if (msg.error) return done(reject, new Error(msg.error.message));
        try {
          done(resolve, JSON.parse(msg.result.content[0].text));
        } catch (e) {
          done(reject, e);
        }
      }
    });

    ws.on("error", (e) => done(reject, e));
  });
}

const NOISE = [/\/appdata\/local\/temp\/claude\//i, /\/scratchpad\//i, /\/node_modules\//i];

function format(files, { severity = "error", pathFilter, excludeCodes = [], max = 50 }) {
  const wanted = severity === "all" ? null : severity.toLowerCase();
  const rows = [];
  for (const f of files) {
    if (!f.diagnostics?.length) continue;
    if (NOISE.some((re) => re.test(f.uri))) continue;
    let rel;
    try {
      rel = path.relative(process.cwd(), fileURLToPath(f.uri)).replace(/\\/g, "/");
    } catch {
      rel = f.uri;
    }
    if (pathFilter && !rel.toLowerCase().includes(pathFilter.toLowerCase())) continue;
    for (const d of f.diagnostics) {
      if (wanted && d.severity?.toLowerCase() !== wanted) continue;
      if (excludeCodes.includes(String(d.code))) continue;
      rows.push(
        `${rel}:${d.range.start.line + 1}:${d.range.start.character + 1}  [${d.source ?? "?"}${d.code ?? ""}] ${d.message}`
      );
    }
  }
  const shown = rows.slice(0, max);
  const header = `${rows.length} matching diagnostic(s)${rows.length > max ? `, showing first ${max}` : ""} as of ${new Date().toISOString()}`;
  return [header, "", ...shown].join("\n");
}

const server = new Server(
  { name: "vscode-problems", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "vscode_problems",
      description:
        "Read the VS Code Problems panel for this workspace. Returns compact 'path:line:col [source+code] message' rows. Defaults to errors only. Requires VS Code open on this workspace.",
      inputSchema: {
        type: "object",
        properties: {
          severity: {
            type: "string",
            enum: ["error", "warning", "information", "hint", "all"],
            default: "error",
          },
          pathFilter: {
            type: "string",
            description: "Only files whose relative path contains this substring.",
          },
          excludeCodes: {
            type: "array",
            items: { type: "string" },
            description: "Diagnostic codes to drop, e.g. ['6133'] for unused-variable noise.",
          },
          max: { type: "number", default: 50 },
        },
      },
    },
  ],
}));

server.setRequestHandler(CallToolRequestSchema, async (req) => {
  if (req.params.name !== "vscode_problems") throw new Error(`Unknown tool: ${req.params.name}`);
  const lock = findLock(process.cwd());
  if (!lock)
    return {
      content: [
        {
          type: "text",
          text: "VS Code IDE server not found for this workspace. Is VS Code open with the Claude Code extension active?",
        },
      ],
    };
  try {
    const files = await fetchDiagnostics(lock);
    return { content: [{ type: "text", text: format(files, req.params.arguments ?? {}) }] };
  } catch (e) {
    return { content: [{ type: "text", text: `Could not read diagnostics: ${e.message}` }] };
  }
});

// --- entry point ---------------------------------------------------------
const isCli = process.argv[2] === "--cli";

if (isCli) {
  const arg = (name, fallback) => {
    const i = process.argv.indexOf(`--${name}`);
    return i > -1 ? process.argv[i + 1] : fallback;
  };
  const lock = findLock(process.cwd());
  if (!lock) {
    console.error("No IDE server found for", process.cwd());
    process.exit(1);
  }
  const files = await fetchDiagnostics(lock);
  const out = format(files, {
    severity: arg("severity", "error"),
    pathFilter: arg("path"),
    excludeCodes: (arg("exclude", "") || "").split(",").filter(Boolean),
    max: Number(arg("max", 50)),
  });
  console.log(out);
  console.error(`\n[${out.length} chars, ~${Math.ceil(out.length / 4)} tokens]`);
} else {
  await server.connect(new StdioServerTransport());
}
ptim · 2 days ago
In case it's useful for anyone my workaround to get claude to see the problems pane was to create a node powered MCP shim.

This is fantastic @npapadacis - many thanks! I ran with it and made this an NPM package: https://github.com/ptim/claude-vscode-ide-bridge-mcp

npapadacis · 2 days ago
> In case it's useful for anyone my workaround to get claude to see the problems pane was to create a node powered MCP shim. This is fantastic @npapadacis - many thanks! I ran with it and made this an NPM package: https://github.com/ptim/claude-vscode-ide-bridge-mcp

Glad it was helpful. Looks like you definitely ran with it, that's a much more comprehensive solution than my quick hack 😋