MCP Hub
Back to servers

@forgespace/mcp-gateway-client

Forge MCP Gateway client - Connect to your Forge MCP Gateway instance via NPX

npm155/wk
Updated
Mar 11, 2026

Quick Install

npx -y @forgespace/mcp-gateway-client
Forge Space

Forge MCP Gateway

AI-powered MCP tool routing hub — part of the Forge Space open developer workspace.

CI Pipeline License: MIT Python Docker PRs Welcome

Self-hosted gateway using IBM Context Forge with AI-driven optimization, predictive scaling, ML monitoring, and enterprise security. Connect any MCP server, route intelligently, manage via admin UI.

One connection from Cursor (or other MCP clients) to the gateway; add upstream MCP servers via the Admin UI.

GitHub repo description (paste in Settings → General → Description, 350 char max):

Self-hosted Forge MCP gateway using IBM Context Forge. One Cursor (or MCP client) connection; add upstream servers via Admin UI. Docker, virtual servers, tool-router. MIT.

License: MIT

Prerequisites

  • Docker
  • Docker Compose V2 (docker compose) or V1 (docker-compose)

Optional: Dev Container for one-click lint/test (shellcheck, ruff, pytest) without installing them on the host. Part of the Forge Space Ecosystem - Complete AI-powered development platform.

Quick start

cp .env.example .env
# Edit .env: set PLATFORM_ADMIN_EMAIL, PLATFORM_ADMIN_PASSWORD, JWT_SECRET_KEY, AUTH_ENCRYPTION_SECRET (min 32 chars each). Run: make generate-secrets
make start

Then run make register to register gateways and get the Cursor URL.

Admin UI boot contract:

  • NEXT_PUBLIC_SUPABASE_URL must be a valid http or https URL
  • NEXT_PUBLIC_SUPABASE_ANON_KEY must be present
  • if either value is missing or invalid, the admin shell stays bootable and shows a configuration-required state instead of crashing at import time
  • monitoring dashboard service rows are keyboard-operable and do not rely on clickable non-semantic containers

Wrapper Bridge (Recommended)

Use the wrapper bridge as the stable MCP client entrypoint:

{
  "mcpServers": {
    "forge-mcp-gateway": {
      "command": "/absolute/path/to/forge-mcp-gateway/scripts/mcp-wrapper.sh",
      "env": {
        "MCP_CLIENT_SERVER_URL": "http://localhost:4444/servers/<UUID>/mcp"
      },
      "timeout": 120000
    }
  }
}

Get your configuration:

  1. Start gateway: make start
  2. Register servers: make register (saves URL to data/.mcp-client-url)
  3. Run ./scripts/setup-forge-space-mcp.sh to configure your IDE mcp config safely
    • If make register cannot produce data/.mcp-client-url (minimal mode), run: ./scripts/setup-forge-space-mcp.sh --mcp-url http://host.docker.internal:4444/servers/<UUID>/mcp

NPX Client Status

@forgespace/mcp-gateway-client is resolvable on npm. Wrapper-first setup remains the recommended IDE path for homelab stability, while direct npx is available for smoke checks and manual use.

Maintainer release path:

  1. Confirm scope/token access: npm whoami && npm access list packages @forgespace --json
    • npm access ... is advisory; definitive permission is validated by the publish step.
  2. Run publish workflow: gh workflow run npm-release-core.yml -f publish=true -f npm_tag=latest
  3. Verify package availability: npm view @forgespace/mcp-gateway-client version
  4. Verify CLI entrypoint through workflow logs:
    • check Verify published package resolvability in npm-release-core.yml
    • the workflow runs a retried CLI smoke invocation after package resolvability succeeds.

Default make start (or ./start.sh) starts the gateway and all local servers (e.g. sequential-thinking). Use make gateway-only (or ./start.sh gateway-only) for the gateway alone. Data is stored in ./data (SQLite). Add gateways in Admin UI or run make register after start; create a virtual server, attach tools, note its UUID.

Registering URL-based MCP servers

Servers that expose an HTTP/SSE URL can be added as gateways so one Cursor connection reaches them through Context Forge. Either add them in Admin UI (MCP ServersAdd New MCP Server or Gateway) or run once the gateway is up:

make register

