Skip to main content

Configuring MCP Clients

You've understood MCP architecture: the Host-Client-Server model, transport layers, and the three primitives (tools, resources, prompts). Now comes the practical question: How do you actually connect MCP servers to your tools so they can use them?

Configuration is where theory meets reality. And it's deceptively straightforward—JSON files that define which servers to launch, how to authenticate, what parameters to pass. But getting it wrong breaks everything silently. A misconfigured environment variable means your agent can't access GitHub. A wrong path means the server won't start. A typo means no error message—the tool simply fails to load.

This lesson covers configuration across every major platform: Claude Code (where you probably started), Claude Desktop (the standalone application), VS Code (for developers integrating MCP), and programmatic clients (when you build agents in Python or Node.js). By the end, you'll understand how to set up production-ready MCP configurations that work reliably.

Configuration Locations: Where MCP Looks for Servers

MCP clients search for configuration in predictable locations:

Claude Code (Project-Level Configuration)

Path: .claude/settings.json (in your project root)

This is project-specific. Each project can have different MCP servers configured.

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}

Advantages:

  • Project isolation (different projects, different servers)
  • Committed to git (team visibility)
  • Workspace-specific setup

Use when:

  • Building agents for specific projects
  • Team collaboration (configuration in version control)
  • Different projects need different server sets

Claude Desktop (Global Configuration)

Path:

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

This is global—applies to all Claude Desktop sessions.

{
"mcpServers": {
"github": {
"command": "uvx",
"args": ["--python", "3.12", "mcp-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
},
"filesystem": {
"command": "uvx",
"args": ["mcp-filesystem", "/Users/yourname/Documents"]
}
}
}

Advantages:

  • Always available across sessions
  • Centralized configuration
  • Perfect for frequently-used servers

Use when:

  • Tools you use in every conversation
  • Personal assistant-style MCP servers
  • Development tools needed across projects

VS Code / Cursor (User Settings)

Path:

  • User settings (global): Via VS Code settings UI or settings.json
  • Workspace settings (project): .vscode/settings.json

VS Code integrates MCP through extensions. Configuration looks slightly different:

{
"mcpServers": {
"github": {
"command": "uvx",
"args": ["mcp-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}

Settings are managed through VS Code's configuration system, not directly as files (though the underlying format is JSON).

Use when:

  • IDE-integrated MCP usage
  • VS Code extensions that speak MCP
  • Cursor IDE integration

Configuration Structure: The mcpServers Object

Every MCP client configuration follows the same structure:

{
"mcpServers": {
"server-name": {
"command": "executable or npx",
"args": ["arg1", "arg2", "arg3"],
"env": {
"VAR_NAME": "${VAR_NAME}"
}
}
}
}

Let's break down each field:

command: How to Start the Server

For local executables:

"command": "/usr/local/bin/mcp-server"

For npm packages (via npx):

"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"]

For Python packages (via uvx):

"command": "uvx",
"args": ["--python", "3.12", "mcp-github"]

The client executes this command as a subprocess and communicates via stdio.

args: Command Arguments

Arguments passed to the command. For npm packages:

"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/serve"]

Breaking this down:

  • -y: Auto-answer yes to npm prompts
  • @modelcontextprotocol/server-filesystem: Package name
  • /path/to/serve: Path the server will expose

For HTTP servers (if you're pointing to remote MCP):

"args": ["--host", "localhost", "--port", "8000"]

env: Environment Variables

Passes environment variables to the server process. This is critical for secrets.

"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}",
"DATABASE_URL": "${DATABASE_URL}",
"API_KEY": "${API_KEY}"
}

The ${VAR_NAME} syntax tells the client: "Look up VAR_NAME from the environment where you're running and substitute it here."

This protects you from accidentally committing secrets to git:

  • Configuration file contains ${GITHUB_TOKEN} (safe)
  • Your shell environment has GITHUB_TOKEN=ghp_xxxx (secret)
  • Client substitutes at runtime

Environment Variables: Where Secrets Come From

Configuration references environment variables. The client retrieves their actual values from:

  1. Shell environment (what you have in your terminal)
  2. .env files (if the client supports them)
  3. System variables (machine-wide settings)

.env Files (For Development)

Create a .env file in your project root:

GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
DATABASE_URL=postgresql://user:pass@localhost/db
API_KEY=sk-1234567890abcdef

Don't commit this to git. Add to .gitignore:

.env
.env.local

Some MCP clients automatically load .env files. Others require you to source the file:

export $(cat .env | xargs)

Then start Claude Code or your application.

System Environment Variables

For production, set variables in your deployment environment:

# In your shell
export GITHUB_TOKEN=ghp_xxxx

# Or in deployment platform (Docker, Kubernetes, etc.)
ENV GITHUB_TOKEN=ghp_xxxx

The client reads these at runtime.

Common Configuration Patterns

Pattern 1: Filesystem Server (Local Files)

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/you/project"]
}
}
}

