Tutorial

Configure Multiple MCP Servers - Run 5-10+ Servers Simultaneously

Learn how to configure and run multiple MCP servers simultaneously. Covers config examples, naming conventions, port management, and memory optimization.

Why Run Multiple MCP Servers?

The real power of the Model Context Protocol emerges when you combine multiple specialized servers. Instead of one monolithic server that does everything, the MCP ecosystem encourages small, focused servers - one for database access, one for file operations, one for web search, one for Git, and so on. Running 5-10 servers simultaneously gives your AI assistant a rich toolkit that covers most development workflows.

This guide walks you through configuring multiple servers across Claude Desktop, Cursor, and VS Code, with full 10-server config examples for each client. You will learn server naming conventions, how to avoid port and naming conflicts, manage memory across many servers, and control startup order. For guidance on how many servers your system can handle, see our how many MCP servers can you run guide.

Claude Desktop - Full 10-Server Configuration

Claude Desktop uses a JSON configuration file to define MCP servers. Each server gets a unique key in the mcpServers object. Here is a production-ready config with 10 servers covering a full-stack development workflow:

{
  "mcpServers": {
    "filesystem": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/projects"],
      "env": {}
    },
    "github": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
      }
    },
    "postgres": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "POSTGRES_URL": "postgresql://user:pass@localhost:5432/mydb"
      }
    },
    "memory": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-memory"],
      "env": {
        "MEMORY_FILE_PATH": "/Users/you/memory/claude-memory.json"
      }
    },
    "brave-search": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "BSAxxxxxxxxxx"
      }
    },
    "puppeteer": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-puppeteer"]
    },
    "sqlite": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-sqlite", "/Users/you/projects/data/app.db"]
    },
    "sequential-thinking": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
    },
    "slack": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@anthropic/mcp-server-slack"],
      "env": {
        "SLACK_BOT_TOKEN": "xoxb-xxxxxxxxxxxx"
      }
    },
    "fetch": {
      "command": "/usr/local/bin/npx",
      "args": ["-y", "@modelcontextprotocol/server-fetch"]
    }
  }
}

Config file location: On macOS: ~/Library/Application Support/Claude/claude_desktop_config.json. On Windows: %APPDATA%\Claude\claude_desktop_config.json. On Linux: ~/.config/Claude/claude_desktop_config.json. Note the use of absolute paths for npx - this prevents ENOENT errors since GUI apps do not inherit shell PATH.

Cursor - Full 10-Server Configuration

Cursor supports both project-level (.cursor/mcp.json) and global (~/.cursor/mcp.json) configs. Here is a 10-server project config for a full-stack web application:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx"
      }
    },
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "POSTGRES_URL": "postgresql://user:pass@localhost:5432/mydb"
      }
    },
    "memory": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-memory"],
      "env": {
        "MEMORY_FILE_PATH": "./memory/project-memory.json"
      }
    },
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "BSAxxxxxxxxxx"
      }
    },
    "puppeteer": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-puppeteer"]
    },
    "sqlite": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sqlite", "./data/app.db"]
    },
    "sequential-thinking": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
    },
    "fetch": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-fetch"]
    },
    "redis": {
      "command": "npx",
      "args": ["-y", "mcp-server-redis"],
      "env": {
        "REDIS_URL": "redis://localhost:6379"
      }
    }
  }
}

In Cursor, navigate to Settings, MCP to manage servers through the UI, or edit the config file directly at .cursor/mcp.json in your project root. Cursor's advantage over Claude Desktop is per-server restart - you can restart a single server without reloading the entire editor. See the Cursor MCP guide for troubleshooting.

VS Code - Full 10-Server Configuration

VS Code configures MCP servers in .vscode/mcp.json (project-level) or settings.json (global). VS Code supports variable substitution for secrets with ${input:name}:

// .vscode/mcp.json
{
  "servers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "${workspaceFolder}"]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}"
      }
    },
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "POSTGRES_URL": "${input:postgres_url}"
      }
    },
    "memory": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-memory"]
    },
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "${input:brave_key}"
      }
    },
    "puppeteer": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-puppeteer"]
    },
    "sqlite": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sqlite", "${workspaceFolder}/data/app.db"]
    },
    "sequential-thinking": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
    },
    "fetch": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-fetch"]
    },
    "slack": {
      "command": "npx",
      "args": ["-y", "@anthropic/mcp-server-slack"],
      "env": {
        "SLACK_BOT_TOKEN": "${input:slack_token}"
      }
    }
  }
}

Server Naming Conventions

Consistent naming makes your config readable, prevents conflicts, and helps the AI select the right tool. Follow these conventions:

Pattern Example When to Use
Service name postgres, github, slack One server per service type
Service-environment postgres-dev, postgres-staging, postgres-prod Multiple instances of same service
Purpose-based web-search, code-analysis, email-sender Custom servers with specific function
Project-scoped myapp-db, frontend-browser Project-specific configs with potential global overlap

Rules: Use lowercase kebab-case. Keep names to 1-3 words. Avoid generic names like server1 or my-server. The server name appears in AI tool calls, so make it descriptive enough that the AI can determine which server handles which task.

Conflict Resolution

When the same server name appears in multiple config files (global vs project), different clients handle the conflict differently:

Client Conflict Behavior Recommendation
Claude Desktop Global only (no project config) No conflict possible
Cursor Project config takes precedence Use unique names or rely on precedence
VS Code Project config merges with user settings Use unique names per scope

To avoid conflicts entirely, use environment-qualified names for servers that vary between projects (myapp-postgres) and plain names for universally-configured servers (memory, brave-search).