(or ./scripts/register-gateways.sh). The command is idempotent: if a gateway name already exists (e.g. after restart with the same DB), it reports "OK name (already registered)" instead of failing. It waits up to 90s for the gateway to respond at /health (override with REGISTER_GATEWAY_MAX_WAIT). If the first URL fails (e.g. 127.0.0.1 on Docker Desktop), it retries with localhost or vice versa. If still unreachable, run docker compose ps gateway and docker compose logs gateway. If a gateway shows FAIL, the gateway could not initialize the remote URL (see Troubleshooting). Run REGISTER_VERBOSE=1 make register to see the full API response. For local SSE gateways (e.g. sqlite, desktop-commander, github), the script retries once after 15s on "Unable to connect" or "Unexpected error". If all local gateways fail, translate containers may still be starting (first run pulls npm packages): wait 30–60s and run again, or set REGISTER_WAIT_SECONDS=30 in .env or run make register-wait.

make register reads scripts/gateways.txt (one line per gateway: Name|URL or Name|URL|Transport) or the EXTRA_GATEWAYS env var (comma-separated). Default gateways.txt registers local servers up to snyk (sequential-thinking through snyk). sqlite, github, and Context7 are commented out (they often fail with "Unable to connect" or "Unexpected error"; uncomment after checking docker compose logs sqlite|github or add Context7/sqlite/github via Admin UI). .env.example sets REGISTER_WAIT_SECONDS=30 so translate containers are ready before registration. After make start, run make register (or make register-wait to force a 30s wait). After registering gateways, the script creates or updates virtual server(s) and prints Cursor URLs. Cursor (and some other MCP clients) can only handle about 60 tools per connection; if you register many gateways, a single virtual server with all tools can trigger a warning. To stay under the limit, use multiple virtual servers, each with a subset of gateways:

  • With config/virtual-servers.txt: One line per server: ServerName|gateway1,gateway2,.... The script creates or updates each named server with up to 60 tools from those gateways and prints one URL per server. Connect Cursor to one URL (e.g. cursor-default for general dev, cursor-search for search/docs). See scripts/README.md and docs/AI_USAGE.md.
  • Single entry point (router): The cursor-router virtual server is the default for the wrapper. It exposes only the tool-router gateway (1–2 tools). Set GATEWAY_JWT in .env (run make jwt and paste the token; refresh periodically, e.g. weekly) so the router can call the gateway API. See docs/AI_USAGE.md.
  • Without virtual-servers.txt: A single virtual server (name default or REGISTER_VIRTUAL_SERVER_NAME) gets all tools; fine if you have few gateways. Example remote entries:
NameURLTransport
Context7https://mcp.context7.com/mcpStreamable HTTP
context-awesomehttps://www.context-awesome.com/api/mcpStreamable HTTP
prisma-remotehttps://mcp.prisma.io/mcpStreamable HTTP
cloudflare-observabilityhttps://observability.mcp.cloudflare.com/mcpStreamable HTTP
cloudflare-bindingshttps://bindings.mcp.cloudflare.com/mcpStreamable HTTP

Auth (v0, apify-dribbble, etc.): Add the gateway in Admin UI, then edit it and set Passthrough Headers (e.g. Authorization) or Authentication type OAuth so the gateway sends the token. Do not put secrets in gateways.txt or in the repo. For the exact Context Forge structure (gateway, virtual server, prompts, resources) and which registrations need manual steps, see docs/ADMIN_UI_MANUAL_REGISTRATION.md.

Some remote URLs may show "Failed to initialize" (e.g. context-awesome returns 406 from this gateway). See Troubleshooting below. Stdio-only servers (e.g. sequential-thinking) need the translate setup in the next section or stay in Cursor.

Local servers (stdio → SSE)

The default ./start.sh starts the gateway and these local translate services (stdio → SSE):

