Table of contents

How do I Troubleshoot MCP Server Connection Issues?

Troubleshooting MCP (Model Context Protocol) server connection issues requires a systematic approach to identify and resolve problems in the client-server communication pipeline. Connection failures can stem from configuration errors, network issues, authentication problems, or bugs in server implementation. This guide provides comprehensive troubleshooting techniques to diagnose and fix common MCP server connectivity problems.

Understanding MCP Connection Flow

Before troubleshooting, it's important to understand the MCP connection lifecycle:

  1. Server Discovery: The MCP client reads configuration to locate available servers
  2. Transport Initialization: Connection established via stdio, HTTP/SSE, or WebSocket
  3. Protocol Handshake: Client and server exchange initialization messages
  4. Capability Negotiation: Both parties agree on supported features
  5. Ready State: Server is ready to accept requests

Connection issues can occur at any of these stages, and identifying the failure point is crucial for effective troubleshooting.

Common Connection Issues and Solutions

1. Server Process Not Starting

Symptoms: No response from server, timeout errors, or immediate connection failure.

Diagnosis:

Check if the server process is actually starting:

# For Node.js MCP servers
ps aux | grep node | grep mcp

# For Python MCP servers
ps aux | grep python | grep mcp

# Check system logs
tail -f /var/log/system.log  # macOS
journalctl -f  # Linux

Solutions:

Verify the command path in your MCP configuration:

{
  "mcpServers": {
    "web-scraper": {
      "command": "/usr/local/bin/node",  // Use absolute path
      "args": ["/full/path/to/server.js"],
      "env": {
        "NODE_ENV": "production"
      }
    }
  }
}

Test server startup manually:

# Node.js
node /path/to/server.js

# Python
python -m your_mcp_server

# Check for syntax errors or missing dependencies
node --check server.js
python -m py_compile server.py

Add execution permissions if needed:

chmod +x /path/to/server.js
chmod +x /path/to/server.py

2. Stdio Transport Issues

Symptoms: Server starts but doesn't respond to requests, hangs indefinitely.

Diagnosis:

Stdio transport uses standard input/output streams. Issues often arise from: - Logging to stdout instead of stderr - Buffering problems - Encoding issues

Solutions:

Ensure all logging goes to stderr, not stdout:

// WRONG - This breaks stdio communication
console.log("Debug message");

// CORRECT - Use stderr for logging
console.error("Debug message");

In Python:

import sys

# WRONG
print("Debug message")

# CORRECT
print("Debug message", file=sys.stderr)

# Or use logging module
import logging
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    stream=sys.stderr  # Important: log to stderr
)

Set unbuffered I/O for immediate communication:

{
  "mcpServers": {
    "scraper": {
      "command": "python",
      "args": ["-u", "-m", "mcp_server"],  // -u for unbuffered
      "env": {
        "PYTHONUNBUFFERED": "1"
      }
    }
  }
}

3. HTTP/SSE Transport Connection Failures

Symptoms: Connection timeouts, 404 errors, CORS issues, or SSL/TLS errors.

Diagnosis:

Test the HTTP endpoint directly:

# Check if server is listening
curl -v http://localhost:3000/mcp

# Test SSE endpoint
curl -N -H "Accept: text/event-stream" http://localhost:3000/mcp/sse

# Check SSL certificate
openssl s_client -connect scraper.example.com:443 -servername scraper.example.com

Solutions:

Verify server URL and port:

{
  "mcpServers": {
    "remote-scraper": {
      "url": "https://scraper.example.com/mcp",
      "transport": "sse",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN"
      }
    }
  }
}

Enable CORS on the server side:

import express from 'express';
import cors from 'cors';

const app = express();