Avoiding Port Conflicts

Most MCP servers use stdio transport (communication over stdin/stdout), which means they do not need network ports at all. Port conflicts only arise when using Streamable HTTP transport or when servers themselves need to bind to ports (for example, Puppeteer's Chrome debugging port).

If you run multiple servers that do need ports, assign explicit port numbers in your config and maintain a registry:

{
  "mcpServers": {
    "puppeteer-main": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-puppeteer"],
      "env": {
        "PUPPETEER_CHROME_PORT": "9222"
      }
    },
    "custom-api": {
      "command": "node",
      "args": ["api-server.js", "--port", "3100"]
    },
    "custom-dashboard": {
      "command": "node",
      "args": ["dashboard-server.js", "--port", "3101"]
    }
  }
}

Memory Management

Each MCP server runs as a separate process, consuming memory independently. A typical Node.js MCP server uses 30-80 MB of RAM at idle, and heavy servers like Puppeteer use 120-300 MB. With 10 servers, expect 400-800 MB total memory usage. See the how many servers guide for detailed memory benchmarks per server.

Strategies for managing memory with many servers:

  • Monitor usage: Run ps aux | grep -E "(mcp|server-)" | awk '{sum += $6} END {print sum/1024 " MB"}' to check total MCP memory usage.
  • Set Node.js memory limits: Add "env": { "NODE_OPTIONS": "--max-old-space-size=64" } to constrain individual servers to 64 MB.
  • Use project-scoped configs: Only load servers relevant to the current project. A web project does not need the Slack server, and a data project does not need Puppeteer.
  • Pre-install packages: Using npm install -g instead of npx -y reduces startup memory spikes from package resolution.
  • Prefer lightweight servers: Python-based servers using FastMCP typically use 20-35 MB, less than equivalent Node.js servers.

Startup Order and Dependencies

MCP clients typically start all configured servers in parallel. This can be an issue if Server B depends on Server A being ready (for example, a custom server that depends on a database server also being configured). Most clients do not support explicit startup ordering, so handle dependencies at the server level:

  • Retry on startup: Have servers retry their external connections during initialization with exponential backoff instead of failing immediately.
  • Lazy connections: Do not connect to databases or APIs until the first tool call that needs them. Return the tool listing immediately.
  • Health check tools: Implement a simple health check tool that reports whether all dependencies are ready.

Recommended Server Combinations

Here are battle-tested combinations for common workflows:

Workflow Servers Est. Memory
Web Development filesystem + github + postgres + puppeteer + memory ~400 MB
Data Engineering filesystem + postgres + sqlite + brave-search + memory ~300 MB
DevOps github + filesystem + slack + brave-search + memory ~280 MB
Content Creation filesystem + memory + brave-search + puppeteer + fetch ~350 MB

Browse all available servers on our MCP servers directory to find the right combination for your workflow. For environment variable configuration across multiple servers, see the environment variables guide.

Troubleshooting Multi-Server Issues

When running multiple MCP servers, debugging can be more complex because failures in one server can mask issues in others. Here are common multi-server problems and their solutions:

  • One broken server prevents all servers from loading: If your config JSON is invalid (trailing comma, unescaped backslash), no servers will load. Validate your JSON before restarting the client. Use python3 -c "import json; json.load(open('config.json'))" to check syntax.
  • Server name collision: If two servers have the same key name in the config, the second one silently overwrites the first. Use unique, descriptive names for every server entry.
  • Shared port conflicts: If two HTTP-based servers try to bind to the same port, the second one will crash. Assign explicit, unique ports to each server that needs one. Most stdio servers do not need ports at all.
  • Excessive memory usage: Monitor total MCP memory usage with ps aux | grep node | awk '{sum+=$6}END{print sum/1024"MB"}'. If it exceeds available RAM, reduce the number of active servers or add memory limits via NODE_OPTIONS.
  • Slow startup with many npx servers: Each npx invocation resolves and potentially downloads packages. Pre-install frequently used packages globally with npm install -g to reduce startup time from 5 seconds per server to under 1 second.
  • Environment variable isolation: Each server has its own env configuration. If two servers need the same API key, you must specify it in both server configs independently. There is no shared env mechanism in the MCP config format.

Configuration Templates for Teams

For teams sharing MCP configurations, create a template config file with placeholders for secrets:

// mcp-config-template.json - commit this to your repo
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "."]
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "REPLACE_WITH_YOUR_TOKEN"
      }
    },
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "POSTGRES_URL": "REPLACE_WITH_YOUR_DATABASE_URL"
      }
    }
  }
}

Team members copy this template, replace the placeholders with their own credentials, and save it as their actual config file. Add the actual config file to .gitignore to keep secrets out of version control. See the environment variables guide for more secrets management approaches.

Disabling Servers Without Removing Config

When you want to temporarily disable a server without deleting its configuration, you have several options depending on your client:

  • Cursor: Toggle servers on and off in Settings, MCP section. The config entry remains intact but the server does not start.
  • VS Code: Some extensions support a "disabled": true field on server entries. Check your extension's documentation.
  • Claude Desktop: No built-in disable feature. The workaround is to move the server entry to a separate backup config file, or rename the server key to something like "_disabled_github" (the server will fail to start but the config is preserved).
  • All clients: You can change the command to something that exits immediately, like "command": "echo", as a quick disable without changing the rest of the config.

Frequently Asked Questions

Related Guides

Ready to explore MCP servers?

Browse 100+ curated MCP servers
Step-by-step setup tutorials
Community-driven reviews and ratings