Gateway nameURL (internal)Notes
sequential-thinkinghttp://sequential-thinking:8013/sse
chrome-devtoolshttp://chrome-devtools:8014/sse
playwrighthttp://playwright:8015/sse
magicuidesign-mcphttp://magicuidesign-mcp:8016/sse@magicuidesign/mcp
desktop-commanderhttp://desktop-commander:8017/sse
puppeteerhttp://puppeteer:8018/sse
browser-toolshttp://browser-tools:8019/sse
tavilyhttp://tavily:8020/sseSet TAVILY_API_KEY in .env
filesystemhttp://filesystem:8021/sseSet FILESYSTEM_VOLUME (host path) in .env; default ./workspace
reactbitshttp://reactbits:8022/ssereactbits-dev-mcp-server
snykhttp://snyk:8023/sseSet SNYK_TOKEN in .env (Snyk CLI auth)
memoryhttp://memory:8027/ssePersistent knowledge graph; data in ./data/memory (no API key)
git-mcphttp://git-mcp:8028/sseLocal git operations: commit, branch, diff, log (no API key)
fetchhttp://fetch:8029/sseWeb content fetching to markdown for LLM use (no API key)
postgreshttp://postgres:8031/sseSet POSTGRES_CONNECTION_STRING in .env; see Multi-User Config
mongodbhttp://mongodb:8032/sseSet MONGODB_CONNECTION_STRING in .env; see Multi-User Config
tool-routerhttp://tool-router:8030/sseSingle entry point; set GATEWAY_JWT in .env (see cursor-router)
sqlitehttp://sqlite:8024/sseSet SQLITE_DB_PATH / SQLITE_VOLUME in .env; default ./data
githubhttp://github:8025/sseSet GITHUB_PERSONAL_ACCESS_TOKEN in .env
uihttp://ui:8026/sseAI-driven UI generation (7 tools); set FIGMA_ACCESS_TOKEN in .env for Figma sync

After start, run make register to register them (or add in Admin UI with the URLs above, Transport SSE). This creates or updates a virtual server and prints its Cursor URL. Attach tools in Admin UI if you skip that step. Optional: set REGISTER_PROMPTS=true and add config/prompts.txt (format: name|description|template with {{arg}} and \n for newlines), then run make register. Use make gateway-only to run only the gateway (no translate services).

Stack-focused gateways (React, Node, TypeScript, Java, Spring, Prisma, etc.): config/gateways.txt includes local SSE servers and optional remote entries (Context7, context-awesome, prisma-remote). Add more via EXTRA_GATEWAYS in .env. Next.js (next-devtools-mcp) is project-local; run it inside your Next app. Spring AI MCP runs on the host; add its URL to EXTRA_GATEWAYS if you expose it.

Servers that stay in Cursor or as remote gateways: context-forge (gateway wrapper), browserstack, infisical-lukbot use custom scripts or tokens; run them on the host or add their HTTP URL in Admin UI if you expose them. Remote-only servers (Context7, context-awesome, prisma, cloudflare-*, v0, apify-dribbble) add as gateways with URL; v0 and apify need Passthrough Headers or OAuth in Admin UI.

Connect Cursor

The gateway requires a Bearer JWT on every request.

Automatic JWT (recommended) Use the wrapper script so no token is stored in mcp.json and no weekly refresh is needed. From the repo: ensure .env is set, run make register once (this writes data/.mcp-client-url), then run ./scripts/setup-forge-space-mcp.sh to set the context-forge entry in your IDE mcp config to the wrapper. The wrapper config includes a 2-minute MCP timeout to avoid "Request timed out" (-32001); set CURSOR_MCP_TIMEOUT_MS in .env (e.g. 180000) to change it. Before first use, run make cursor-pull so the Context Forge Docker image is cached and the first IDE connection does not time out while the image downloads. Restart your IDE. The wrapper uses the mcp-router virtual server by default; set REGISTER_MCP_CLIENT_SERVER_NAME=cursor-default in .env and run make register to use the full tool set instead. The wrapper generates a fresh JWT on each connection and runs the gateway Docker image. On Linux the script adds --add-host=host.docker.internal:host-gateway automatically. Optional: set MCP_CLIENT_SERVER_URL in your IDE config if you prefer not to use data/.mcp-client-url, or pass --mcp-url directly to ./scripts/setup-forge-space-mcp.sh. To configure manually instead, set the entry to {"command": "/absolute/path/to/forge-mcp-gateway/scripts/mcp-wrapper.sh", "timeout": 120000} (use your clone path).

