uv
(uvenv
is an alias it provides)](#1--install-uv--uvenv-is-an-alias-it-provides)
+ - [2 · Create an on-the-spot venv & run the wrapper](#2--create-an-on-the-spot-venv--run-the-wrapper)
+ - [Claude Desktop JSON (runs through **uvenv run**)](#claude-desktop-json-runs-through-uvenv-run)
+ - [Using with Claude Desktop (or any GUI MCP client)](#-using-with-claude-desktop-or-any-gui-mcp-client)
+- [Quick Start: VS Code Dev Container](#-quick-start-vs-code-dev-container)
+ - [1 · Clone & Open](#1--clone--open)
+ - [2 · First-Time Build (Automatic)](#2--first-time-build-automatic)
+- [Quick Start (manual install)](#quick-start-manual-install)
+ - [Prerequisites](#prerequisites)
+ - [One-liner (dev)](#one-liner-dev)
+ - [Containerised (self-signed TLS)](#containerised-self-signed-tls)
+ - [Smoke-test the API](#smoke-test-the-api)
+- [Installation](#installation)
+ - [Via Make](#via-make)
+ - [UV (alternative)](#uv-alternative)
+ - [pip (alternative)](#pip-alternative)
+ - [Optional (PostgreSQL adapter)](#optional-postgresql-adapter)
+ - [Quick Postgres container](#quick-postgres-container)
+- [Configuration (`.env` or env vars)](#configuration-env-or-env-vars)
+ - [Basic](#basic)
+ - [Authentication](#authentication)
+ - [UI Features](#ui-features)
+ - [Security](#security)
+ - [Logging](#logging)
+ - [Transport](#transport)
+ - [Federation](#federation)
+ - [Resources](#resources)
+ - [Tools](#tools)
+ - [Prompts](#prompts)
+ - [Health Checks](#health-checks)
+ - [Database](#database)
+ - [Cache Backend](#cache-backend)
+ - [Development](#development)
+- [Running](#running)
+- [Makefile](#makefile)
+ - [Script helper](#script-helper)
+ - [Manual (Uvicorn)](#manual-uvicorn)
+- [Authentication examples](#authentication-examples)
+- [AWS / Azure / OpenShift](#️-aws--azure--openshift)
+- [IBM Cloud Code Engine Deployment](#️-ibm-cloud-code-engine-deployment)
+ - [Prerequisites](#-prerequisites)
+ - [Environment Variables](#-environment-variables)
+ - [Make Targets](#-make-targets)
+ - [Example Workflow](#-example-workflow)
+- [API Endpoints](#api-endpoints)
+- [Testing](#testing)
+- [Project Structure](#project-structure)
+- [API Documentation](#api-documentation)
+- [Makefile targets](#makefile-targets)
+- [Troubleshooting](#-troubleshooting)
+ - [Diagnose the listener](#diagnose-the-listener)
+ - [Why localhost fails on Windows](#why-localhost-fails-on-windows)
+ - [Fix (Podman rootless)](#fix-podman-rootless)
+ - [Fix (Docker Desktop > 4.19)](#fix-docker-desktop--419)
+- [Contributing](#contributing)
+- [Changelog](#changelog)
+- [License](#license)
+- [Core Authors and Maintainers](#core-authors-and-maintainers)
+- [Star History and Project Activity](#star-history-and-project-activity)
+
+
## 🚀 Overview & Goals
**ContextForge MCP Gateway** is a production-grade gateway, registry, and proxy that sits in front of any [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server or REST API—exposing a unified endpoint for all your AI clients.
@@ -30,7 +112,7 @@ It supports:
* Federation across multiple MCP and REST services
* Virtualization of legacy APIs as MCP-compliant tools and servers
-* Transport over HTTP, JSON-RPC, WebSocket, SSE, and stdio
+* Transport over HTTP, JSON-RPC, WebSocket, SSE, stdio and streamable-HTTP
* An Admin UI for real-time management and configuration
* Built-in auth, observability, retries, and rate-limiting
* Scalable deployments via Docker or PyPI, Redis-backed caching, and multi-cluster federation
@@ -51,7 +133,7 @@ For a list of upcoming features, check out the [ContextForge MCP Gateway Roadmap
Name: ${tool.name}
URL: ${tool.url}
Type: ${tool.integrationType}
@@ -566,11 +578,11 @@ async function viewTool(toolId) { ${authHTML}${JSON.stringify(tool.headers || {}, null, 2)}+
${JSON.stringify(tool.headers || {}, null, 2)}
${JSON.stringify(tool.inputSchema || {}, null, 2)}+
${JSON.stringify(tool.inputSchema || {}, null, 2)}
URI: ${resource.uri}
Name: ${resource.name}
Type: ${resource.mimeType || "N/A"}
@@ -787,7 +799,7 @@ async function viewPrompt(promptName) { ); const prompt = await response.json(); document.getElementById("prompt-details").innerHTML = ` -Name: ${prompt.name}
Description: ${prompt.description || "N/A"}
Status: @@ -807,7 +819,7 @@ async function viewPrompt(promptName) {
${JSON.stringify(prompt.arguments || [], null, 2)}+
${JSON.stringify(prompt.arguments || [], null, 2)}
Name: ${gateway.name}
URL: ${gateway.url}
Description: ${gateway.description || "N/A"}
+Transport: + ${gateway.transport === "STREAMABLEHTTP" ? "Streamable HTTP" : + gateway.transport === "SSE" ? "SSE" : "N/A"} +
Status:
${gateway.isActive ? "Active" : "Inactive"}
@@ -905,7 +921,7 @@ async function viewGateway(gatewayId) {
${authHTML}
${JSON.stringify(gateway.capabilities || {}, null, 2)}
+ ${JSON.stringify(gateway.capabilities || {}, null, 2)}
Name: ${server.name}
Description: ${server.description || "N/A"}
Status: @@ -1310,64 +1327,64 @@ async function loadAggregatedMetrics() { // Build an aggregated metrics table const tableHTML = ` -
Entity | -Total | -Successful | -Failed | -Failure Rate | -Min RT | -Max RT | -Avg RT | -Last Exec | +Entity | +Total | +Successful | +Failed | +Failure Rate | +Min RT | +Max RT | +Avg RT | +Last Exec |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Tools | -${toolsTotal} | -${toolsSuccess} | -${toolsFailed} | -${toolsFailureRate} | -${toolsMin} | -${toolsMax} | -${toolsAvg} | -${toolsLast} | +Tools | +${toolsTotal} | +${toolsSuccess} | +${toolsFailed} | +${toolsFailureRate} | +${toolsMin} | +${toolsMax} | +${toolsAvg} | +${toolsLast} |
Resources | -${resourcesTotal} | -${resourcesSuccess} | -${resourcesFailed} | -${resourcesFailureRate} | -${resourcesMin} | -${resourcesMax} | -${resourcesAvg} | -${resourcesLast} | +Resources | +${resourcesTotal} | +${resourcesSuccess} | +${resourcesFailed} | +${resourcesFailureRate} | +${resourcesMin} | +${resourcesMax} | +${resourcesAvg} | +${resourcesLast} |
Servers | -${serversTotal} | -${serversSuccess} | -${serversFailed} | -${serversFailureRate} | -${serversMin} | -${serversMax} | -${serversAvg} | -${serversLast} | +Servers | +${serversTotal} | +${serversSuccess} | +${serversFailed} | +${serversFailureRate} | +${serversMin} | +${serversMax} | +${serversAvg} | +${serversLast} |
Prompts | -${promptsTotal} | -${promptsSuccess} | -${promptsFailed} | -${promptsFailureRate} | -${promptsMin} | -${promptsMax} | -${promptsAvg} | -${promptsLast} | +Prompts | +${promptsTotal} | +${promptsSuccess} | +${promptsFailed} | +${promptsFailureRate} | +${promptsMin} | +${promptsMax} | +${promptsAvg} | +${promptsLast} |
ID | -Name | -Executions | +ID | +Name | +Executions |
---|
ID | -URI | -Name | -Executions | +ID | +URI | +Name | +Executions |
---|
ID | -Name | -Executions | +ID | +Name | +Executions |
---|
ID | -Name | -Executions | +ID | +Name | +Executions |
---|
Icon | ID | Name | Description | Tools | Resources | Prompts | Actions | |
---|---|---|---|---|---|---|---|---|
@@ -205,44 +213,44 @@ MCP Servers Catalogclass="h-8 w-8" /> {% else %} - N/A + N/A {% endif %} |
{{ server.id }} | {{ server.name }} | {{ server.description }} | -+ | {% if server.associatedTools %} {{ server.associatedTools | map('string') | join(', ') }} {% else %} - N/A + N/A {% endif %} | {% if server.associatedResources %} {{ server.associatedResources | join(', ') }} {% else %} - N/A + N/A {% endif %} | {% if server.associatedPrompts %} {{ server.associatedPrompts | join(', ') }} {% else %} - N/A + N/A {% endif %} |
@@ -279,7 +287,7 @@ MCP Servers Catalog{% endif %} @@ -310,70 +318,70 @@MCP Servers Catalog-
- Add New Server+
+ Add New Server |