NOUMENA MCP Gateway — a secure, policy-controlled proxy for Model Context Protocol servers.
Shield sits between AI clients and your MCP backend servers. It aggregates multiple MCP backends into a single endpoint, namespaces their tools and resources to avoid name conflicts, enforces Rego-based access policies, and optionally requires OAuth 2.0 bearer-token authentication on every connection.
Shield is designed to be immediately useful: a single command gives you a working gateway with no infrastructure required. The same configuration scales to enterprise deployments with authentication, fine-grained access policies, and a full audit trail — without the heavyweight setup that most enterprise MCP solutions demand.
- Multi-backend aggregation — proxy any number of stdio or HTTP MCP servers behind a single endpoint.
- Automatic namespacing — tools, resources, and prompts are prefixed with their backend name (e.g.
wikipedia:search) so name collisions across backends are impossible. - Policy engine — restrict tool access with OPA Rego policies. Enforcement applies when Rego policy files are loaded; configuring the policy engine without any loaded
.regofiles does not by itself deny access. - OAuth 2.0 authentication — validate bearer tokens via token introspection; advertise protected-resource metadata for automatic client discovery.
- Audit trail — every tool call, resource access, and prompt invocation is recorded with structured logs for compliance and debugging.
- Admin UI — built-in web interface (
:8080by default) with catalog browsing, session inspection, and audit log viewer. - Per-session isolation — every MCP client gets its own dedicated backend connections; one client cannot affect another.
- Go 1.26.1 or newer
- (Optional) Docker — required to run the demo backends or stdio backends that are packaged as containers
- (Optional) Node.js / npx — for the MCP Inspector client
Clone the repository and build the binary:
git clone https://github.com/noumenadigital/shield.git
cd shield
go build -o shield ./cmd/shieldOr run directly without building:
go run ./cmd/shield <command>Start a gateway with no backends (useful for a smoke-test):
go run ./cmd/shield serverThe MCP endpoint is now available at http://localhost:8081/mcp and the admin UI at http://localhost:8080/.
Connect an MCP client to the gateway using the MCP Inspector:
npx @modelcontextprotocol/inspector --server-url http://localhost:8081/mcp| Command | Description |
|---|---|
shield server |
Start the MCP gateway. Accepts -f <config.yaml> or -catalog <mcp.json> flag. |
shield from-catalog <mcp.json> |
Convert mcpServers JSON catalog file into a full YAML config and writes it to stdout. |
If you already have an mcp.json (e.g. from Claude Desktop or another MCP client), you can start a gateway immediately:
./shield server -catalog mcp.jsonTools from all listed backends are automatically aggregated and namespaced. For example, a search tool on a wikipedia backend becomes wikipedia:search.
Migrate from a JSON catalog to a full YAML configuration in one step:
./shield from-catalog mcp.json > config.yaml
./shield server -f config.yaml./shield server -f path/to/config.yamlShield is configured with a YAML file. The top-level sections are:
mcp: # MCP gateway listener (default port: 8081)
admin: # Admin web interface (default port: 8080)
backends: # Named backend MCP servers (stdio or HTTP)
policyEngine: # OPA Rego access-control policies (optional)
authentication: # OAuth 2.0 bearer-token authentication (optional)mcp:
port: 8081
backends:
wikipedia:
url: http://localhost:18000/mcp
local-tool:
command: /usr/local/bin/my-mcp-server
args: ["--verbose"]mcp:
port: 8081
backends:
wikipedia:
url: http://localhost:18000/mcp
policyEngine:
type: rego
source: "." # load *.rego files from the same directory
package: whitelistPlace .rego files next to the config file to whitelist tools:
# global-whitelist.rego
package whitelist
mcp.wikipedia.tools.search.allowed := trueauthentication:
identityProvider:
url: https://auth.example.com/realms/my-realm
clientID: shield-server
clientSecret: "env.SHIELD_CLIENT_SECRET"
scopes:
- profile
- emailFor the full configuration reference see docs/configuration.md.
For the full architecture reference see docs/architecture.md.
For the Rego policy authoring guide see docs/rego.md.
Check the installed version:
$ shield version
shield v0.1.0Shield exposes a health endpoint for load balancers and monitoring systems:
$ curl http://localhost:8081/health
{
"status": "ok",
"name": "noumena-shield",
"version": "<build-tag-or-dev>",
"time": "YYYY-MM-DDTHH:MM:SSZ"
}Endpoint Details:
- Path:
/health - HTTP Method: GET
- Response Code: 200 OK (when healthy)
- Content-Type:
application/json - Authentication: Not required (always accessible)
- Response Fields:
status: Server status ("ok"when healthy)name: Server name ("noumena-shield")version: Server version (injected from the build tag; defaults to"dev"for local/non-release builds)time: Current UTC time in RFC3339 format
This endpoint is useful for:
- Kubernetes liveness/readiness probes: Configure your container orchestration to periodically check
/health - Load balancer health checks: Route traffic only to healthy Shield instances
- Monitoring systems: Verify Shield is running and responsive
Shield uses GitHub Actions and GoReleaser to automate semantic versioning and releases.
-
Trigger the release workflow via GitHub Actions:
- Go to Actions → Release workflow → "Run workflow"
- Enter a version (e.g.,
0.2.0orv0.2.0) — both formats are accepted - The workflow normalizes the version to
v-prefixed semver (v0.2.0) - The workflow validates the semver format and checks that the tag doesn't already exist
-
Automated steps:
- GoReleaser builds and archives binaries for:
- Platforms: Linux, macOS, Windows
- Architectures: amd64, arm64
- Format:
shield-{os}-{arch}.tar.gz(.zipfor Windows)
- Generates SHA256 checksums
- Automatically extracts release notes from commit messages since the last release
- Creates a GitHub release with all artifacts
- Uses: default
GITHUB_TOKENprovided by GitHub Actions (workflow grantscontents: write)
- GoReleaser builds and archives binaries for:
The binary version is automatically injected at build time via GoReleaser using the git tag:
var version = "dev" // Set to the git tag (e.g., v0.1.0) at build timeThe version is printed by the shield version command and must match the git tag.
- Fork the repository and create a feature branch.
- Install pre-commit hooks (enforces
go fmt,go vet,golangci-lint, and tests on every commit):pre-commit install
- Make your changes, ensuring all tests pass:
go test -short ./... - Open a pull request with a clear description of your change.
Shield is licensed under the Apache License 2.0.