Manual JWT (URL-based or docker args)

  1. Generate a JWT (e.g. 1 week): run make jwt (or make refresh-cursor-jwt to update the token in mcp.json in place; run weekly or before opening Cursor).

    Or run:

    docker exec mcpgateway python3 -m mcpgateway.utils.create_jwt_token \
      --username "$PLATFORM_ADMIN_EMAIL" --exp 10080 --secret "$JWT_SECRET_KEY"
    
  2. Add to ~/.cursor/mcp.json (docker wrapper with token in args):

    {
      "mcpServers": {
        "context-forge": {
          "command": "docker",
          "args": [
            "run",
            "--rm",
            "-i",
            "-e",
            "MCP_SERVER_URL=http://host.docker.internal:4444/servers/YOUR_SERVER_UUID/mcp",
            "-e",
            "MCP_AUTH=Bearer YOUR_JWT_TOKEN",
            "-e",
            "MCP_TOOL_CALL_TIMEOUT=120",
            "ghcr.io/ibm/mcp-context-forge:1.0.0-BETA-2",
            "python3",
            "-m",
            "mcpgateway.wrapper"
          ]
        }
      }
    }
    

    On Linux add after "-i": "--add-host=host.docker.internal:host-gateway". Restart Cursor after changing the config.

    Alternative: URL-based (Streamable HTTP or SSE) Example with your server UUID and a token in headers:

    "context-forge": {
      "type": "streamableHttp",
      "url": "http://localhost:4444/servers/YOUR_SERVER_UUID/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_JWT_TOKEN"
      }
    }
    

    For SSE use "type": "sse" and path .../servers/YOUR_SERVER_UUID/sse. Both require Authorization: Bearer YOUR_JWT_TOKEN. To avoid storing the token in mcp.json, use the Automatic JWT wrapper or the docker wrapper above. To refresh the token in mcp.json without copy-paste, run make refresh-cursor-jwt (e.g. weekly via cron: 0 9 * * 0 or a launchd plist).

Environment

See .env.example. Required: PLATFORM_ADMIN_EMAIL, PLATFORM_ADMIN_PASSWORD, JWT_SECRET_KEY, AUTH_ENCRYPTION_SECRET (each at least 32 chars; run make generate-secrets). Never commit .env or secrets.

CI Tenant Contract

The test-autogen-warn workflow job requires these repository variables:

  • FORGE_TENANT_ID
  • FORGE_TENANT_PROFILE_REF

CI attempts a best-effort checkout of Forge-Space/forge-tenant-profiles for warn-only parity. For private profile access, configure FORGE_TENANT_PROFILES_READ_TOKEN. If the profile repo, repository variables, or resolved profile path are unavailable, parity is skipped and the warn-only flow remains non-blocking.

Automated Maintenance

This repository includes automated workflows for dependency updates, MCP server discovery, and Docker image updates.

Dependency Updates (Renovate)

Schedule: Every Monday at 2 AM UTC

Renovate automatically checks for updates to:

  • Python dependencies (requirements.txt)
  • Docker images (Context Forge gateway)
  • GitHub Actions

Auto-merge policy:

  • ✅ Patch/minor updates: Auto-merge after 3-day stabilization + passing CI
  • ❌ Major updates: Require manual review (labeled breaking-change)
  • 🔒 Security vulnerabilities: Immediate auto-merge

Setup: Add RENOVATE_TOKEN secret to repository settings (GitHub PAT with repo and workflow scopes).

Dashboard: Check the Dependency Dashboard issue for pending updates.

MCP Server Registry Check

Schedule: Every Monday at 3 AM UTC

Automatically scans the MCP Registry for:

  • New servers not in gateways.txt
  • Status of commented servers (auth requirements, etc.)

Creates/updates a GitHub issue with findings. No secrets required.

Docker Image Updates

Schedule: Every Monday at 4 AM UTC

Checks IBM/mcp-context-forge for new releases and automatically creates PRs with:

  • Updated image tags in all files
  • Changelog link
  • Testing checklist

PRs require manual review before merge.

n8n Automation

Self-hosted n8n workflow automation for CI alerts, security advisories, cross-repo release coordination, and monitoring. Runs in Docker alongside the gateway but in its own compose file.

Setup

cp .env.n8n.example .env.n8n
make n8n-secrets          # generate webhook HMAC secrets
# paste secrets into .env.n8n, configure GitHub token + Slack webhook
make n8n-start
# open http://localhost:5678 and import workflows from n8n-workflows/

Workflows

#WorkflowTriggerPhase
1CI Failure AlertGitHub webhook (workflow_run)1
2Security Advisory AggregatorDaily 9 AM cron1
3Upstream Release NotifierGitHub webhook (release)2
4Stale PR ReminderDaily 10 AM weekdays2
5Weekly Velocity ReportMonday 9 AM cron3
6Docker Health MonitorEvery 5 minutes3

Commands