What it does: Exposes files in /Users/you/project as MCP resources. The agent can read files, search directories.

No environment variables needed: Filesystem doesn't require secrets.

Pattern 2: GitHub Server (Requires Authentication)

{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}

What it does: Enables MCP tools for creating issues, fetching PRs, managing workflows.

Requires: GitHub Personal Access Token with appropriate permissions.

Get token:

  1. Go to GitHub Settings → Developer Settings → Personal Access Tokens
  2. Create token with repo, read:org scopes
  3. Store in .env: GITHUB_TOKEN=ghp_xxxx

Pattern 3: Database Server (PostgreSQL, MySQL, etc.)

{
"mcpServers": {
"database": {
"command": "uvx",
"args": ["mcp-database"],
"env": {
"DATABASE_URL": "${DATABASE_URL}"
}
}
}
}

What it does: Exposes database tables as MCP resources; provides tools for querying and updates.

Requires: Database connection string.

Format: postgresql://user:password@host:port/database

Get connection string:

# For local development
DATABASE_URL=postgresql://user:pass@localhost:5432/mydb

# For managed services (Supabase, Railway, etc.)
DATABASE_URL=postgresql://user:xxx@server.replication.supabase.co:5432/postgres?sslmode=require

Pattern 4: Multiple Servers in One Configuration

{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/project"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
},
"database": {
"command": "uvx",
"args": ["mcp-database"],
"env": {
"DATABASE_URL": "${DATABASE_URL}"
}
}
}
}

Important: Each server is independent. The client launches one subprocess per server. When you ask the agent to execute a tool:

  1. Agent requests tool create_issue (GitHub tool)
  2. Client routes to GitHub server
  3. GitHub server executes; returns result

The agent doesn't know (or care) about database server—it's not involved unless you explicitly request a database tool.

Configuration for Programmatic Clients (Python)

When building agents programmatically, you configure MCP differently—through code instead of JSON files.

Using Claude SDK with Stdio Transport

from mcp import ClientSession, StdioClientTransport

# Configure server
transport = StdioClientTransport(
command="npx",
args=[
"-y",
"@modelcontextprotocol/server-github"
],
env={
"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN")
}
)

# Create session
async with ClientSession(transport) as session:
await session.initialize()
tools = await session.list_tools()
print(tools)

Key differences from JSON:

  • Direct Python code instead of configuration files
  • Environment variables via os.getenv() instead of ${VAR_NAME}
  • Explicit session initialization

Using Anthropic SDK with MCP Integration

from anthropic import Anthropic

client = Anthropic()

# Configure MCP servers
mcp_config = {
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": os.getenv("GITHUB_TOKEN")
}
}
}
}

# Pass to client
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
tools=[...], # MCP tools discovered via mcp_config
messages=[...]
)

Configuration Comparison: Which to Use When

ScenarioLocationFormatBest For
Claude Code.claude/settings.jsonJSONProject-specific agents, team workflows
Claude Desktop~/.config/Claude/claude_desktop_config.json (Linux)JSONPersonal use, always-available tools
VS Code.vscode/settings.json or user settingsJSONIDE integration, extension support
Python AgentProgrammatic (code)Python objectsCustom agent applications, deployment
Node.js AgentProgrammatic (code)JavaScript objectsBackend services, serverless functions

Decision framework:

  • Team collaboration: Use Claude Code with .claude/settings.json (in git)
  • Personal tools: Use Claude Desktop global config
  • IDE workflows: Use VS Code settings integration
  • Production agents: Programmatic configuration in Python/Node

Security Best Practices for Production

Never Hardcode Secrets

WRONG:

{
"env": {
"GITHUB_TOKEN": "ghp_xxxxxxxxxxxxxxxxxxxx"
}
}

Commit this to git, and it's compromised forever. GitHub revokes it, but the token is in your git history permanently.

RIGHT:

{
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}

Let the deployment platform provide the secret.

Use Secret Management for Production

For Kubernetes:

apiVersion: v1
kind: Secret
metadata:
name: mcp-secrets
data:
GITHUB_TOKEN: base64encodedtoken
---
apiVersion: v1
kind: ConfigMap
metadata:
name: mcp-config
data:
settings.json: |
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}

For Docker:

FROM node:20

COPY . /app
WORKDIR /app

# Read secret from build arg (passed at build time, not stored in image)
ARG GITHUB_TOKEN
ENV GITHUB_TOKEN=${GITHUB_TOKEN}

CMD ["node", "agent.js"]

Build with: docker build --build-arg GITHUB_TOKEN=ghp_xxx .

Rotate Credentials Regularly

MCP agents running for weeks/months should use credentials that can be rotated without restarting:

  • GitHub: Regularly create new Personal Access Tokens
  • Database: Use database users with limited permissions
  • API keys: Implement key rotation policies

