This project demonstrates a federated MCP (Model Context Protocol) system with GitHub OAuth integration and OpenID Federation (OIDCFed) trust chains.
- π GitHub OAuth authentication
- π°οΈ Federation trust management
- π€ MCP server with federation JWT validation
- π³ Docker-based deployment
- π Federation admin interface
- Docker and Docker Compose
- Node.js (for building npm packages)
- Git
- A GitHub account (for OAuth setup)
git clone <repository-url>
cd <repository-name>- Go to GitHub Settings > Developer settings > OAuth Apps
- Click "New OAuth App"
- Fill in the application details:
- Application name: Federation MCP Demo (or your preferred name)
- Homepage URL:
http://localhost:3006(note: using port 3006 to avoid conflicts) - Authorization callback URL:
http://localhost:3006/oauth/callback
- Click "Register application"
- Note down the Client ID and Client Secret from the app settings
# Copy the example environment file
cp .env.example .env
# Edit the .env file with your GitHub OAuth credentials
# Required variables:
# GITHUB_CLIENT_ID=your_github_client_id_here
# GITHUB_CLIENT_SECRET=your_github_client_secret_here
# FEDERATION_NAME=alpha (default, can be customized)Example .env file:
GITHUB_CLIENT_ID=Ov23abc123def456
GITHUB_CLIENT_SECRET=abc123def456ghi789jkl012mno345pqr678stu
FEDERATION_NAME=alpha./scripts/setup.sh is now required before any Docker builds. It prepares the
filesystem layout that is mounted into the containers and creates the default
federation and MCP instance.
# Build packages, generate keys, and scaffold default assets
./scripts/setup.shRunning the setup script will:
- Build the npm packages (
@letsfederate/fedmgrand@letsfederate/mcp-core) - Generate federation keys and configuration under
build/install/ - Create the default MCP instance (
mcp-demo) under/usr/src/app/build/install/mcp_instances - Clean up any existing containers and attempt to start the stack
After the script finishes (or after the build phase if you stop it before the Docker step), verify that the following host directories now exist:
build/install/keysβ shared federation anchor keys copied into containers as/usr/src/app/keysbuild/install/federations/<federation-name>β federation configs copied to/usr/src/app/federationsbuild/install/fed-reg/registry.jsonβ registry copied to/usr/src/app/data/registry.json/usr/src/app/build/install/mcp_instances/<instance-name>β MCP runtime assets copied into the MCP container
π‘ If you prefer to start Docker manually, run the setup script once to materialize these directories and then proceed with
docker-composecommands.
# (Re)build images and start services after setup assets exist
docker-compose up --build -dThe containers expect the directories listed above to be present so that the
bootstrap process can mount/copy keys and registry data into /usr/src/app at
runtime.
After the setup completes, you should see:
β
Federation Admin is healthy
β
MCP Server is healthy
π Setup complete!
π Next steps:
1. Open http://localhost:3006 in your browser
2. Click 'Login with GitHub'
3. Test the MCP API integration
The system uses the following ports (configured to avoid common conflicts):
- Federation Admin:
http://localhost:3006(external) β3001(internal) - MCP Server:
http://localhost:4006(external) β4001(internal)
If you encounter port binding errors, check what's using the ports:
# Check port usage
netstat -tlnp | grep -E ":(3006|4006)"
# Or use ss if netstat is not available
ss -tlnp | grep -E ":(3006|4006)"To use different ports:
- Edit
docker-compose.ymland change the port mappings - Update the health check URLs in
scripts/setup.sh - Update the OAuth callback URL in your GitHub app settings
If you see "Missing private key" errors:
# Regenerate keys
./scripts/setup-keys.sh alpha
# Restart containers
docker-compose down
docker-compose up -dIf containers can't access keys:
# Fix permissions
sudo chown -R 1000:1000 ./build/install/
# Restart containers
docker-compose down
docker-compose up -d# View all logs
docker-compose logs -f
# View specific service logs
docker-compose logs -f federation-admin
docker-compose logs -f mcp-serverIf the containers fail during bootstrap because build/install/... directories
are empty or missing:
# Re-run the setup script to regenerate keys, federation data, and MCP assets
./scripts/setup.sh
# After the assets exist, rebuild the containers
docker-compose down
docker-compose up --build -dDouble-check that the directories listed in the setup section are populated before rebuilding the images.
# Stop all services
docker-compose down
# Start services
docker-compose up -d
# Rebuild and start services
docker-compose up --build -d
# Check container status
docker-compose pssequenceDiagram
participant MCP
participant FED as fedmgr-admin
participant AN as Anchor CA
MCP->>MCP: generate key-pair + jwks.json
MCP->>FED: "POST /sign-entity" (json: metadata + jwks)
FED-->>AN: validate + sign
AN-->>FED: JWS(entity_statement)
FED-->>MCP: entity_statement
MCP->>MCP: host /.well-known/openid-federation
- ./scripts/setup.sh
flowchart LR
subgraph docker-compose
direction LR
FM[fedmgr container<br>β’ Anchor CA and Entity-Stmt<br>β’ Token-Exchange + AS]
MCP[demo-mcp container<br>port 4001]
end
GH[GitHub OAuth IdP]
VS[VS Code / curl API caller]
FM -- "1οΈβ£ on start:<br/>generate anchor key & CA<br/>publish /.well-known" --> FM
MCP -- "2οΈβ£ boot:<br/>fetch & verify FM entity stmt<br/>cache trust-marks" --> FM
VS -. "3οΈβ£ browser to /login" .-> GH
GH -- "4οΈβ£ user MFA & consent<br/>β auth code" --> VS
VS -->|"5οΈβ£ POST /callback<br/>auth code"| FM
FM -- "6οΈβ£ token-exchange:<br/>ID-Token β JAG<br/>issue DPoP-bound JWT" --> VS
VS -- "7οΈβ£ Authorization: Bearer <jwt><br/>DPoP: proof" --> MCP
MCP -- "8οΈβ£ verify sig trust-mark<br/>return protected response" --> VS
```