make n8n-start     # start n8n container
make n8n-stop      # stop n8n
make n8n-logs      # tail logs
make n8n-health    # health check
make n8n-backup    # export workflows
make n8n-secrets   # generate webhook secrets

Security

  • Localhost-only access (127.0.0.1:5678)
  • HMAC-SHA256 signature verification on all GitHub webhooks
  • One unique secret per workflow
  • Resource-limited: 0.5 CPU, 512MB RAM, 50 PIDs
  • Read-only GitHub API access (no merging, no deploying)
  • n8n data excluded from git (n8n-data/, n8n-logs/)
  • JSON-RPC and SSE error responses redact internal exception details; full traces stay server-side.
  • /rpc/stream quality events include an additive security_spoke report block (v1, advisory fail-open, DAST hooks telemetry only).

API Documentation

The gateway exposes an auto-generated OpenAPI spec with all 21 endpoints documented:

  • Swagger UI: http://localhost:8030/docs
  • ReDoc: http://localhost:8030/redoc
  • OpenAPI JSON: http://localhost:8030/openapi.json

Endpoints are grouped by tag: rpc (JSON-RPC tool execution), audit (governance trail), health (probes), monitoring (cache/performance metrics).

Development

  • Workflow and adding gateways/prompts: docs/DEVELOPMENT.md
  • Script index: scripts/README.md
  • Maintenance automation: See Automated Maintenance above
  • Lint baseline: ruff check tool_router/ dribbble_mcp/ is enforced in CI and includes test files (import ordering and unused unpacked variables fail the lint job).

Trunk Based Development Workflow

This project uses Trunk Based Development with the following branch strategy:

