DEV Community

Shirley Mali
Shirley Mali

Posted on

Fixing "MCP burp: Couldn't start for Cowork and Code sessions. Error: Connection closed" in Claude Desktop

If you've connected Burp Suite's MCP server to Claude Desktop on macOS and hit this error:

MCP burp: Couldn't start for Cowork and Code sessions. Error: Connection closed

...and Burp itself seems to be running fine, this post walks through exactly how to diagnose and fix it. The root cause turned out to be a macOS security feature most people have never heard of, so even if you're new to debugging this kind of thing, you should be able to follow along.

The setup

Burp Suite ships with its own MCP Server feature (Settings → look for the "Burp MCP Server" panel), which exposes Burp's tooling — like sending requests through Repeater or reading proxy history — to AI clients like Claude Desktop.

When it's working, you get a nice "running" badge in Claude Desktop's MCP settings. When it's not, you get this instead:

Not a lot to go on. Let's dig in.

Step 1: Confirm Burp's MCP server is actually running

Before touching Claude Desktop's config, check that Burp itself has something listening. Burp's MCP server settings panel shows the host and port it's bound to (defaults are 127.0.0.1:9876):

Confirm something is actually listening on that port:

lsof -i :9876
Enter fullscreen mode Exit fullscreen mode

If you see a Java process (Burp itself runs on the JVM) in LISTEN state, Burp's side is fine. That was true in my case, so the problem was somewhere between Burp and Claude Desktop, not in Burp itself.

Step 2: Look at what Claude Desktop is actually trying to run

Claude Desktop's MCP servers are defined in a config file. On macOS:

cat ~/Library/Application\ Support/Claude/claude_desktop_config.json
Enter fullscreen mode Exit fullscreen mode

The relevant part looked like this:

