Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions .github/workflows/container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: build-and-push-container

on:
push:
branches: [ "main" ]
tags: [ "v*" ]
workflow_dispatch: {}

permissions:
contents: read
packages: write

jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

# Enables emulation so the amd64 runner can build arm64 too
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 # Buildx builder [oai_citation:1‡GitHub](https://github.com/docker/setup-buildx-action?utm_source=chatgpt.com)

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} # packages:write [oai_citation:2‡GitHub](https://github.com/docker/login-action?utm_source=chatgpt.com)

- name: Build and push (multi-arch)
uses: docker/build-push-action@v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
35 changes: 35 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Build stage
FROM golang:1.23-alpine AS builder

WORKDIR /app

# Copy go mod files
COPY go.mod go.sum ./
RUN go mod download

# Copy source code
COPY . .

# Build the binary
RUN CGO_ENABLED=0 GOOS=linux go build -o flowguard-go .

# Runtime stage
FROM alpine:latest

# Install Docker CLI and bash for launching backend MCP servers
RUN apk add --no-cache docker-cli bash

WORKDIR /app

# Copy binary from builder
COPY --from=builder /app/flowguard-go .

# Copy run.sh script
COPY run.sh .
RUN chmod +x run.sh

# Expose default HTTP port
EXPOSE 8000

# Use run.sh as entrypoint
ENTRYPOINT ["/app/run.sh"]
295 changes: 293 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,293 @@
# gh-aw-mcpg
Github Agentic Workflows MCP Gateway
# FlowGuard (Go Port)

A simplified Go port of FlowGuard - a proxy server for Model Context Protocol (MCP) servers.

## Features

- **Configuration Modes**: Supports both TOML files and JSON stdin configuration
- **Routing Modes**:
- **Routed**: Each backend server accessible at `/mcp/{serverID}`
- **Unified**: Single endpoint `/mcp` that routes to configured servers
- **Docker Support**: Launch backend MCP servers as Docker containers
- **Stdio Transport**: JSON-RPC 2.0 over stdin/stdout for MCP communication

## Quick Start

### Prerequisites

1. **Docker** installed and running
2. **Go 1.23+** for building from source

### Setup Steps

1. **Build the binary**
```bash
go build -o flowguard-go
```

2. **Create your environment file**
```bash
cp example.env .env
```

3. **Create a GitHub Personal Access Token**
- Go to https://github.com/settings/tokens
- Click "Generate new token (classic)"
- Select scopes as needed (e.g., `repo` for repository access)
- Copy the generated token

4. **Add your token to `.env`**

Replace the placeholder value with your actual token:
```bash
sed -i '' 's/GITHUB_PERSONAL_ACCESS_TOKEN=.*/GITHUB_PERSONAL_ACCESS_TOKEN=your_token_here/' .env
```

Or edit `.env` manually and replace the value of `GITHUB_PERSONAL_ACCESS_TOKEN`.

5. **Pull required Docker images**
```bash
docker pull ghcr.io/github/github-mcp-server:latest
docker pull mcp/fetch
docker pull mcp/memory
```

6. **Start FlowGuard**

In one terminal, run:
```bash
./run.sh
```

This will start FlowGuard in routed mode on `http://127.0.0.1:8000`.

7. **Run Codex (in another terminal)**
```bash
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:

```bash
cp ~/.codex/config.toml.bak ~/.codex/config.toml
```

## Testing with curl

You can test the MCP server directly using curl commands:

### 1. Initialize a session and extract session ID

```bash
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"
```

### 2. List available tools

```bash
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": {}
}'
```

### Manual Build & Run

If you prefer to run manually without the `run.sh` script:

```bash
# Run with TOML config
./flowguard-go --config config.toml

# Run with JSON stdin config
echo '{"mcpServers": {...}}' | ./flowguard-go --config-stdin
```

## Configuration

### TOML Format (`config.toml`)

```toml
[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"]
```

### JSON Stdin Format

```json
{
"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.

## Usage

```
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 Image

```bash
docker build -t flowguard-go .
```

### Run Container

```bash
docker run --rm -v $(pwd)/.env:/app/.env \
-v /var/run/docker.sock:/var/run/docker.sock \
-p 8000:8000 \
flowguard-go
```

The 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)

### Override with custom configuration

To use a custom config file, set environment variables that `run.sh` reads:

```bash
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-go
```

Available 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).


## API Endpoints

### Routed Mode (default)

- `POST /mcp/{serverID}` - Send JSON-RPC request to specific server
- Example: `POST /mcp/github` with body `{"jsonrpc": "2.0", "method": "tools/list", "id": 1}`

### Unified Mode

- `POST /mcp` - Send JSON-RPC request (routed to first configured server)

### Health Check

- `GET /health` - Returns `OK`

## MCP Methods

Supported JSON-RPC 2.0 methods:

- `tools/list` - List available tools
- `tools/call` - Call a tool with parameters
- Any other MCP method (forwarded as-is)

## Architecture Simplifications

This Go port focuses on core MCP proxy functionality:

- ✅ TOML and JSON stdin configuration
- ✅ Stdio transport for backend servers
- ✅ Docker container launching
- ✅ Routed and unified modes
- ✅ Basic request/response proxying
- ❌ DIFC enforcement (removed)
- ❌ Sub-agents (removed)
- ❌ Guards (removed)

## Development

### Project Structure

```
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
```

### Dependencies

- `github.com/spf13/cobra` - CLI framework
- `github.com/BurntSushi/toml` - TOML parser
- Standard library for JSON, HTTP, exec

## License

Same as original FlowGuard project.
Loading