Branch Structure

  • main: Production-ready code, always deployable
  • dev: Development environment branch, continuously deployed
  • release/x.y.z: Release preparation branches
  • feature/*: Feature development branches

Workflow

  1. Feature Development

    git checkout dev
    git pull origin dev
    git checkout -b feature/your-feature-name dev
    # Make your changes
    git commit -m "feat: add your feature"
    git push origin feature/your-feature-name
    
  2. Testing & Review

    • Create PR from feature/your-feature-name to release/x.y.z
    • All CI tests must pass
    • Code review required
  3. Release Preparation

    git checkout release/x.y.z
    git merge feature/your-feature-name
    git push origin release/x.y.z
    
  4. Production Deployment

    git checkout main
    git merge release/x.y.z
    git tag v1.2.3
    git push origin main --tags
    

Branch Protection

  • main: Require PR approval, passing CI, no force pushes
  • release/*: Require PR approval and passing CI
  • dev: Require passing CI only

Environment Configuration

  • Dev Environment: Uses .env.development, auto-deployed from dev branch
  • Production Environment: Uses .env.production, deployed from main merges

Using the gateway with AI

Which tools to use for planning, docs, search, browser, DB: docs/AI_USAGE.md.

🏗️ Shared Package Structure

This project uses a centralized shared package structure for UIForge-wide standardization:

.github/shared/
├── workflows/           # Reusable CI/CD templates
├── configs/             # Shared configurations
├── scripts/            # Utility scripts
├── templates/          # GitHub templates
└── README.md           # Comprehensive documentation

Key Benefits

  • 40% reduction in duplicate configurations
  • Standardized CI/CD pipelines across UIForge projects
  • Unified security scanning and dependency management
  • Automated setup with symlink management

Usage

  • Setup: Run ./scripts/setup-shared-symlinks.sh to create configuration links
  • Documentation: See .github/shared/README.md for detailed usage
  • Migration: Use docs/UIFORGE_MIGRATION_GUIDE.md for other projects

CI/CD Pipeline

The main workflow (.github/workflows/ci.yml) uses shared templates:

jobs:
  ci:
    uses: ./.github/shared/workflows/base-ci.yml
    with:
      project-type: 'gateway'
      node-version: '22'
      python-version: '3.12'

Troubleshooting

403 "Insufficient permissions. Required: admin.dashboard" on /admin The admin UI requires an authenticated user with the admin.dashboard permission. Open the gateway root or login page first (e.g. http://localhost:4444/ or http://localhost:4444/login), sign in with PLATFORM_ADMIN_EMAIL and PLATFORM_ADMIN_PASSWORD from your .env, then go to http://localhost:4444/admin. If the browser prompts for credentials, use the same email and password. Do not put secrets in the repo; keep them only in .env.

"Failed to initialize gateway" when adding a gateway The gateway (Context Forge) checks the URL when you save. Common causes: (1) Remote server down or unreachable from the container. (2) Wrong URL or path (e.g. some servers need /sse). (3) Server rejects the request — e.g. Context Awesome (https://www.context-awesome.com/api/mcp) returns 406 unless the client sends Accept: application/json, text/event-stream; if Context Forge does not send that header, initialization fails and this is an upstream limitation. Workaround: use the server from a client that supports that URL (e.g. Cursor with the URL in mcp.json) or watch Context Forge for fixes.

If you see "Failed to initialize gateway" or "Unable to connect to gateway" for all local gateways when running make register, the translate services must listen on 0.0.0.0 so the gateway container can reach them (docker-compose already uses --host 0.0.0.0). If you changed the translate command, add --host 0.0.0.0. Otherwise, translate containers may still be starting (first run can take 30–60s while npx installs packages): wait and run make register again, or run make register-wait (or REGISTER_WAIT_SECONDS=30 make register). If only one local gateway (e.g. sqlite) fails, the same wait-and-retry usually fixes it. Ensure make start was used (not make gateway-only) and docker compose ps shows the translate services running. If translate containers are Restarting, they may be crashing (e.g. missing npx in the image): rebuild with docker compose build --no-cache sequential-thinking, then make stop and make start.

Script hangs on "Waiting for gateway" The register script polls the gateway for up to 90s. On Docker Desktop for Mac, if you use GATEWAY_URL=http://127.0.0.1:4444, the script now tries localhost first. If it still hangs, set GATEWAY_URL=http://localhost:4444 in .env.

MCP Registry shows "Failed" for some servers When you add a server from the registry, the gateway validates it (connects and lists tools). Failure usually means the remote server is down, slow, or unreachable from the gateway. Try Click to Retry. If it still fails, add the gateway manually: Gateways → New Gateway, enter the same name and URL (e.g. https://mcp.deepwiki.com/sse). Servers that need OAuth show "OAuth Config Required" in the registry; after adding them, edit the gateway and set Authentication type to OAuth with the provider’s client ID, secret, and URLs (see Context Forge OAuth docs).

context-forge shows "Error" / "Needs authentication" / "Loading tools" forever, or logs "Server disconnected without sending a response" / "No server info found" Often caused by weak JWT_SECRET_KEY or AUTH_ENCRYPTION_SECRET (gateway logs: "Secret has low entropy", "Secret should be at least 32 characters"). Fix: run make generate-secrets, add the two lines to .env, then make stop, make start, make register, and fully quit Cursor (Cmd+Q / Alt+F4) and reopen. Reload Window is not enough. If that’s not the cause:

  • If you use the wrapper (recommended): Run python3 scripts/ide-setup.py setup cursor --action verify to check gateway, data/.mcp-client-url, server existence, Context Forge image, and gateway reachability from Docker. If any check fails, run make start then make register, then rerun ./scripts/setup-forge-space-mcp.sh and fully restart your IDE. Run make cursor-pull once so the first IDE start does not timeout while the image downloads. To use the default mcp-router (tool-router): remove or comment out REGISTER_MCP_CLIENT_SERVER_NAME in .env, run make register, then restart the IDE. If you have REGISTER_MCP_CLIENT_SERVER_NAME=cursor-default in .env, the wrapper uses cursor-default; the URL in data/.mcp-client-url is only updated when you run make register. If logs show "No server info found": (1) Ensure the gateway is running (make start) and reachable from Docker (the wrapper runs in a container and uses host.docker.internal:4444). (2) Run make register to refresh the URL, then restart the IDE. (3) For mcp-router, set GATEWAY_JWT in .env (run make jwt and paste) so the router can call the gateway. If logs show "Request timed out" (MCP error -32001): (1) Run make cursor-pull so the Context Forge image is cached. (2) Rerun ./scripts/setup-forge-space-mcp.sh after setting CURSOR_MCP_TIMEOUT_MS=180000 in .env if needed. (3) Fully restart the IDE. If make register reports GET /servers returned 404, the gateway is in minimal mode and cannot write data/.mcp-client-url; run ./scripts/setup-forge-space-mcp.sh --mcp-url <server-url> and keep the URL in MCP_CLIENT_SERVER_URL in your IDE entry.

  • If you use a manual JWT (URL in mcp.json): (1) make start (ensure gateway is running). (2) make refresh-cursor-jwt (updates the Bearer token in ~/.cursor/mcp.json for the context-forge entry; the script also finds user-context-forge if that’s the key Cursor uses). (3) Restart Cursor. Your URL must end with /mcp or /sse. If Cursor is on the host and the gateway runs in Docker, use http://host.docker.internal:4444/servers/UUID/mcp. Alternatively switch to the wrapper with ./scripts/setup-forge-space-mcp.sh.

"Method Not Allowed" or "Invalid OAuth error response" when connecting Cursor to context-forge You are using a URL like http://localhost:4444/servers/UUID without a transport path. Use /sse for SSE or /mcp for streamable HTTP (e.g. .../servers/UUID/sse). You must also send the JWT: use the docker wrapper with MCP_SERVER_URL=.../servers/UUID/mcp and MCP_AUTH=Bearer YOUR_JWT_TOKEN, or add headers: { "Authorization": "Bearer YOUR_JWT_TOKEN" } to the SSE URL config.

500 on /admin (gateways/partial, prompts/partial) or "Loading gateways..." / "Loading prompts..." never finish The admin UI loads data from the gateway backend; when the backend returns 500, those requests fail. A common cause is a corrupted SQLite database. Check gateway logs: docker compose logs gateway --tail 100. If you see sqlite3.DatabaseError: database disk image is malformed, follow the recovery steps in the next bullet (stop, remove ./data/mcp.db and WAL/SHM, restart). Then run make register again to re-register gateways. See data/README.md. You can run make reset-db to stop the stack and remove the DB files in one step, then make start and make register.

"database disk image is malformed" or "FileLock health check failed" The SQLite database in ./data/mcp.db is corrupted (e.g. after a hard shutdown or disk issue). Stop the stack, remove the DB file (and mcp.db-shm, mcp.db-wal if present), and restart so the gateway creates a fresh database. Use make reset-db then make start (and make register to re-add gateways). See data/README.md.

Admin "Prompts" page stuck on "Loading prompts..." The Context Forge admin UI at /admin/#prompts can hang due to an upstream frontend/API mismatch or slow response. Workarounds: (1) Use the API: run make jwt to get a token, then curl -H "Authorization: Bearer <token>" <gateway>/prompts. (2) Register prompts via Make: set REGISTER_PROMPTS=true in .env and add lines to config/prompts.txt (format: name|description|template), then run make register. (3) Inspect in browser: DevTools → Network, filter by "prompts" or XHR; check the request URL, status, and response body. If the API returns 200 with valid JSON and the UI still spins, report to IBM/mcp-context-forge. A CSP error in the console for fonts.googleapis.com is unrelated to prompts loading.

Missing servers and authentication Some gateways are commented out in config/gateways.txt so make register succeeds by default. To enable them:

  • Commented local (sqlite, github): Uncomment the corresponding lines in config/gateways.txt, set the required env vars in .env (e.g. GITHUB_PERSONAL_ACCESS_TOKEN for github), run make register or make register-wait. If they fail, see the "Failed to initialize gateway" / "Unable to connect" bullets above and docker compose logs sqlite or docker compose logs github.
  • Commented remote (Context7, context-awesome, prisma-remote, cloudflare-*, v0, apify-dribbble): Uncomment in scripts/gateways.txt and run make register, or add the gateway via Admin UI (MCP Servers → Add New MCP Server or Gateway). For Context7, v0, apify-dribbble, cloudflare-*: after adding the gateway, edit it in Admin UI and set Passthrough Headers (e.g. Authorization) or Authentication type OAuth so the gateway can call the upstream. See docs/ADMIN_UI_MANUAL_REGISTRATION.md.

Authentication checklist: Local gateways that need keys: TavilyTAVILY_API_KEY in .env; SnykSNYK_TOKEN; GitHubGITHUB_PERSONAL_ACCESS_TOKEN. Remote gateways Context7, v0, apify-dribbble, cloudflare-* → configure Passthrough Headers or OAuth in Admin UI (do not put secrets in config/gateways.txt or the repo).

Contributing / Forking

You can fork this repo to run your own MCP gateway stack. After forking: copy .env.example to .env, set secrets (make generate-secrets), then make start and make register. To contribute back: run make lint and make test, open a PR with a clear description; see CHANGELOG.md for the project’s change conventions.

References

Reviews

No reviews yet

Sign in to write a review