Files
2025-10-28 13:08:19 -05:00

12 KiB

MCP Configuration Reference

Complete schema and technical reference for MCP server configuration in Claude Code plugins.

Configuration Schema

Stdio Server Configuration

{
  command: string                    // Required: Executable path or command name
  args?: string[]                    // Optional: Command-line arguments
  env?: Record<string, string>       // Optional: Environment variables
}

Field Details:

  • command: The executable to run. Can be:

    • System command: "node", "python", "npx"
    • Absolute path: "/usr/local/bin/my-server"
    • Plugin-relative: "${CLAUDE_PLUGIN_ROOT}/servers/my-server"
  • args: Array of arguments passed to the command

    • Order matters
    • Supports variable expansion: ["--config", "${CONFIG_PATH}"]
  • env: Environment variables for the process

    • Inherits user's environment by default
    • Additional vars override/extend inherited ones
    • Supports variable expansion: {"KEY": "${USER_KEY}"}

Example:

{
  "my-server": {
    "command": "node",
    "args": ["${CLAUDE_PLUGIN_ROOT}/dist/server.js", "--port", "8080"],
    "env": {
      "NODE_ENV": "production",
      "LOG_LEVEL": "${LOG_LEVEL:-info}"
    }
  }
}

HTTP Server Configuration

{
  type: "http"                       // Required: Transport type
  url: string                        // Required: HTTP(S) endpoint URL
  headers?: Record<string, string>   // Optional: HTTP headers
}

Field Details:

  • type: Must be "http" for HTTP transport

  • url: The MCP endpoint URL

    • Must be valid HTTP(S) URL
    • Supports variable expansion: "${API_BASE_URL}/mcp"
    • Should end in /mcp by convention
  • headers: HTTP headers sent with requests

    • Common uses: Authentication, API keys, custom metadata
    • Supports variable expansion: {"Authorization": "Bearer ${TOKEN}"}

Example:

{
  "api-server": {
    "type": "http",
    "url": "https://api.example.com/mcp",
    "headers": {
      "Authorization": "Bearer ${API_TOKEN}",
      "X-Client-Version": "1.0.0",
      "Accept": "application/json"
    }
  }
}

SSE Server Configuration (Deprecated)

{
  type: "sse"                        // Required: Transport type
  url: string                        // Required: SSE endpoint URL
  headers?: Record<string, string>   // Optional: HTTP headers
}

Note: SSE transport is deprecated. Use HTTP transport instead when available.

Field Details:

  • type: Must be "sse" for Server-Sent Events transport
  • url: The SSE endpoint URL
  • headers: HTTP headers (same as HTTP transport)

Example:

{
  "legacy-server": {
    "type": "sse",
    "url": "https://api.example.com/sse",
    "headers": {
      "X-API-Key": "${API_KEY}"
    }
  }
}

Environment Variable Expansion

Syntax

Pattern Behavior Example
${VAR} Required variable (error if not set) ${API_KEY}
${VAR:-default} Optional with fallback value ${PORT:-8080}
${CLAUDE_PLUGIN_ROOT} Plugin directory path (special) ${CLAUDE_PLUGIN_ROOT}/bin

Expansion Locations

Environment variables can be expanded in:

  • Stdio servers:

    • command field
    • args array elements
    • env object values
  • HTTP/SSE servers:

    • url field
    • headers object values

Special Variables

${CLAUDE_PLUGIN_ROOT}

  • Type: Plugin-specific
  • Value: Absolute path to plugin directory
  • Use case: Reference bundled servers, configs, assets
  • Example: "${CLAUDE_PLUGIN_ROOT}/servers/db-server"

User Environment Variables

All variables from user's shell environment are available:

{
  "env": {
    "PATH": "${PATH}",              // User's PATH
    "HOME": "${HOME}",              // User's home directory
    "DATABASE_URL": "${DATABASE_URL}" // Custom user variable
  }
}

Expansion Examples

Basic expansion:

{
  "url": "${API_BASE_URL}/mcp"
}

With API_BASE_URL=https://api.example.com, becomes:

https://api.example.com/mcp

Default values:

{
  "env": {
    "LOG_LEVEL": "${LOG_LEVEL:-info}",
    "PORT": "${PORT:-3000}"
  }
}

Without environment variables set, becomes:

{
  "env": {
    "LOG_LEVEL": "info",
    "PORT": "3000"
  }
}

Plugin-relative paths:

{
  "command": "${CLAUDE_PLUGIN_ROOT}/bin/server",
  "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"]
}

With plugin at /home/user/.claude/plugins/my-plugin, becomes:

command: /home/user/.claude/plugins/my-plugin/bin/server
args: ["--config", "/home/user/.claude/plugins/my-plugin/config.json"]

Configuration Files

Location: Plugin root directory

Structure:

{
  "mcpServers": {
    "server-name-1": { /* config */ },
    "server-name-2": { /* config */ }
  }
}

Advantages:

  • Separates concerns (MCP config separate from plugin metadata)
  • Easier to maintain complex configurations
  • Can be shared/reused across plugins
  • Better for multiple MCP servers

Example:

{
  "mcpServers": {
    "database": {
      "command": "npx",
      "args": ["-y", "@bytebase/dbhub", "--dsn", "${DATABASE_URL}"]
    },
    "api": {
      "type": "http",
      "url": "${API_BASE_URL}/mcp"
    }
  }
}

plugin.json (Inline)

Location: .claude-plugin/plugin.json

Structure:

{
  "name": "my-plugin",
  "version": "1.0.0",
  "mcpServers": {
    "server-name": { /* config */ }
  }
}

Advantages:

  • Single file for simple plugins
  • All configuration in one place
  • No additional files needed

Example:

{
  "name": "simple-plugin",
  "version": "1.0.0",
  "description": "A simple plugin with one MCP server",
  "mcpServers": {
    "api": {
      "type": "http",
      "url": "https://api.example.com/mcp"
    }
  }
}

Choosing Between .mcp.json and inline:

  • Use .mcp.json for 2+ servers or complex configs
  • Use inline for single simple server
  • Both methods are functionally identical

Server Lifecycle

1. Plugin Enable

  • Plugin is enabled via /plugin enable
  • MCP servers are registered with Claude Code
  • No servers start yet

2. Claude Code Start

  • Claude Code reads enabled plugins
  • MCP servers start automatically
  • Stdio servers: Process spawned
  • HTTP/SSE servers: Connection established

3. Server Ready

  • Server responds to initialization
  • Tools/resources/prompts registered
  • Available via /mcp command

4. Plugin Update

  • Configuration changes detected
  • Requires Claude Code restart to apply
  • Old servers stop, new ones start on restart

5. Plugin Disable

  • Plugin disabled via /plugin disable
  • MCP servers stop automatically
  • Resources cleaned up

Platform-Specific Considerations

Windows

npx Wrapper Required:

{
  "command": "cmd",
  "args": ["/c", "npx", "-y", "package-name"]
}

Path Separators:

  • Windows: Use forward slashes / in JSON
  • Variable expansion handles platform differences
  • Example: "${CLAUDE_PLUGIN_ROOT}/bin/server" works on all platforms

Environment Variables:

{
  "env": {
    "USERPROFILE": "${USERPROFILE}",  // Windows home directory
    "APPDATA": "${APPDATA}"            // Windows app data
  }
}

macOS/Linux

Standard Commands:

{
  "command": "npx",
  "args": ["-y", "package-name"]
}

Executable Permissions:

  • Bundled executables must have execute permissions
  • Set in version control: git update-index --chmod=+x server.sh
  • Or in plugin distribution: chmod +x ${CLAUDE_PLUGIN_ROOT}/bin/*

Validation and Errors

Common Validation Errors

Invalid JSON:

Error: Failed to parse .mcp.json

Solution: Validate JSON syntax with jq or JSON validator

Missing Required Fields:

Error: Missing required field 'command' in stdio server config
Error: Missing required field 'url' in http server config

Solution: Add required fields per schema above

Invalid Variable Expansion:

Error: Environment variable 'API_KEY' is required but not set

Solution: Set required environment variable or provide default value

Invalid URL:

Error: Invalid URL in http server config

Solution: Ensure URL is valid HTTP(S) format

Runtime Errors

Server Won't Start:

  • Check command path exists and is executable
  • Verify all required environment variables are set
  • Check server logs for startup errors

Connection Failed (HTTP/SSE):

  • Verify URL is accessible
  • Check network/firewall settings
  • Confirm authentication headers are correct

Server Not Found:

  • Ensure plugin is enabled
  • Restart Claude Code after config changes
  • Check /mcp output for registered servers

Performance Considerations

Stdio Servers

Process Overhead:

  • Each stdio server is a separate process
  • Consider resource usage for multiple servers
  • Use HTTP servers for remote services

Startup Time:

  • Servers start on Claude Code launch
  • Slow-starting servers delay tool availability
  • Consider lazy initialization for heavy servers

HTTP/SSE Servers

Network Latency:

  • Remote servers add network latency
  • Use connection pooling where possible
  • Consider caching for read-heavy operations

Rate Limiting:

  • Respect API rate limits
  • Implement backoff strategies
  • Cache responses when appropriate

Security Best Practices

Credential Management

Do:

  • Store credentials in environment variables
  • Use ${VAR} expansion in configs
  • Document required variables in README
  • Use secure storage for sensitive values

Don't:

  • Hardcode credentials in JSON
  • Commit credentials to version control
  • Share credentials in plugin distributions
  • Log credential values

Network Security

HTTPS Only:

{
  "type": "http",
  "url": "https://api.example.com/mcp"  // ✅ HTTPS
}

Avoid HTTP:

{
  "type": "http",
  "url": "http://api.example.com/mcp"  // ❌ Insecure
}

Certificate Validation:

  • HTTPS certificates are validated by default
  • Don't disable certificate validation
  • Use valid, trusted certificates

Process Security

Least Privilege:

  • Stdio servers run with user's permissions
  • Don't require elevated privileges
  • Validate all inputs from MCP protocol

Sandboxing:

  • Stdio servers are not sandboxed
  • Be cautious with user input
  • Validate/sanitize all data

Debugging

Enable Debug Logging

Set environment variables before starting Claude Code:

export DEBUG=mcp:*
export MCP_LOG_LEVEL=debug
claude

Check Server Status

Within Claude Code:

/mcp

Shows:

  • Registered servers
  • Connection status
  • Available tools/resources

Test Server Manually

Stdio Server:

# Test command directly
node ${CLAUDE_PLUGIN_ROOT}/servers/my-server.js

# With environment
API_KEY=test node servers/my-server.js

HTTP Server:

# Test endpoint
curl -H "Authorization: Bearer ${API_TOKEN}" \
     https://api.example.com/mcp

Common Debug Scenarios

Server Not Appearing:

  1. Check plugin is enabled: /plugin list
  2. Verify config syntax: cat .mcp.json | jq .
  3. Restart Claude Code
  4. Check for error messages on startup

Server Starts But No Tools:

  1. Check server logs for initialization errors
  2. Verify server implements MCP protocol correctly
  3. Test server manually outside Claude Code
  4. Check server responds to tools/list request

Environment Variables Not Expanding:

  1. Verify syntax: ${VAR} not $VAR
  2. Check variable is set: echo $VAR
  3. Restart Claude Code after setting variables
  4. Check for typos in variable names

See Also