# MCP Configuration Guide This document provides comprehensive guidance for configuring Model Context Protocol (MCP) servers with Claude Code for the Flyer Crawler project. ## Table of Contents 1. [What is MCP](#what-is-mcp) 2. [Server Overview](#server-overview) 3. [Configuration Locations](#configuration-locations) 4. [Global Settings Configuration](#global-settings-configuration) 5. [Project-Level Configuration](#project-level-configuration) 6. [Server Setup Instructions](#server-setup-instructions) 7. [Bugsink MCP](#bugsink-mcp) 8. [PostgreSQL MCP](#postgresql-mcp) 9. [Gitea MCP](#gitea-mcp) 10. [Other MCP Servers](#other-mcp-servers) 11. [Troubleshooting](#troubleshooting) 12. [Best Practices](#best-practices) --- ## What is MCP Model Context Protocol (MCP) is a standardized protocol that allows AI assistants like Claude to interact with external tools and services. MCP servers expose capabilities (tools) that Claude can invoke to: - Query databases - Manage containers - Access file systems - Interact with APIs (Gitea, Bugsink, etc.) - Store and retrieve knowledge graph data - Inspect caches and key-value stores **Why We Use MCP:** | Benefit | Description | | ------------------ | ------------------------------------------------------------------------ | | Direct Integration | Claude can directly query databases, inspect containers, and access APIs | | Context Awareness | Tools provide real-time information without manual copy-paste | | Automation | Complex workflows can be executed through tool chains | | Consistency | Standardized interface across different services | --- ## Server Overview The Flyer Crawler project uses the following MCP servers: | Server | Tool Prefix | Purpose | Config Location | | ------------------ | -------------------------- | -------------------------------------------------- | --------------- | | `gitea-projectium` | `mcp__gitea-projectium__*` | Gitea API at gitea.projectium.com | Global | | `gitea-torbonium` | `mcp__gitea-torbonium__*` | Gitea API at gitea.torbonium.com | Global | | `podman` | `mcp__podman__*` | Container management | Global | | `filesystem` | `mcp__filesystem__*` | File system access | Global | | `memory` | `mcp__memory__*` | Knowledge graph persistence | Global | | `redis` | `mcp__redis__*` | Redis cache inspection | Global | | `bugsink` | `mcp__bugsink__*` | Production error tracking (bugsink.projectium.com) | Global | | `localerrors` | `mcp__localerrors__*` | Dev container error tracking (localhost:8000) | Project | | `devdb` | `mcp__devdb__*` | Development PostgreSQL database | Project | --- ## Configuration Locations Claude Code uses **two separate configuration systems** for MCP servers: ### Global Configuration **Location (Windows):** ```text C:\Users\\.claude\settings.json ``` **Used For:** - Production services (HTTPS endpoints) - Servers shared across all projects - Container management (Podman) - Knowledge graph (Memory) ### Project-Level Configuration **Location:** ```text /.mcp.json ``` **Used For:** - Localhost services (HTTP endpoints) - Development databases - Project-specific tools ### When to Use Each | Scenario | Configuration | | --------------------------------- | ---------------------- | | Production APIs (HTTPS) | Global `settings.json` | | Shared tools (memory, filesystem) | Global `settings.json` | | Localhost services (HTTP) | Project `.mcp.json` | | Development databases | Project `.mcp.json` | | Per-project customization | Project `.mcp.json` | **Important:** Localhost MCP servers work more reliably in project-level `.mcp.json` than in global `settings.json`. See [Troubleshooting](#localhost-servers-not-loading) for details. --- ## Global Settings Configuration ### File Format ```json { "mcpServers": { "server-name": { "command": "path/to/executable", "args": ["arg1", "arg2"], "env": { "ENV_VAR": "value" }, "disabled": true } } } ``` **Configuration Options:** | Field | Required | Description | | ---------- | -------- | ----------------------------------------- | | `command` | Yes | Path to executable or command | | `args` | No | Array of command-line arguments | | `env` | No | Environment variables for the server | | `disabled` | No | Set to `true` to disable without removing | ### Example Global Configuration ```json { "mcpServers": { "memory": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "@modelcontextprotocol/server-memory"] }, "filesystem": { "command": "d:\\nodejs\\node.exe", "args": [ "c:\\Users\\\\AppData\\Roaming\\npm\\node_modules\\@modelcontextprotocol\\server-filesystem\\dist\\index.js", "d:\\gitea" ] }, "podman": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "podman-mcp-server@latest"], "env": { "DOCKER_HOST": "npipe:////./pipe/podman-machine-default" } }, "redis": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "@modelcontextprotocol/server-redis", "redis://localhost:6379"] }, "bugsink": { "command": "d:\\nodejs\\node.exe", "args": ["d:\\gitea\\bugsink-mcp\\dist\\index.js"], "env": { "BUGSINK_URL": "https://bugsink.projectium.com", "BUGSINK_TOKEN": "<40-char-hex-token>" } }, "gitea-projectium": { "command": "d:\\gitea-mcp\\gitea-mcp.exe", "args": ["run", "-t", "stdio"], "env": { "GITEA_HOST": "https://gitea.projectium.com", "GITEA_ACCESS_TOKEN": "" } }, "gitea-torbonium": { "command": "d:\\gitea-mcp\\gitea-mcp.exe", "args": ["run", "-t", "stdio"], "env": { "GITEA_HOST": "https://gitea.torbonium.com", "GITEA_ACCESS_TOKEN": "" } } } } ``` --- ## Project-Level Configuration ### File Location Create `.mcp.json` in the project root: ```text d:\gitea\flyer-crawler.projectium.com\flyer-crawler.projectium.com\.mcp.json ``` ### File Format ```json { "mcpServers": { "server-name": { "command": "path/to/executable", "args": ["arg1", "arg2"], "env": { "ENV_VAR": "value" } } } } ``` ### Current Project Configuration ```json { "mcpServers": { "localerrors": { "command": "d:\\nodejs\\node.exe", "args": ["d:\\gitea\\bugsink-mcp\\dist\\index.js"], "env": { "BUGSINK_URL": "http://127.0.0.1:8000", "BUGSINK_TOKEN": "<40-char-hex-token>" } }, "devdb": { "command": "D:\\nodejs\\npx.cmd", "args": [ "-y", "@modelcontextprotocol/server-postgres", "postgresql://postgres:postgres@127.0.0.1:5432/flyer_crawler_dev" ] } } } ``` --- ## Server Setup Instructions ### Memory (Knowledge Graph) **Package:** `@modelcontextprotocol/server-memory` **Purpose:** Persists knowledge across sessions - project context, credentials, known issues. **Configuration:** ```json "memory": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "@modelcontextprotocol/server-memory"] } ``` **Key Tools:** - `mcp__memory__read_graph` - Read entire knowledge graph - `mcp__memory__search_nodes` - Search for specific entities - `mcp__memory__create_entities` - Add new knowledge ### Filesystem **Package:** `@modelcontextprotocol/server-filesystem` **Purpose:** Provides file system access to specified directories. **Configuration:** ```json "filesystem": { "command": "d:\\nodejs\\node.exe", "args": [ "c:\\Users\\\\AppData\\Roaming\\npm\\node_modules\\@modelcontextprotocol\\server-filesystem\\dist\\index.js", "d:\\gitea" ] } ``` **Note:** The last argument(s) specify allowed directories. ### Podman/Docker **Package:** `podman-mcp-server` **Purpose:** Container management - list, start, stop, inspect containers. **Configuration:** ```json "podman": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "podman-mcp-server@latest"], "env": { "DOCKER_HOST": "npipe:////./pipe/podman-machine-default" } } ``` **Key Tools:** - `mcp__podman__container_list` - List running containers - `mcp__podman__container_logs` - View container logs - `mcp__podman__container_inspect` - Detailed container info - `mcp__podman__image_list` - List images ### Redis **Package:** `@modelcontextprotocol/server-redis` **Purpose:** Inspect Redis cache, set/get values, list keys. **Configuration:** ```json "redis": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "@modelcontextprotocol/server-redis", "redis://localhost:6379"] } ``` **Key Tools:** - `mcp__redis__get` - Get value by key - `mcp__redis__set` - Set key-value pair - `mcp__redis__list` - List keys matching pattern - `mcp__redis__delete` - Delete key(s) --- ## Bugsink MCP Bugsink is a self-hosted error tracking service. We run two instances: | Instance | URL | MCP Server | Purpose | | ----------- | -------------------------------- | ------------- | ---------------------------- | | Production | `https://bugsink.projectium.com` | `bugsink` | Production error tracking | | Development | `http://localhost:8000` | `localerrors` | Dev container error tracking | ### Installation The `bugsink-mcp` package is **NOT published to npm**. Clone and build from source: ```bash # Clone the repository git clone https://github.com/j-shelfwood/bugsink-mcp.git d:\gitea\bugsink-mcp # Install and build cd d:\gitea\bugsink-mcp npm install npm run build ``` **Repository:** https://github.com/j-shelfwood/bugsink-mcp ### Configuration **Production (Global `settings.json`):** ```json "bugsink": { "command": "d:\\nodejs\\node.exe", "args": ["d:\\gitea\\bugsink-mcp\\dist\\index.js"], "env": { "BUGSINK_URL": "https://bugsink.projectium.com", "BUGSINK_TOKEN": "<40-char-hex-token>" } } ``` **Development (Project `.mcp.json`):** ```json "localerrors": { "command": "d:\\nodejs\\node.exe", "args": ["d:\\gitea\\bugsink-mcp\\dist\\index.js"], "env": { "BUGSINK_URL": "http://127.0.0.1:8000", "BUGSINK_TOKEN": "<40-char-hex-token>" } } ``` **Required Environment Variables:** | Variable | Description | | --------------- | -------------------------------------------- | | `BUGSINK_URL` | Full URL to Bugsink instance (with protocol) | | `BUGSINK_TOKEN` | 40-character hex API token | **Important:** - Variable is `BUGSINK_TOKEN`, NOT `BUGSINK_API_TOKEN` - Do NOT use `npx` - the package is not on npm - Use `http://127.0.0.1:8000` not `http://localhost:8000` for localhost ### Creating API Tokens Bugsink 2.0.11 does NOT have a "Settings > API Keys" menu in the UI. Tokens must be created via Django management command. **For Dev Container (localhost:8000):** ```bash MSYS_NO_PATHCONV=1 podman exec \ -e DATABASE_URL=postgresql://bugsink:bugsink_dev_password@postgres:5432/bugsink \ -e SECRET_KEY=dev-bugsink-secret-key-minimum-50-characters-for-security \ flyer-crawler-dev sh -c 'cd /opt/bugsink/conf && \ DJANGO_SETTINGS_MODULE=bugsink_conf \ PYTHONPATH=/opt/bugsink/conf:/opt/bugsink/lib/python3.10/site-packages \ /opt/bugsink/bin/python -m django create_auth_token' ``` **For Production (via SSH):** ```bash ssh root@projectium.com "cd /opt/bugsink && bugsink-manage create_auth_token" ``` Both commands output a 40-character lowercase hex token (e.g., `a609c2886daa4e1e05f1517074d7779a5fb49056`). ### Key Tools - `mcp__bugsink__test_connection` / `mcp__localerrors__test_connection` - Verify connection - `mcp__bugsink__list_projects` - List all projects - `mcp__bugsink__list_issues` - List issues for a project - `mcp__bugsink__get_issue` - Get issue details - `mcp__bugsink__get_stacktrace` - Get event stacktrace as Markdown ### Testing Connection ```typescript // Production mcp__bugsink__test_connection(); // Expected: "Connection successful: Connected successfully. Found N project(s)." // Development mcp__localerrors__test_connection(); // Expected: "Connection successful: Connected successfully. Found N project(s)." ``` --- ## PostgreSQL MCP **Package:** `@modelcontextprotocol/server-postgres` **Purpose:** Execute SQL queries against the development database. ### Configuration Add to project-level `.mcp.json`: ```json "devdb": { "command": "D:\\nodejs\\npx.cmd", "args": [ "-y", "@modelcontextprotocol/server-postgres", "postgresql://postgres:postgres@127.0.0.1:5432/flyer_crawler_dev" ] } ``` ### Connection String Format ```text postgresql://[user]:[password]@[host]:[port]/[database] ``` **Examples:** ```text # Development (local container) postgresql://postgres:postgres@127.0.0.1:5432/flyer_crawler_dev # Test database postgresql://flyer_crawler_test:password@127.0.0.1:5432/flyer_crawler_test ``` ### Database Information | Property | Value | | --------------------- | ------------------------ | | Container | `flyer-crawler-postgres` | | Image | `postgis/postgis:15-3.4` | | Host (from Windows) | `127.0.0.1` | | Host (from container) | `postgres` | | Port | `5432` | | Database | `flyer_crawler_dev` | | User | `postgres` | | Password | `postgres` | ### Usage Examples ```typescript // List all tables mcp__devdb__query({ sql: "SELECT tablename FROM pg_tables WHERE schemaname = 'public'" }); // Count records mcp__devdb__query({ sql: 'SELECT COUNT(*) FROM flyers' }); // Check table structure mcp__devdb__query({ sql: "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'flyers'", }); // Find recent records mcp__devdb__query({ sql: 'SELECT id, name, created_at FROM flyers ORDER BY created_at DESC LIMIT 10', }); ``` ### Prerequisites 1. **PostgreSQL container must be running:** ```bash podman ps | grep flyer-crawler-postgres ``` 2. **Port 5432 must be mapped:** ```bash podman port flyer-crawler-postgres # Expected: 5432/tcp -> 0.0.0.0:5432 ``` 3. **Database must exist:** ```bash podman exec flyer-crawler-postgres psql -U postgres -c "\l" | grep flyer_crawler_dev ``` --- ## Gitea MCP **Binary:** `gitea-mcp` (compiled Go binary) **Purpose:** Interact with Gitea repositories, issues, pull requests. ### Configuration ```json "gitea-projectium": { "command": "d:\\gitea-mcp\\gitea-mcp.exe", "args": ["run", "-t", "stdio"], "env": { "GITEA_HOST": "https://gitea.projectium.com", "GITEA_ACCESS_TOKEN": "" } } ``` ### Getting Access Token 1. Log in to Gitea web interface 2. Go to **Settings > Applications** 3. Under **Generate New Token**, enter a name 4. Select required scopes (typically `read:user`, `write:repository`, `write:issue`) 5. Click **Generate Token** 6. Copy the token immediately (shown only once) ### Key Tools - `mcp__gitea-projectium__list_my_repos` - List accessible repositories - `mcp__gitea-projectium__list_repo_issues` - List issues in a repo - `mcp__gitea-projectium__get_issue_by_index` - Get issue details - `mcp__gitea-projectium__create_issue` - Create new issue - `mcp__gitea-projectium__create_pull_request` - Create PR - `mcp__gitea-projectium__get_file_content` - Read file from repo - `mcp__gitea-projectium__list_branches` - List branches ### Example Operations ```typescript // List repositories mcp__gitea - projectium__list_my_repos({ page: 1, pageSize: 20 }); // Get issue mcp__gitea - projectium__get_issue_by_index({ owner: 'username', repo: 'repository-name', index: 42, }); // Create issue mcp__gitea - projectium__create_issue({ owner: 'username', repo: 'repository-name', title: 'Bug: Something is broken', body: '## Description\n\nSteps to reproduce...', }); ``` --- ## Other MCP Servers ### Sequential Thinking **Package:** `@modelcontextprotocol/server-sequential-thinking` **Purpose:** Structured step-by-step reasoning for complex problems. ```json "sequential-thinking": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"] } ``` ### Playwright (Browser Automation) **Package:** `@anthropics/mcp-server-playwright` **Purpose:** Browser automation for testing and scraping. ```json "playwright": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "@anthropics/mcp-server-playwright"] } ``` ### Sentry (Cloud Error Tracking) **Package:** `@sentry/mcp-server` **Purpose:** Error tracking for Sentry instances (NOT Bugsink). ```json "sentry": { "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "@sentry/mcp-server"], "env": { "SENTRY_AUTH_TOKEN": "" } } ``` **Note:** Bugsink has a different API than Sentry. Use `bugsink-mcp` for Bugsink instances. --- ## Troubleshooting ### Localhost Servers Not Loading **Symptoms:** - `mcp__localerrors__*` or `mcp__devdb__*` tools not available - No error messages in logs - Server silently skipped during startup **Root Cause:** Claude Code's global `settings.json` has issues loading localhost stdio MCP servers on Windows. The exact cause may be related to: - Multiple servers using the same underlying package - Localhost URL filtering - Windows-specific MCP loader bugs **Solution:** Use **project-level `.mcp.json`** for all localhost MCP servers. This bypasses the global config loader entirely. **Working Pattern:** - Global `settings.json`: Production HTTPS servers - Project `.mcp.json`: Localhost HTTP servers ### Server Name Collision **Symptoms:** - Second server with similar name never starts - No error logged - server silently filtered out **Root Cause:** Claude Code may skip MCP servers when names share prefixes (e.g., `bugsink` and `bugsink-dev`). **Solution:** Use completely distinct names: - `bugsink` for production - `localerrors` for development (NOT `bugsink-dev` or `devbugsink`) ### Connection Timed Out **Error:** `Connection timed out after 30000ms` **Causes:** - Server takes too long to start - npx download is slow - Server crashes during initialization **Solutions:** 1. Move important servers earlier in config 2. Use pre-installed packages instead of npx: ```json "command": "d:\\nodejs\\node.exe", "args": ["path/to/installed/package/dist/index.js"] ``` 3. Check server can start manually ### Environment Variable Issues **Common Mistakes:** | Wrong | Correct | | ----------------------- | ----------------------- | | `BUGSINK_API_TOKEN` | `BUGSINK_TOKEN` | | `http://localhost:8000` | `http://127.0.0.1:8000` | **Verification:** Test server manually with environment variables: ```bash cd d:\gitea\bugsink-mcp set BUGSINK_URL=http://127.0.0.1:8000 set BUGSINK_TOKEN= node dist/index.js ``` Expected output: ``` Bugsink MCP server started Connected to: http://127.0.0.1:8000 ``` ### PostgreSQL Connection Refused **Solutions:** 1. Check container is running: ```bash podman ps | grep flyer-crawler-postgres ``` 2. Verify port mapping: ```bash podman port flyer-crawler-postgres ``` 3. Test connection: ```bash podman exec flyer-crawler-postgres psql -U postgres -d flyer_crawler_dev -c "SELECT 1" ``` 4. Check for port conflicts: ```bash netstat -an | findstr 5432 ``` ### Verifying Configuration **List loaded servers:** ```bash claude mcp list ``` **Check debug logs (Windows):** ```text C:\Users\\.claude\debug\*.txt ``` Look for MCP server startup messages. Missing servers indicate configuration problems. --- ## Best Practices ### 1. Keep Configs Organized - **Global config:** Shared/production servers - **Project config:** Local development servers - **Never duplicate** the same server in both ### 2. Order Servers by Importance Place essential servers first in configuration: 1. `memory` - Knowledge persistence 2. `filesystem` - File access 3. `podman` - Container management 4. Other servers... ### 3. Use Direct Node Execution For faster startup, avoid npx and use direct node execution: ```json // Slow (npx downloads on each start) "command": "D:\\nodejs\\npx.cmd", "args": ["-y", "package-name"] // Fast (pre-installed) "command": "d:\\nodejs\\node.exe", "args": ["path/to/installed/dist/index.js"] ``` ### 4. Disable Instead of Delete Use `"disabled": true` to troubleshoot without losing configuration: ```json "problem-server": { "command": "...", "disabled": true } ``` ### 5. Test Manually First Before adding to config, verify server works: ```bash cd /path/to/mcp-server set ENV_VAR=value node dist/index.js ``` ### 6. Store Secrets Securely - Use the memory MCP to store API tokens for future sessions - Never commit `.mcp.json` with real tokens (add to `.gitignore`) - Use environment variables where possible ### 7. Restart After Changes MCP configuration changes require a full VS Code restart (not just window reload). --- ## Quick Reference ### Available MCP Packages | Server | Package/Source | npm? | | ------------------- | -------------------------------------------------- | ---------------------- | | memory | `@modelcontextprotocol/server-memory` | Yes | | filesystem | `@modelcontextprotocol/server-filesystem` | Yes | | redis | `@modelcontextprotocol/server-redis` | Yes | | postgres | `@modelcontextprotocol/server-postgres` | Yes | | sequential-thinking | `@modelcontextprotocol/server-sequential-thinking` | Yes | | podman | `podman-mcp-server` | Yes | | gitea | `gitea-mcp` (binary) | No | | bugsink | `j-shelfwood/bugsink-mcp` | No (build from source) | | sentry | `@sentry/mcp-server` | Yes | | playwright | `@anthropics/mcp-server-playwright` | Yes | ### Common Tool Prefixes | Server | Tool Prefix | Example | | -------------- | ------------------------- | -------------------------------------- | | Memory | `mcp__memory__` | `mcp__memory__read_graph` | | Filesystem | `mcp__filesystem__` | `mcp__filesystem__read_file` | | Podman | `mcp__podman__` | `mcp__podman__container_list` | | Redis | `mcp__redis__` | `mcp__redis__get` | | Bugsink (prod) | `mcp__bugsink__` | `mcp__bugsink__list_issues` | | Bugsink (dev) | `mcp__localerrors__` | `mcp__localerrors__list_issues` | | PostgreSQL | `mcp__devdb__` | `mcp__devdb__query` | | Gitea | `mcp__gitea-projectium__` | `mcp__gitea-projectium__list_my_repos` | --- ## Related Documentation - [CLAUDE.md - MCP Servers Section](../../CLAUDE.md#mcp-servers) - [DEV-CONTAINER-BUGSINK.md](../DEV-CONTAINER-BUGSINK.md) - [BUGSINK-SYNC.md](../BUGSINK-SYNC.md) - [sql/master_schema_rollup.sql](../../sql/master_schema_rollup.sql) --- _Last updated: January 2026_