{
  "mcpServers": {
    "burp": {
      "command": "/Applications/Burp Suite.app/Contents/Resources/jre.bundle/Contents/Home/bin/java",
      "args": [
        "-jar",
        "/Users/YOURUSER/.BurpSuite/mcp-proxy/mcp-proxy-all.jar",
        "--sse-url",
        "http://127.0.0.1:9876"
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

So Claude Desktop spawns a small Java "bridge" process (mcp-proxy-all.jar) that translates MCP's protocol into calls against Burp's --sse-url endpoint. That jar gets generated by Burp's "Extract server proxy jar" button and the whole entry gets written automatically when you click "Install to Claude Desktop" in Burp's MCP panel.

Both files existed and had sane permissions, so nothing looked obviously wrong yet.

Step 3: Run the exact command by hand

This is the single most useful debugging step here: don't trust the vague error in Claude Desktop's UI. Copy the command and args out of the config and run them yourself in a terminal:

"/Applications/Burp Suite.app/Contents/Resources/jre.bundle/Contents/Home/bin/java" \
  -jar "/Users/YOURUSER/.BurpSuite/mcp-proxy/mcp-proxy-all.jar" \
  --sse-url "http://127.0.0.1:9876"
Enter fullscreen mode Exit fullscreen mode

Result:

zsh: killed      -jar "/Users/YOURUSER/.BurpSuite/mcp-proxy/mcp-proxy-all.jar" --sse-url
Enter fullscreen mode Exit fullscreen mode

"Killed" with zero output is a big clue. Real Java errors (bad jar, wrong version, missing class) almost always print something before dying — a stack trace, an exception message, at least a JVM startup banner if things get far enough. Getting nothing at all means something external terminated the process before Java could even complain.

Step 4: Get the exit code

"/Applications/Burp Suite.app/Contents/Resources/jre.bundle/Contents/Home/bin/java" \
  -jar "/Users/YOURUSER/.BurpSuite/mcp-proxy/mcp-proxy-all.jar" \
  --sse-url "http://127.0.0.1:9876"
echo $?
Enter fullscreen mode Exit fullscreen mode
137
Enter fullscreen mode Exit fullscreen mode

Exit code 137 = 128 + 9, which means the process received signal 9 (SIGKILL). Something outside the JVM killed it outright. That rules out a normal application crash and points at either:

  • macOS Gatekeeper / code-signing enforcement, or
  • the kernel's out-of-memory killer, or
  • an architecture mismatch (Intel binary on Apple Silicon or vice versa)

Step 5: Rule out the easy stuff

Architecture check — make sure the Java binary matches your Mac's CPU:

file "/Applications/Burp Suite.app/Contents/Resources/jre.bundle/Contents/Home/bin/java"
uname -m
Enter fullscreen mode Exit fullscreen mode

Both came back arm64, so that wasn't it.

Quarantine flag — freshly extracted files sometimes get tagged by macOS and blocked:

xattr -l /Users/YOURUSER/.BurpSuite/mcp-proxy/mcp-proxy-all.jar
Enter fullscreen mode Exit fullscreen mode

Empty output, no quarantine flag either.

Sandbox / AMFI logs — checked for an obvious denial in the unified log:

log show --last 3m --predicate 'process == "java" OR process == "amfid" OR process == "taskgated"' --debug
Enter fullscreen mode Exit fullscreen mode

Zero matching entries. This was actually the most important negative result: it meant the kill wasn't coming from the usual Gatekeeper/AMFI path that shows up under those process names.

Step 6: Find the real reason with codesign

This is the step that cracked it. Instead of just checking if the binary is signed, dump full verbose signing info, including launch constraints:

codesign -dv --verbose=4 "/Applications/Burp Suite.app/Contents/Resources/jre.bundle/Contents/Home/bin/java"
Enter fullscreen mode Exit fullscreen mode

Buried in the output:

Launch Constraints:
    Has Parent Launch Constraints
    [Dict]
        [Key] team-identifier
        [Value]
            [String] N82YM748DZ
Enter fullscreen mode Exit fullscreen mode

That team identifier belongs to PortSwigger (Burp's vendor). This Java binary has a macOS Launch Constraint that only allows it to run when its parent process is also signed by PortSwigger.

Launch Constraints are a relatively recent macOS security feature (introduced in macOS Sonoma) that some vendors apply to binaries bundled inside their apps, specifically to stop those binaries being launched by anything else. It's meant to prevent a bundled runtime from being hijacked and reused outside its intended app.

That explains everything:

  • Running it from Terminal → parent process is zsh, not PortSwigger-signed → instant SIGKILL.
  • Running it from Claude Desktop as an MCP subprocess → parent process is Claude, not PortSwigger-signed → same instant SIGKILL.
  • No output, because the kernel kills it before Java even starts executing.
  • No Gatekeeper/AMFI log entries, because Launch Constraint enforcement happens at a different layer (launchd/kernel) than the usual code-signing checks those tools log under.

The fix

Don't use Burp's bundled, constrained JRE to run the bridge jar. Point Claude Desktop at a regular, unconstrained system Java install instead — the jar itself has no such restriction, only Burp's bundled java binary does.

Check what you already have installed:

which java
/usr/libexec/java_home -V
Enter fullscreen mode Exit fullscreen mode

If you don't have one, install one, e.g. with Homebrew:

brew install openjdk
Enter fullscreen mode Exit fullscreen mode

Then update the command field in claude_desktop_config.json for the burp entry to point at that system Java instead of Burp's bundled one, keeping everything else the same:

{
  "mcpServers": {
    "burp": {
      "command": "/Library/Java/JavaVirtualMachines/temurin-26.jdk/Contents/Home/bin/java",
      "args": [
        "-jar",
        "/Users/YOURUSER/.BurpSuite/mcp-proxy/mcp-proxy-all.jar",
        "--sse-url",
        "http://127.0.0.1:9876"
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

(Substitute whichever JVM path /usr/libexec/java_home -V listed for you.)

Fully quit Claude Desktop (Cmd+Q, not just closing the window) and relaunch it. Check Settings → Local MCP servers:

Running, no more "Connection closed" error.

Summary

Symptom Cause
"Connection closed" in Claude Desktop MCP bridge subprocess dying silently
zsh: killed, exit code 137, zero JVM output Process was SIGKILL'd externally
No Gatekeeper/AMFI log entries Kill happened via a Launch Constraint, not standard code-signing checks
codesign -dv --verbose=4 shows Has Parent Launch Constraints with a vendor team ID The binary refuses to run under any parent process not signed by that vendor
Fix Run the same jar with a different, unconstrained JVM (system Java instead of the app-bundled one)

If you're debugging something similar with any app that bundles its own JRE, codesign -dv --verbose=4 <path-to-java> and checking for Launch Constraints is worth doing early. An instant SIGKILL (exit 137) with no application-level error output is the telltale sign you're dealing with an OS-level restriction, not a bug in the app itself.


Environment: macOS, Apple Silicon (arm64), Burp Suite, Claude Desktop.

Top comments (0)