Claude Desktop / Claude Code setup

This page covers the actual config files for plugging an mcp-tkx server into the two main Anthropic clients. Both clients support STDIO; Claude Code also supports SSE (Claude Desktop does not, as of November 2025).

Claude Desktop (STDIO)

Config file location

OSPath
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json
Linux~/.config/Claude/claude_desktop_config.json

Direct invocation via clojure -X

For the example STDIO server in this repo:

{
  "mcpServers": {
    "toolkit": {
      "command": "/bin/sh",
      "args": [
        "-c",
        "cd /path/to/mcp-tkx/example/cljc-server-stdio && clojure -X:mcp-server"
      ]
    }
  }
}

For your own server, replace the path and the alias:

{
  "mcpServers": {
    "my-server": {
      "command": "/bin/sh",
      "args": [
        "-c",
        "cd /path/to/your/project && clojure -X:mcp-server"
      ]
    }
  }
}

The /bin/sh -c "cd ... && ..." wrapper is the most reliable way to set the working directory before launch. On Windows, use cmd.exe /c instead, or use cwd (some Claude Desktop builds support it; older builds don't).

After saving the config, restart Claude Desktop (quit fully, File → Quit on macOS, not just close the window). On launch, the hammer icon (or "Connect apps" button) shows your server.

Direct invocation via bb

If you have Babashka installed and a bb mcp (or similar) task in your bb.edn:

{
  "mcpServers": {
    "my-server": {
      "command": "/bin/sh",
      "args": [
        "-c",
        "cd /path/to/your/project && bb mcp"
      ]
    }
  }
}

bb startup is ~50ms, JVM Clojure cold start is ~3–5s. If your server doesn't need to run on the JVM (e.g. a thin proxy), bb is the faster option. Most Clojure servers, including this fork's example, use the JVM and accept the cold-start cost; the server stays alive for the duration of the Claude Desktop session.

Docker-based server config

The repo ships a docker-compose.yml and Dockerfile for running the example server in a container. This isolates JVM dependencies but adds startup latency:

{
  "mcpServers": {
    "toolkit": {
      "command": "/bin/sh",
      "args": [
        "-c",
        "cd /path/to/mcp-tkx && docker-compose run --service-ports --rm mcp-server clojure -X:mcp-server '{:bind \"0.0.0.0\"}'"
      ]
    }
  }
}

Important: build the image first (docker-compose build) before pointing Claude Desktop at it. Otherwise the build output (Maven downloads, Docker layer pulls) gets sent to Claude Desktop as JSON-RPC and breaks the connection.

Tailing logs

Claude Desktop writes one log file per MCP server, named after the key in mcpServers:

# macOS, replace "toolkit" with your server name
tail -n 200 -F ~/Library/Logs/Claude/mcp-server-toolkit.log

# Windows
type %APPDATA%\Claude\Logs\mcp-server-toolkit.log

# Linux
tail -n 200 -F ~/.config/Claude/Logs/mcp-server-toolkit.log

The log captures the server's stderr plus a record of the JSON-RPC traffic. The toolkit's example server logs to stderr (via the embedded nREPL banner and any user println to *err*); stdout is reserved for JSON-RPC.

If the log shows JSON-RPC parse errors at startup, your server is probably writing non-JSON to stdout (a startup banner, a println, a build artefact). Move it to stderr, (.println System/err "..."), or remove it.

Claude Code (CLI)

Claude Code reads two config files: project-level .mcp.json (commit this so teammates inherit) and global ~/.claude.json.

Project-level .mcp.json

{
  "mcpServers": {
    "my-server": {
      "command": "clj",
      "args": ["-X:mcp-server"],
      "cwd": "${workspaceFolder}"
    }
  }
}

${workspaceFolder} expands to the repo root. cwd is reliable in Claude Code (unlike older Claude Desktop builds).

Global via claude mcp add

# Add for the current project
claude mcp add my-server -- clj -X:mcp-server

# List
claude mcp list

# Show config for one server
claude mcp get my-server

# Remove
claude mcp remove my-server

Claude Code via SSE

This fork's example SSE server (example/clj-server-sse/) listens on :7925. Start it first:

cd example/clj-server-sse
clojure -X:mcp-server
# Server logs:
# Listening on http://127.0.0.1:7925

Then register with Claude Code:

claude mcp add toolkit-sse --transport sse http://127.0.0.1:7925/sse

Make sure the server is running before starting Claude Code; the SSE transport requires the server to be live for the connection to establish.

Claude Desktop does not currently support SSE (as of the 2025-11-25 spec release). Use STDIO for Claude Desktop and SSE for Claude Code if you need both.

The SSE example uses the older 2024-11-05 SSE transport. For the current 2025-03-26+ transport, use the clj-server-streamable-http example (single /mcp endpoint, Mcp-Session-Id sessions, Last-Event-Id resumability), see the Streamable HTTP transport guide. Register it with Claude Code via:

claude mcp add toolkit-http --transport http http://127.0.0.1:7926/mcp

MCP Inspector, for development

@modelcontextprotocol/inspector is the browser-based dev tool for driving any MCP server:

# STDIO
npx @modelcontextprotocol/inspector clojure -X:mcp-server

# Or for the cljs / Node example
npx @modelcontextprotocol/inspector node out/node-server.js

# For SSE, open the inspector and configure manually
npx @modelcontextprotocol/inspector
# In the UI: Transport Type → SSE; URL → http://127.0.0.1:7925/sse

The Inspector shows the prompt list, resource list, tool list, and lets you call tools / read resources interactively. It's the fastest way to validate a server before wiring it into Claude.

Multi-server setup

Claude Desktop / Claude Code support multiple servers concurrently. Each entry under mcpServers is a separate process:

{
  "mcpServers": {
    "spock": {
      "command": "clj",
      "args": ["-M:spock-mcp"],
      "cwd": "/path/to/spock"
    },
    "toolkit": {
      "command": "clj",
      "args": ["-X:mcp-server"],
      "cwd": "/path/to/mcp-tkx/example/cljc-server-stdio"
    },
    "ts-mcp": {
      "command": "node",
      "args": ["/path/to/ts-mcp/dist/index.js"]
    }
  }
}

The client merges tool / prompt / resource lists from all connected servers. Tool names should be globally unique; if two servers register the same tool name, behaviour is client-dependent (Claude Desktop disambiguates with a server prefix in the UI; Claude Code may pick one).

Troubleshooting checklist

  • Tool list not showing up: Click "Connect apps" in Claude Desktop's UI to force a refresh. The first-load delay can be 5–15 seconds depending on JVM cold-start.
  • Server starts then immediately exits: Check the log file. The most common cause is the server writing JSON to a non-stdout stream, or writing non-JSON to stdout.
  • Claude Code SSE connection refused: Start the server before starting Claude Code. SSE requires the server to be live at registration time AND at connection time.
  • Different behaviour between MCP Inspector and Claude Desktop: Inspector negotiates the latest version (2025-11-25); Claude Desktop may negotiate down. Check (:protocol-version @session) in the running server to see what was actually negotiated.
  • clojure: command not found in Claude Desktop logs: Claude Desktop launches the server with a minimal PATH on macOS. Wrap the command with the absolute path: "command": "/opt/homebrew/bin/clojure" or use the /bin/sh -c "cd ... && clojure ..." form which inherits the user shell's PATH.

See also