A Go port of FlowGuard - a gateway for Model Context Protocol (MCP) servers.
- Configuration Modes: Supports both TOML files and JSON stdin configuration
- Routing Modes:
- Routed: Each backend server accessible at
/mcp/{serverID} - Unified: Single endpoint
/mcpthat routes to configured servers
- Routed: Each backend server accessible at
- Docker Support: Launch backend MCP servers as Docker containers
- Stdio Transport: JSON-RPC 2.0 over stdin/stdout for MCP communication
- Docker installed and running
- Go 1.23+ for building from source
-
Build the binary
go build -o flowguard-go
-
Create your environment file
cp example.env .env
-
Create a GitHub Personal Access Token
- Go to https://github.com/settings/tokens
- Click "Generate new token (classic)"
- Select scopes as needed (e.g.,
repofor repository access) - Copy the generated token
-
Add your token to
.envReplace the placeholder value with your actual token:
sed -i '' 's/GITHUB_PERSONAL_ACCESS_TOKEN=.*/GITHUB_PERSONAL_ACCESS_TOKEN=your_token_here/' .env
Or edit
.envmanually and replace the value ofGITHUB_PERSONAL_ACCESS_TOKEN. -
Pull required Docker images
docker pull ghcr.io/github/github-mcp-server:latest docker pull mcp/fetch docker pull mcp/memory
-
Start FlowGuard
In one terminal, run:
./run.sh
This will start FlowGuard in routed mode on
http://127.0.0.1:8000. -
Run Codex (in another terminal)
cp ~/.codex/config.toml ~/.codex/config.toml.bak && cp agent-configs/codex.config.toml ~/.codex/config.toml AGENT_ID=demo-agent codex
You can use '/mcp' in codex to list the available tools.
That's it! FlowGuard is now proxying MCP requests to your configured backend servers.
When you're done you can restore your old codex config file:
cp ~/.codex/config.toml.bak ~/.codex/config.toml
You can test the MCP server directly using curl commands:
MCP_URL="http://127.0.0.1:8000/mcp/github"
SESSION_ID=$(
curl -isS -X POST $MCP_URL \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Authorization: Bearer demo-agent' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"1.0.0","capabilities":{},"clientInfo":{"name":"curl","version":"0.1"}}}' \
| awk 'BEGIN{IGNORECASE=1} /^mcp-session-id:/{print $2}' | tr -d '\r'
)
echo "Session ID: $SESSION_ID"curl -s \
-H "Content-Type: application/json" \
-H "Mcp-Session-Id: $SESSION_ID" \
-H 'Authorization: Bearer demo-agent' \
-X POST \
$MCP_URL \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}'If you prefer to run manually without the run.sh script:
# Run with TOML config
./flowguard-go --config config.toml
# Run with JSON stdin config
echo '{"mcpServers": {...}}' | ./flowguard-go --config-stdin[servers]
[servers.github]
command = "docker"
args = ["run", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "-i", "ghcr.io/github/github-mcp-server:latest"]
[servers.filesystem]
command = "node"
args = ["/path/to/filesystem-server.js"]{
"mcpServers": {
"github": {
"type": "local",
"container": "ghcr.io/github/github-mcp-server:latest",
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": ""
},
}
}
}Environment Variable Passthrough: Set the value to an empty string ("") to pass through the variable from the host environment.
FlowGuard is a proxy server for Model Context Protocol (MCP) servers.
It provides routing, aggregation, and management of multiple MCP backend servers.
Usage:
flowguard-go [flags]
Flags:
-c, --config string Path to config file (default "config.toml")
--config-stdin Read MCP server configuration from stdin (JSON format). When enabled, overrides --config
--env string Path to .env file to load environment variables
-h, --help help for flowguard-go
-l, --listen string HTTP server listen address (default "127.0.0.1:3000")
--routed Run in routed mode (each backend at /mcp/<server>)
--unified Run in unified mode (all backends at /mcp)
docker build -t flowguard-go .docker run --rm -v $(pwd)/.env:/app/.env \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 8000:8000 \
flowguard-goThe container uses run.sh as the entrypoint, which automatically:
- Detects architecture and sets DOCKER_API_VERSION (1.43 for arm64, 1.44 for amd64)
- Loads environment variables from
.env - Starts FlowGuard in routed mode on port 8000
- Reads configuration from stdin (via heredoc in run.sh)
To use a custom config file, set environment variables that run.sh reads:
docker run --rm -v $(pwd)/config.toml:/app/config.toml \
-v $(pwd)/.env:/app/.env \
-v /var/run/docker.sock:/var/run/docker.sock \
-e CONFIG=/app/config.toml \
-e ENV_FILE=/app/.env \
-e PORT=8000 \
-e HOST=127.0.0.1 \
-p 8000:8000 \
flowguard-goAvailable environment variables for run.sh:
CONFIG- Path to config file (overrides stdin config)ENV_FILE- Path to .env file (default:.env)PORT- Server port (default:8000)HOST- Server host (default:127.0.0.1)MODE- Server mode flag (default:--routed, can be--unified)
Note: Set DOCKER_API_VERSION=1.43 for arm64 (Mac) or 1.44 for amd64 (Linux).
POST /mcp/{serverID}- Send JSON-RPC request to specific server- Example:
POST /mcp/githubwith body{"jsonrpc": "2.0", "method": "tools/list", "id": 1}
- Example:
POST /mcp- Send JSON-RPC request (routed to first configured server)
GET /health- ReturnsOK
Supported JSON-RPC 2.0 methods:
tools/list- List available toolstools/call- Call a tool with parameters- Any other MCP method (forwarded as-is)
This Go port focuses on core MCP proxy functionality with optional security features:
- ✅ TOML and JSON stdin configuration
- ✅ Stdio transport for backend servers
- ✅ Docker container launching
- ✅ Routed and unified modes
- ✅ Basic request/response proxying
FlowGuard includes a complete implementation of Decentralized Information Flow Control (DIFC) for information security, but it is not yet enabled by default. The DIFC system provides:
- Label-based Security: Track information flow with secrecy and integrity labels
- Reference Monitor: Centralized policy enforcement for all MCP operations
- Guard Framework: Domain-specific resource labeling (e.g., GitHub repos, files)
- Agent Tracking: Per-agent taint tracking across requests
- Fine-grained Control: Collection filtering for partial access to resources
internal/difc/
├── labels.go # Secrecy/integrity labels with flow semantics
├── resource.go # Resource labeling (coarse & fine-grained)
├── evaluator.go # DIFC policy evaluation & enforcement
├── agent.go # Per-agent label tracking (taint tracking)
└── capabilities.go # Global tag registry
internal/guard/
├── guard.go # Guard interface definition
├── noop.go # NoopGuard (default, allows all operations)
├── registry.go # Guard registration & lookup
└── context.go # Agent ID extraction utilities
- Resource Labeling: Guards label resources based on domain knowledge (e.g., "repo:owner/name", "visibility:private")
- Agent Tracking: Each agent has secrecy/integrity labels that accumulate through reads (taint tracking)
- Policy Enforcement: Reference Monitor checks if operations violate label flow semantics:
- Read: Resource secrecy must flow to agent secrecy (resource ⊆ agent)
- Write: Agent integrity must flow to resource integrity (agent ⊆ resource)
- Fine-grained Filtering: Collections (e.g., search results) automatically filtered to allowed items
To enable DIFC enforcement, you'll need to:
- Implement domain-specific guards (e.g., GitHub, filesystem)
- Configure agent labels in
config.toml - Register guards in server initialization
See docs/DIFC_INTEGRATION_PROPOSAL.md for full design details.
Current Status: All DIFC infrastructure is implemented and tested, but only the NoopGuard is active (which returns empty labels, effectively disabling enforcement). Custom guards for specific backends (GitHub, filesystem, etc.) are not yet implemented.
flowguard-go/
├── main.go # Entry point
├── go.mod # Dependencies
├── Dockerfile # Container image
└── internal/
├── cmd/ # CLI commands (cobra)
├── config/ # Configuration loading
├── launcher/ # Backend server management
├── mcp/ # MCP protocol types & connection
└── server/ # HTTP server
github.com/spf13/cobra- CLI frameworkgithub.com/BurntSushi/toml- TOML parser- Standard library for JSON, HTTP, exec
Same as original FlowGuard project.