Principle of Least Privilege

Only grant credentials the minimum permissions needed:

  • GitHub: If MCP server only reads PRs, create token with read-only scopes
  • Database: Create database user with SELECT on specific tables (not admin)
  • API Keys: Use API keys with rate limits, specific resource access

This limits damage if credentials leak.

Troubleshooting Configuration Issues

Server Won't Start

Error: Command not found: mcp-server

Causes:

  • Executable doesn't exist at path
  • npx/uvx not installed
  • Path is wrong

Fix:

# Verify command works outside config
npx -y @modelcontextprotocol/server-github

# If it works manually, config path might be relative
# Use absolute paths instead
"command": "/usr/local/bin/mcp-server"
# Or use npx/uvx (which finds packages)
"command": "npx"

Server Starts But No Tools Available

Cause: Environment variable not found

Error: GITHUB_TOKEN not provided

Fix:

# Set variable before starting
export GITHUB_TOKEN=ghp_xxxx
# Then start Claude Code

# Or add to .env and source it
source .env

Configuration Not Being Loaded

Cause: Wrong file path or location

Check:

  • Claude Code: ./.claude/settings.json in project root
  • Claude Desktop (Linux): ~/.config/Claude/claude_desktop_config.json
  • VS Code: Settings UI or .vscode/settings.json

Verify:

# List Claude Code config
cat .claude/settings.json | jq .mcpServers

# Check Claude Desktop location (macOS)
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json | jq .

JSON Syntax Error

Error: Invalid JSON in configuration

Check:

  • Missing commas between properties
  • Trailing commas
  • Unquoted keys

Validate:

# Use jq to validate
cat .claude/settings.json | jq .

# Or use online JSON validator

Try With AI

Use your AI companion to explore MCP configuration scenarios and troubleshoot setup issues.

Safety Note on Configuration Security

When configuring MCP servers, remember:

  • Never commit .env files or configuration with hardcoded secrets to git
  • Use environment variable references (${VAR_NAME}) in configuration files
  • Rotate credentials regularly—if a secret leaks, create new credentials immediately
  • Principle of least privilege—only grant each MCP server the permissions it needs
  • Verify SSL/TLS when connecting to remote MCP servers—don't accept unencrypted connections in production

Configuration security determines whether your agents can be compromised. Get this right.

Prompt 1: Analyze Your Current Configuration

Setup: Understanding what's already configured in your environment

I have MCP servers configured in Claude Code. Help me understand what I have set up.

Here's my .claude/settings.json:
[paste your configuration]

For each server in my configuration:
1. Identify what tool this server provides
2. What permissions or secrets does it need?
3. How would I know if this server is working correctly?
4. What would break if I misconfigured the environment variables?

What you're learning: Analyzing existing configuration to understand server requirements and potential failure modes.

Prompt 2: Configure a New Server

Setup: Adding GitHub server to an existing setup

I want to add a GitHub MCP server to my configuration. I already have:
[paste your current mcpServers object]

I want to be able to create issues and fetch pull requests. Help me:
1. Write the JSON configuration for a GitHub MCP server
2. Tell me what permissions I need on my GitHub token
3. Explain how to securely provide the token (I should never commit it to git)
4. Walk me through testing to verify it's working

Here's what my environment looks like:
- I use Claude Code
- My project is at /Users/me/project
- I have a GitHub Personal Access Token already created

What you're learning: Configuring new servers, managing environment variables securely, and validating setup through testing.

Prompt 3: Troubleshoot Configuration Problems

Setup: Debugging a configuration that isn't working

I configured a database MCP server but when I try to query the database,
I get this error: "[ENOENT] DATABASE_URL environment variable not set"

Here's my configuration:
[paste your configuration]

Here's what I did to set up the environment:
1. Created a .env file with DATABASE_URL=postgresql://...
2. Didn't source the .env file
3. Started Claude Code directly

What's wrong? Walk me through:
1. Why this error is happening
2. How environment variable substitution works
3. The correct way to provide DATABASE_URL
4. How to debug this in the future

What you're learning: Understanding why configuration fails, how to diagnose environment variable issues, and implementing proper secret management.

Prompt 4: Design Configuration for Team Collaboration

Setup: Setting up MCP for a team project

I'm setting up MCP configuration for my team's project. Here's what we need:

- 5 developers, each with their own GitHub token
- Shared project codebase (all on same git repo)
- Database server accessible from cloud (not local)
- Filesystem access to /project directory

For this scenario:
1. Should we use .claude/settings.json or global Claude Desktop config?
2. How do we handle different GITHUB_TOKEN values per developer?
3. Should DATABASE_URL go in .env, environment variables, or somewhere else?
4. What do we commit to git? What do we keep local?

Help me design a configuration strategy that works for a team.

What you're learning: Scaling configuration from personal use to team collaboration; understanding security implications of shared configuration.