This guide covers debugging techniques specific to MCP (Model Context Protocol) servers when using the Copilot SDK for Clojure.
Before diving deep, verify these basics:
- MCP server executable exists and is runnable
- Command path is correct (use absolute paths when in doubt)
- Tools are enabled (
:mcp-tools ["*"]or specific tool names) - Server implements MCP protocol correctly (responds to
initialize) - No firewall blocking the process
Use the client's :log-level :debug to see MCP communication:
(copilot/with-client-session [{:log-level :debug}
session
{:on-permission-request copilot/approve-all
:model "gpt-5.4"
:mcp-servers {"my-server" {:mcp-command "/path/to/server"
:mcp-args []
:mcp-tools ["*"]}}}]
;; Debug output will show MCP initialization and tool calls
(h/query "Use my tools" :session session))You can also add environment variables to enable MCP server-side debugging:
{:mcp-command "/path/to/server"
:mcp-args []
:mcp-tools ["*"]
:env {"MCP_DEBUG" "1"
"DEBUG" "*"
"NODE_DEBUG" "mcp"}} ; For Node.js MCP serversAlways test your MCP server outside the SDK first.
Send an initialize request via stdin:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | /path/to/your/mcp-serverExpected response:
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"your-server","version":"1.0"}}}After initialization, request the tools list:
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | /path/to/your/mcp-serverUse the official MCP Inspector tool:
npx @modelcontextprotocol/inspector /path/to/your/mcp-serverThis provides a web UI to send test requests, view responses, and inspect tool schemas.
Symptoms: No tools appear, no errors in logs.
| Cause | Solution |
|---|---|
| Wrong command path | Use absolute path: /usr/local/bin/server |
| Missing executable permission | chmod +x /path/to/server |
| Missing dependencies | Check with ldd (Linux) or run manually |
| Working directory issues | Set :cwd in config |
Debug by running manually:
cd /expected/working/dir
/path/to/command arg1 arg2-
Tools not enabled:
{:mcp-tools ["*"]} ; Must be ["*"] or list of tool names -
Server doesn't expose tools: Test with
tools/listrequest manually. -
Initialization handshake fails: Server must respond to
initializecorrectly and handlenotifications/initialized.
-
Prompt doesn't clearly need the tool:
;; Too vague {:prompt "What's the weather?"} ;; Better - explicitly mentions capability {:prompt "Use the weather tool to get the current temperature in Seattle"}
-
Tool description unclear:
;; Bad - model doesn't know when to use it {:description "Does a thing"} ;; Good - clear purpose {:description "Get current weather conditions for a city. Returns temperature, humidity, and conditions."}
-
Tool schema issues: Ensure
inputSchemais valid JSON Schema withrequiredfields.
-
Increase timeout:
{:mcp-command "slow-server" :mcp-args [] :mcp-tools ["*"] :mcp-timeout 300000} ; 5 minutes -
Optimize server performance: Add progress logging, check for blocking I/O.
Common causes:
-
Server writes debug output to stdout instead of stderr:
// Wrong - pollutes stdout console.log("Debug info"); // Correct - use stderr console.error("Debug info");
-
Encoding issues: Ensure UTF-8 encoding, no BOM.
-
Message framing: Each message must be a complete JSON object, newline-delimited.
Gatekeeper blocking:
xattr -d com.apple.quarantine /path/to/mcp-serverHomebrew paths: Use full paths when the CLI environment may not have Homebrew in PATH:
{:mcp-command "/opt/homebrew/bin/node"
:mcp-args ["/path/to/server.js"]
:mcp-tools ["*"]}Permission issues:
chmod +x /path/to/mcp-serverMissing shared libraries:
ldd /path/to/mcp-serverCreate a wrapper script to log all communication:
#!/bin/bash
# mcp-debug-wrapper.sh
LOG="/tmp/mcp-debug-$(date +%s).log"
echo "=== MCP Debug Session ===" >> "$LOG"
tee -a "$LOG" | "$1" "${@:2}" 2>> "$LOG" | tee -a "$LOG"Use it:
{:mcp-command "/path/to/mcp-debug-wrapper.sh"
:mcp-args ["/actual/server/path" "arg1" "arg2"]
:mcp-tools ["*"]}Subscribe to tool execution events to observe MCP tool calls:
(require '[clojure.core.async :refer [chan tap go-loop <!]])
(copilot/with-client-session [session {:on-permission-request copilot/approve-all
:model "gpt-5.4"
:mcp-servers {"my-server" {:mcp-command "server"
:mcp-args []
:mcp-tools ["*"]}}}]
(let [ch (chan 256)]
(tap (copilot/events session) ch)
(go-loop []
(when-let [event (<! ch)]
(case (:type event)
:copilot/tool.execution_start
(println "MCP tool called:" (get-in event [:data :tool-name])
"args:" (get-in event [:data :arguments]))
:copilot/tool.execution_complete
(println "MCP tool completed:" (get-in event [:data :tool-call-id])
"success:" (get-in event [:data :success?]))
nil)
(recur)))
(copilot/send-and-wait! session {:prompt "Use my tools"})))When opening an issue or asking for help, collect:
- SDK version (check
deps.ednorpom.xml) - CLI version (
copilot --version) - MCP server type (Node.js, Python, Go, etc.)
- Full MCP server configuration (redact secrets)
- Result of manual
initializetest - Result of manual
tools/listtest - Debug logs from SDK (
:log-level :debug) - Any error messages
- MCP Overview — Configuration and setup
- MCP Specification — Official protocol docs
- MCP Servers Directory — Community MCP servers