app.use(cors({
  origin: ['https://claude.ai', 'http://localhost:3000'],
  methods: ['GET', 'POST', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

app.post('/mcp', async (req, res) => {
  // Handle MCP requests
});

Fix SSL certificate issues:

# For self-signed certificates (development only)
export NODE_TLS_REJECT_UNAUTHORIZED=0

# Better: Install proper certificate
sudo cp custom-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates

4. Authentication and Authorization Failures

Symptoms: 401 Unauthorized, 403 Forbidden errors.

Diagnosis:

Check authentication headers and credentials:

# Test with authentication
curl -H "Authorization: Bearer YOUR_TOKEN" \
     -H "Content-Type: application/json" \
     http://localhost:3000/mcp

# Check token expiration
jwt decode YOUR_TOKEN  # If using JWT

Solutions:

Implement proper authentication in server:

from mcp.server import Server
from functools import wraps
import os

def require_auth(f):
    @wraps(f)
    async def decorated_function(*args, **kwargs):
        auth_token = os.environ.get('MCP_AUTH_TOKEN')
        # Validate token here
        if not auth_token:
            raise ValueError("Authentication required")
        return await f(*args, **kwargs)
    return decorated_function

@app.call_tool()
@require_auth
async def call_tool(name: str, arguments: dict):
    # Tool implementation
    pass

Set environment variables in configuration:

{
  "mcpServers": {
    "secure-scraper": {
      "command": "node",
      "args": ["server.js"],
      "env": {
        "MCP_AUTH_TOKEN": "your-secret-token",
        "API_KEY": "your-api-key"
      }
    }
  }
}

5. Version Compatibility Issues

Symptoms: Protocol errors, unexpected message formats, capability negotiation failures.

Diagnosis:

Check MCP SDK versions:

# Node.js
npm list @modelcontextprotocol/sdk

# Python
pip show mcp

# Check for updates
npm outdated
pip list --outdated

Solutions:

Update to compatible versions:

# Node.js
npm install @modelcontextprotocol/sdk@latest

# Python
pip install --upgrade mcp

Specify protocol version explicitly:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";

const server = new Server(
  {
    name: "web-scraper",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
      resources: {},
      prompts: {}
    },
    protocolVersion: "2024-11-05"  // Specify version
  }
);

Advanced Debugging Techniques

Enable Verbose Logging

Implement comprehensive logging in your MCP server, similar to monitoring network requests in Puppeteer:

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import winston from 'winston';

// Create logger
const logger = winston.createLogger({
  level: 'debug',
  format: winston.format.combine(
    winston.format.timestamp(),
    winston.format.json()
  ),
  transports: [
    new winston.transports.File({ filename: 'mcp-server.log' }),
    new winston.transports.Console({ level: 'error' })  // stderr only
  ]
});

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

// Log all requests
server.setRequestHandler("tools/call", async (request) => {
  logger.info('Tool call received', {
    tool: request.params.name,
    arguments: request.params.arguments
  });

  try {
    const result = await executeTool(request.params);
    logger.info('Tool call successful', { tool: request.params.name });
    return result;
  } catch (error) {
    logger.error('Tool call failed', {
      tool: request.params.name,
      error: error.message,
      stack: error.stack
    });
    throw error;
  }
});

Python logging setup:

import logging
from mcp.server import Server
import sys

# Configure logging
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('mcp-server.log'),
        logging.StreamHandler(sys.stderr)
    ]
)

logger = logging.getLogger(__name__)

app = Server("web-scraper")

@app.call_tool()
async def call_tool(name: str, arguments: dict):
    logger.info(f"Tool call: {name} with args: {arguments}")

    try:
        result = await execute_tool(name, arguments)
        logger.info(f"Tool call successful: {name}")
        return result
    except Exception as e:
        logger.error(f"Tool call failed: {name}", exc_info=True)
        raise

Use MCP Inspector for Testing

The MCP Inspector is an invaluable debugging tool:

# Install MCP Inspector
npm install -g @modelcontextprotocol/inspector

# Run your server with inspector
npx @modelcontextprotocol/inspector node server.js

# For Python servers
npx @modelcontextprotocol/inspector python -m your_mcp_server

The inspector provides: - Real-time message inspection - Tool testing interface - Resource browsing - Error visualization

Network-Level Debugging

For HTTP/SSE transports, use network analysis tools:

# Monitor HTTP traffic
tcpdump -i any -A port 3000

# Use mitmproxy for detailed HTTP inspection
mitmproxy --mode reverse:http://localhost:3000

# Check network connectivity
netstat -an | grep 3000
lsof -i :3000

Timeout Configuration

Adjust timeouts to prevent premature failures, especially when dealing with handling timeouts in Puppeteer:

import axios from 'axios';

// Set appropriate timeouts
const client = axios.create({
  timeout: 30000,  // 30 seconds
  validateStatus: (status) => status < 500
});

// Implement retry logic
async function callWithRetry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === maxRetries - 1) throw error;

      const delay = Math.min(1000 * Math.pow(2, i), 10000);
      logger.warn(`Retry ${i + 1}/${maxRetries} after ${delay}ms`, {
        error: error.message
      });

      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

Troubleshooting Checklist

When facing connection issues, work through this systematic checklist:

Configuration Validation

  • [ ] Verify MCP server configuration file path and syntax
  • [ ] Check command paths are absolute and executable
  • [ ] Confirm environment variables are set correctly
  • [ ] Validate JSON syntax (no trailing commas, proper quotes)

Server Health

  • [ ] Test server starts independently outside MCP
  • [ ] Check server logs for startup errors
  • [ ] Verify all dependencies are installed
  • [ ] Confirm correct SDK version compatibility

Network and Transport

  • [ ] Test network connectivity to remote servers
  • [ ] Verify firewall rules allow connections
  • [ ] Check SSL/TLS certificates are valid
  • [ ] Confirm correct transport type (stdio, HTTP, SSE)

Authentication

  • [ ] Verify API keys and tokens are current
  • [ ] Check authorization headers are correct
  • [ ] Confirm credentials have necessary permissions
  • [ ] Test authentication independently

