diff --git a/CHANGELOG.md b/CHANGELOG.md
index a54fac1..98b9b4d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@ All notable changes to DebugMCP will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
+## [Unreleased]
+
+### Added
+- **Claude Code auto-registration** - Claude Code is now offered in the agent selection popup and configured via `~/.claude.json`'s user-scope `mcpServers` field. Claude Desktop connects via its Custom Connector UI instead of a static config file; the README's manual configuration section covers both.
+
## [2.3.5] - 2026-09-09
### Fixed
diff --git a/README.md b/README.md
index 75c9d14..e23c3c1 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,10 @@
# DebugMCP (MCP Server) - Empowering AI Agents with Operational Debugging Capabilities
-Let AI agents debug your code inside VS Code - set breakpoints, step through execution, inspect variables, and evaluate expressions. Works with **Codex**, **GitHub Copilot**, **GitHub Copilot CLI**, **Cline**, **Cursor**, **Windsurf**, **Roo Code**, and any MCP-compatible assistant. Compatible with any VS Code supported coding language.
+Let AI agents debug your code inside VS Code - set breakpoints, step through execution, inspect variables, and evaluate expressions. Works with **Codex**, **GitHub Copilot**, **GitHub Copilot CLI**, **Claude Code**, **Cline**, **Cursor**, **Windsurf**, **Roo Code**, and any MCP-compatible assistant. Compatible with any VS Code supported coding language.
[](https://opensource.org/licenses/MIT)
[](https://code.visualstudio.com/)
-[](https://github.com/microsoft/DebugMCP)
+[](https://github.com/microsoft/DebugMCP)
[](https://marketplace.visualstudio.com/items?itemName=ozzafar.debugmcpextension)
> ⭐ **If you find DebugMCP useful, please [star the repo on GitHub](https://github.com/microsoft/DebugMCP)!** It helps others discover the project and motivates continued development.
@@ -133,6 +133,7 @@ DebugMCP works with any MCP-compatible AI assistant. It auto-detects and offers
|-----------|:-----------------:|:-------------:|
| **GitHub Copilot** | ✅ | [See config](#github-copilot) |
| **GitHub Copilot CLI** | ✅ | [See config](#github-copilot-cli) |
+| **Claude Code** | ✅ | [See config](#claude-code) |
| **Cline** | ✅ | [See config](#cline) |
| **Cursor** | ✅ | [See config](#cursor) |
| **Codex** | ✅ | [See config](#codex) |
@@ -214,6 +215,26 @@ Add to `~/.copilot/mcp-config.json` (`${COPILOT_HOME}/mcp-config.json` if `COPIL
}
```
+#### Claude Code
+Register DebugMCP with Claude Code:
+```bash
+claude mcp add --transport http --scope user debugmcp http://localhost:3001/mcp
+```
+
+Or add the equivalent configuration to `~/.claude.json` (top-level `mcpServers`, for cross-project user-scope access — see the [Claude Code MCP docs](https://code.claude.com/docs/en/mcp)):
+```json
+{
+ "mcpServers": {
+ "debugmcp": {
+ "type": "http",
+ "url": "http://localhost:3001/mcp"
+ }
+ }
+}
+```
+
+> **Claude Desktop**: Claude Desktop connects to local/remote HTTP MCP servers through **Settings → Connectors → Add custom connector** rather than a static config file — paste `http://localhost:3001/mcp` there. DebugMCP doesn't auto-register with Desktop for this reason.
+
#### Cursor
Add to Cursor's MCP settings:
```json
@@ -315,7 +336,7 @@ DebugMCP exposes powerful debugger primitives (`evaluate_expression`, `start_deb
Which AI assistants are supported?
-DebugMCP works with any MCP-compatible AI assistant, including **GitHub Copilot**, **GitHub Copilot CLI**, **Cline**, **Cursor**, **Codex**, **Windsurf**, **Roo Code**, **Antigravity**, and others. If your assistant supports the Model Context Protocol, it can use DebugMCP.
+DebugMCP works with any MCP-compatible AI assistant, including **GitHub Copilot**, **GitHub Copilot CLI**, **Claude Code**, **Cline**, **Cursor**, **Codex**, **Windsurf**, **Roo Code**, **Antigravity**, and others. If your assistant supports the Model Context Protocol, it can use DebugMCP. Claude Desktop can also connect via its Custom Connector UI (see [Claude Code](#claude-code) in the manual configuration section).
@@ -429,7 +450,7 @@ The extension handles debug configurations intelligently:
- **Rust**: [rust-analyzer extension](vscode:extension/rust-lang.rust-analyzer)
- **PHP**: [PHP Debug extension](vscode:extension/xdebug.php-debug)
- **Ruby**: [Ruby extension](vscode:extension/Shopify.ruby-lsp) and the [`debug` gem](https://github.com/ruby/debug)
-- MCP-compatible AI assistant (Copilot, Cline, Cursor, Codex, Windsurf, Roo Code, etc.)
+- MCP-compatible AI assistant (Copilot, Claude Code, Cline, Cursor, Codex, Windsurf, Roo Code, etc.)
## Development
diff --git a/docs/architecture/agentConfigurationManager.md b/docs/architecture/agentConfigurationManager.md
index 12c2510..b4a35d8 100644
--- a/docs/architecture/agentConfigurationManager.md
+++ b/docs/architecture/agentConfigurationManager.md
@@ -2,11 +2,11 @@
## Purpose
-Handles automatic configuration of AI coding agents (Cline, GitHub Copilot, GitHub Copilot CLI, Cursor, Codex) to connect to the DebugMCP server. Provides a seamless onboarding experience.
+Handles automatic configuration of AI coding agents (Cline, GitHub Copilot, GitHub Copilot CLI, Claude Code, Cursor, Codex) to connect to the DebugMCP server. Provides a seamless onboarding experience.
## Motivation
-For AI agents to use DebugMCP, they need MCP server configuration in their settings files. Rather than requiring users to manually edit JSON files, this manager auto-configures supported agents with the correct SSE endpoint.
+For AI agents to use DebugMCP, they need MCP server configuration in their settings files. Rather than requiring users to manually edit JSON files, this manager auto-configures supported agents with the Streamable HTTP endpoint.
## Responsibility
@@ -28,6 +28,7 @@ Popup** from the Command Palette after correcting the JSON.
| Cline | `cline_mcp_settings.json` | `mcpServers` |
| GitHub Copilot | `mcp.json` | `servers` |
| GitHub Copilot CLI | `~/.copilot/mcp-config.json` or `${COPILOT_HOME}/mcp-config.json` | `mcpServers` |
+| Claude Code | `~/.claude.json` | Top-level `mcpServers` (user scope, shared across projects) |
| Cursor | `mcp_settings.json` | `mcpServers` |
| Codex | `~/.codex/config.toml` or `${CODEX_HOME}/config.toml` | `mcp_servers.debugmcp` |
@@ -68,6 +69,16 @@ GitHub Copilot CLI uses:
}
```
+Claude Code uses `type: "http"` and `url` in the top-level `mcpServers.debugmcp`
+entry of `~/.claude.json`. Setup preserves unrelated top-level settings, project
+settings (including project-scoped MCP servers), and other user-scoped MCP servers.
+
+On extension activation, migration leaves existing Claude Code `http` and
+`streamable-http` entries unchanged, including custom URLs and headers, unless
+the URL still ends in `/sse`. Entries with `type: "sse"` or a legacy `/sse` URL
+are migrated to the current HTTP configuration. Once migrated, subsequent runs
+do not rewrite the configuration or report another migration.
+
Codex uses TOML:
```toml
[mcp_servers.debugmcp]
diff --git a/package-lock.json b/package-lock.json
index de52f43..e4b30ad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "debugmcpextension",
- "version": "2.3.5",
+ "version": "2.3.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "debugmcpextension",
- "version": "2.3.5",
+ "version": "2.3.6",
"license": "MIT",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.26.0",
diff --git a/package.json b/package.json
index aa6a972..a15f38c 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "debugmcpextension",
"displayName": "DebugMCP — Agentic Debugging for VS Code, Cursor & More",
"description": "Your AI agent debugs for you — right inside VS Code, Cursor & other VS Code-based editors. Let Copilot, Cline, Cursor, Codex & any MCP agent set breakpoints, step through code, and inspect variables live instead of guessing from logs.",
- "version": "2.3.5",
+ "version": "2.3.6",
"publisher": "ozzafar",
"author": {
"name": "Oz Zafar",
diff --git a/src/test/agentConfigurationManager.test.ts b/src/test/agentConfigurationManager.test.ts
index 901f7da..c51accf 100644
--- a/src/test/agentConfigurationManager.test.ts
+++ b/src/test/agentConfigurationManager.test.ts
@@ -1,10 +1,13 @@
// Copyright (c) Microsoft Corporation.
+import * as vscode from 'vscode';
import * as assert from 'assert';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import {
+ AgentConfigurationManager,
+ JsonAgentInfo,
upsertCodexDebugMCPConfig,
upsertJsonDebugMCPConfigFile
} from '../utils/agentConfigurationManager';
@@ -31,6 +34,184 @@ suite('AgentConfigurationManager JSON configuration', () => {
});
});
+suite('AgentConfigurationManager Claude Code configuration', () => {
+ const serverPort = 4317;
+ const expectedEntry = { type: 'http', url: `http://localhost:${serverPort}/mcp` };
+ const unrelatedConfig = {
+ theme: 'dark',
+ projects: {
+ '/sample/project': {
+ hasTrustDialogAccepted: true,
+ mcpServers: {
+ debugmcp: { type: 'http', url: 'http://localhost:9876/mcp' },
+ projectServer: { command: 'sample', args: ['--project'] }
+ }
+ }
+ }
+ };
+ const otherServer = { type: 'http', url: 'https://other.example/mcp' };
+ const originalWriteFile = fs.promises.writeFile;
+ const originalShowInformationMessage = vscode.window.showInformationMessage;
+ let tempDir: string;
+ let manager: AgentConfigurationManager;
+ let supportedAgent: JsonAgentInfo;
+ let agent: JsonAgentInfo;
+ let writes: number;
+ let notifications: string[];
+
+ setup(async () => {
+ tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'debugmcp-claude-config-'));
+ manager = new AgentConfigurationManager({ extensionPath: tempDir } as vscode.ExtensionContext, 180, serverPort);
+ const agents = await manager['getSupportedAgents']();
+ const claudeCode = agents.find(candidate => candidate.id === 'claude-code');
+ assert.ok(claudeCode && claudeCode.configFormat === 'json');
+ supportedAgent = claudeCode;
+ agent = { ...supportedAgent, configPath: path.join(tempDir, '.claude.json') };
+ // Exercise the real setup and migration paths using only the temporary config.
+ manager['getSupportedAgents'] = async () => [agent];
+ manager['installDebugMCPSkill'] = async () => null;
+ writes = 0;
+ notifications = [];
+ fs.promises.writeFile = async (...args: Parameters) => {
+ if (args[0] === agent.configPath) {
+ writes++;
+ }
+ return originalWriteFile(...args);
+ };
+ vscode.window.showInformationMessage = async (message: string) => {
+ notifications.push(message);
+ return undefined;
+ };
+ });
+
+ teardown(async () => {
+ fs.promises.writeFile = originalWriteFile;
+ vscode.window.showInformationMessage = originalShowInformationMessage;
+ await fs.promises.rm(tempDir, { recursive: true, force: true });
+ });
+
+ test('uses the user-scoped Claude Code configuration location', () => {
+ assert.strictEqual(supportedAgent.configPath, path.join(os.homedir(), '.claude.json'));
+ assert.strictEqual(supportedAgent.mcpServerFieldName, 'mcpServers');
+ });
+
+ test('setup generates only the Claude Code HTTP fields using the configured port', async () => {
+ const result = await manager['addDebugMCPToAgent'](agent);
+
+ assert.strictEqual(result.success, true);
+ assert.deepStrictEqual(JSON.parse(await fs.promises.readFile(agent.configPath, 'utf8')), {
+ mcpServers: { debugmcp: expectedEntry }
+ });
+ assert.strictEqual(writes, 1);
+ });
+
+ for (const hasUserServers of [false, true]) {
+ test(`setup preserves unrelated settings with ${hasUserServers ? 'existing' : 'no'} user-scoped servers`, async () => {
+ const existingServers = hasUserServers ? { other: otherServer } : {};
+ const initial = {
+ ...unrelatedConfig,
+ ...(hasUserServers ? { mcpServers: existingServers } : {})
+ };
+ await originalWriteFile(agent.configPath, JSON.stringify(initial), 'utf8');
+
+ const result = await manager['addDebugMCPToAgent'](agent);
+
+ assert.strictEqual(result.success, true);
+ assert.deepStrictEqual(JSON.parse(await fs.promises.readFile(agent.configPath, 'utf8')), {
+ ...unrelatedConfig,
+ mcpServers: { ...existingServers, debugmcp: expectedEntry }
+ });
+ assert.strictEqual(writes, 1);
+ });
+ }
+
+ for (const type of ['http', 'streamable-http']) {
+ for (const url of [expectedEntry.url, 'https://custom.example:4443/debug/mcp']) {
+ test(`migration does not rewrite or notify for ${type} at ${url}`, async () => {
+ const content = JSON.stringify({
+ ...unrelatedConfig,
+ mcpServers: {
+ other: otherServer,
+ debugmcp: { type, url, headers: { 'X-Test': 'synthetic-value' } }
+ }
+ });
+ await originalWriteFile(agent.configPath, content, 'utf8');
+
+ for (let run = 0; run < 2; run++) {
+ await manager.migrateExistingConfigurations();
+
+ assert.strictEqual(await fs.promises.readFile(agent.configPath, 'utf8'), content);
+ assert.strictEqual(writes, 0);
+ assert.deepStrictEqual(notifications, []);
+ }
+ });
+ }
+ }
+
+ for (const legacyEntry of [
+ { type: 'sse', url: 'http://localhost:3001/sse' },
+ { type: 'sse', url: 'http://localhost:3001/mcp' },
+ { type: 'http', url: 'http://localhost:3001/sse' },
+ { type: 'streamable-http', url: 'http://localhost:3001/sse' }
+ ]) {
+ test(`migrates ${legacyEntry.type} at ${legacyEntry.url} only once and preserves unrelated settings`, async () => {
+ await originalWriteFile(agent.configPath, JSON.stringify({
+ ...unrelatedConfig,
+ mcpServers: { other: otherServer, debugmcp: legacyEntry }
+ }), 'utf8');
+
+ await manager.migrateExistingConfigurations();
+
+ const migratedContent = await fs.promises.readFile(agent.configPath, 'utf8');
+ assert.deepStrictEqual(JSON.parse(migratedContent), {
+ ...unrelatedConfig,
+ mcpServers: { other: otherServer, debugmcp: expectedEntry }
+ });
+ assert.strictEqual(writes, 1);
+ assert.deepStrictEqual(notifications, [
+ 'DebugMCP: Migrated 1 agent configuration(s) to use the new transport protocol.'
+ ]);
+
+ await manager.migrateExistingConfigurations();
+
+ assert.strictEqual(await fs.promises.readFile(agent.configPath, 'utf8'), migratedContent);
+ assert.strictEqual(writes, 1);
+ assert.strictEqual(notifications.length, 1);
+ });
+ }
+
+ test('still leaves a valid Copilot CLI HTTP entry unchanged', async () => {
+ agent = { ...agent, id: 'copilot-cli' };
+ const content = JSON.stringify({ mcpServers: { debugmcp: { ...expectedEntry, tools: ['*'] } } });
+ await originalWriteFile(agent.configPath, content, 'utf8');
+
+ await manager.migrateExistingConfigurations();
+
+ assert.strictEqual(await fs.promises.readFile(agent.configPath, 'utf8'), content);
+ assert.strictEqual(writes, 0);
+ assert.deepStrictEqual(notifications, []);
+ });
+
+ test('still migrates a Cline HTTP entry and preserves custom autoApprove settings', async () => {
+ agent = { ...agent, id: 'cline' };
+ const autoApprove = ['list_breakpoints'];
+ await originalWriteFile(agent.configPath, JSON.stringify({
+ mcpServers: { debugmcp: { ...expectedEntry, autoApprove } }
+ }), 'utf8');
+
+ await manager.migrateExistingConfigurations();
+ await manager.migrateExistingConfigurations();
+
+ assert.deepStrictEqual(JSON.parse(await fs.promises.readFile(agent.configPath, 'utf8')), {
+ mcpServers: {
+ debugmcp: { ...expectedEntry, type: 'streamableHttp', autoApprove, disabled: false, timeout: 180 }
+ }
+ });
+ assert.strictEqual(writes, 1);
+ assert.strictEqual(notifications.length, 1);
+ });
+});
+
suite('AgentConfigurationManager Codex TOML configuration', () => {
const mcpServerUrl = 'http://localhost:3001/mcp';
diff --git a/src/utils/agentConfigurationManager.ts b/src/utils/agentConfigurationManager.ts
index ba12127..531bb08 100644
--- a/src/utils/agentConfigurationManager.ts
+++ b/src/utils/agentConfigurationManager.ts
@@ -347,6 +347,18 @@ export class AgentConfigurationManager {
configFormat: 'json',
mcpServerFieldName: 'mcpServers'
},
+ {
+ id: 'claude-code',
+ name: 'claude-code',
+ displayName: 'Claude Code',
+ // User-scope MCP servers live under the top-level `mcpServers` field of
+ // ~/.claude.json (shared across projects), distinct from the per-project
+ // `projects..mcpServers` entries Claude Code also stores there.
+ // See https://code.claude.com/docs/en/mcp.
+ configPath: path.join(os.homedir(), '.claude.json'),
+ configFormat: 'json',
+ mcpServerFieldName: 'mcpServers'
+ },
{
id: 'codex',
name: 'codex',
@@ -371,6 +383,17 @@ export class AgentConfigurationManager {
};
}
+ if (agent?.id === 'claude-code') {
+ // Claude Code's mcpServers schema only recognizes `type`/`url`/`headers`;
+ // `streamableHttp` (the shape the other JSON agents below use) isn't one of
+ // its accepted type values. Its docs treat `http` and `streamable-http` as
+ // aliases for the same Streamable HTTP transport DebugMCP speaks.
+ return {
+ type: 'http',
+ url: this.getMCPServerUrl()
+ };
+ }
+
return {
autoApprove: [],
disabled: false,
@@ -436,11 +459,11 @@ export class AgentConfigurationManager {
continue; // DebugMCP not configured for this agent
}
- // Check if it's using the old SSE configuration
+ // Claude Code's HTTP transport is current; still migrate legacy SSE endpoints.
const needsMigration = agent.id === 'copilot-cli'
? debugmcpConfig.type !== 'http' || (debugmcpConfig.url && debugmcpConfig.url.endsWith('/sse'))
: debugmcpConfig.type === 'sse' ||
- debugmcpConfig.type === 'http' ||
+ (debugmcpConfig.type === 'http' && agent.id !== 'claude-code') ||
(debugmcpConfig.url && debugmcpConfig.url.endsWith('/sse'));
if (needsMigration) {