Protocol Communication

  • [ ] Enable debug logging in both client and server
  • [ ] Use MCP Inspector to test tools directly
  • [ ] Verify message format matches protocol specification
  • [ ] Check for encoding issues in stdio transport

Error Messages and Solutions

"Server not responding"

# Check if process is running
ps aux | grep your-mcp-server

# Restart server with verbose logging
DEBUG=* node server.js 2>&1 | tee server.log

# Check for port conflicts
lsof -i :PORT_NUMBER

"Transport error: connection refused"

# Verify server is listening
netstat -an | grep LISTEN

# Check firewall rules
sudo iptables -L -n  # Linux
pfctl -s rules  # macOS

# Test local connectivity
telnet localhost PORT

"Protocol handshake failed"

Update both client and server to compatible versions, ensure proper initialization:

// Ensure proper server initialization
const server = new Server(
  {
    name: "scraper",
    version: "1.0.0"
  },
  {
    capabilities: {
      tools: {},
      resources: {}
    }
  }
);

// Proper transport setup
const transport = new StdioServerTransport();
await server.connect(transport);

"Tool execution timeout"

Implement proper timeout handling:

import asyncio

async def execute_with_timeout(coro, timeout_seconds=30):
    try:
        return await asyncio.wait_for(coro, timeout=timeout_seconds)
    except asyncio.TimeoutError:
        logger.error(f"Operation timed out after {timeout_seconds}s")
        raise TimeoutError(f"Operation exceeded {timeout_seconds}s limit")

Best Practices for Reliable Connections

  1. Graceful Shutdown: Implement proper cleanup on server shutdown
process.on('SIGINT', async () => {
  logger.info('Shutting down gracefully...');
  await cleanup();
  process.exit(0);
});
  1. Health Checks: Add server health monitoring
@app.list_resources()
async def list_resources():
    return [
        {
            "uri": "health://status",
            "name": "Server Health",
            "mimeType": "application/json",
            "description": "Server health status"
        }
    ]
  1. Connection Pooling: Reuse connections for efficiency
import { Pool } from 'pg';

const pool = new Pool({
  max: 20,
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
});
  1. Error Recovery: Implement automatic reconnection logic
class ResilientMCPClient {
  constructor(config) {
    this.config = config;
    this.maxRetries = 5;
  }

  async connect() {
    for (let i = 0; i < this.maxRetries; i++) {
      try {
        await this.establishConnection();
        return;
      } catch (error) {
        if (i === this.maxRetries - 1) throw error;
        await this.sleep(1000 * Math.pow(2, i));
      }
    }
  }
}

Debugging Tools and Resources

Essential Tools

  1. MCP Inspector: Visual debugging interface
  2. cURL: Test HTTP endpoints
  3. Wireshark: Deep packet inspection
  4. tcpdump: Network traffic analysis
  5. strace/dtrace: System call tracing

Useful Commands

# Trace system calls (Linux)
strace -f -e trace=network node server.js

# Trace system calls (macOS)
sudo dtruss -f node server.js

# Monitor file descriptors
lsof -p $(pgrep -f "node server.js")

# Real-time log monitoring
tail -f mcp-server.log | grep -i error

Conclusion

Troubleshooting MCP server connection issues requires understanding the protocol architecture, systematic diagnosis, and appropriate debugging tools. Start with basic checks like server startup and configuration validation, then progress to more advanced techniques like network analysis and protocol-level debugging.

Most connection issues fall into a few categories: configuration errors, network problems, authentication failures, or version incompatibilities. By following the systematic approach outlined in this guide, using proper logging, and leveraging tools like MCP Inspector, you can quickly identify and resolve most connection problems.

Remember to implement robust error handling, timeout management, and retry logic in your production MCP servers to minimize connection issues. With proper monitoring and proactive debugging, you can maintain reliable MCP server connections for your web scraping and automation workflows.

Try WebScraping.AI for Your Web Scraping Needs

Looking for a powerful web scraping solution? WebScraping.AI provides an LLM-powered API that combines Chromium JavaScript rendering with rotating proxies for reliable data extraction.

Key Features:

  • AI-powered extraction: Ask questions about web pages or extract structured data fields
  • JavaScript rendering: Full Chromium browser support for dynamic content
  • Rotating proxies: Datacenter and residential proxies from multiple countries
  • Easy integration: Simple REST API with SDKs for Python, Ruby, PHP, and more
  • Reliable & scalable: Built for developers who need consistent results

Getting Started:

Get page content with AI analysis:

curl "https://api.webscraping.ai/ai/question?url=https://example.com&question=What is the main topic?&api_key=YOUR_API_KEY"

Extract structured data:

curl "https://api.webscraping.ai/ai/fields?url=https://example.com&fields[title]=Page title&fields[price]=Product price&api_key=YOUR_API_KEY"

Try in request builder

Related Questions

Get Started Now

WebScraping.AI provides rotating proxies, Chromium rendering and built-in HTML parser for web scraping
Icon