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
9 changes: 5 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,23 +245,24 @@ When refactoring for better design:

```bash
# Build everything
make build
./scripts/build

# Format everything
make format
./scripts/format

# Lint everything
make lint
./scripts/lint

# Test mcp-front
./scripts/test
go test ./internal/... -v
go test ./integration -v

# Run mcp-front locally
./mcp-front -config config.json

# Start docs dev server
make doc
./scripts/docs
```

## Documentation Site Guidelines
Expand Down
43 changes: 29 additions & 14 deletions cmd/mcp-front/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,42 @@ func generateDefaultConfig(path string) error {
"addr": ":8080",
"name": "mcp-front",
"auth": map[string]any{
"kind": "oauth",
"issuer": "https://mcp.yourcompany.com",
"allowedDomains": []string{"yourcompany.com"},
"allowedOrigins": []string{"https://claude.ai"},
"tokenTtl": "24h",
"storage": "memory",
"googleClientId": map[string]string{"$env": "GOOGLE_CLIENT_ID"},
"googleClientSecret": map[string]string{"$env": "GOOGLE_CLIENT_SECRET"},
"googleRedirectUri": "https://mcp.yourcompany.com/oauth/callback",
"jwtSecret": map[string]string{"$env": "JWT_SECRET"},
"encryptionKey": map[string]string{"$env": "ENCRYPTION_KEY"},
"kind": "oauth",
"issuer": "https://mcp.yourcompany.com",
"allowedDomains": []string{"yourcompany.com"},
"allowedOrigins": []string{"https://claude.ai"},
"tokenTtl": "24h",
"storage": "memory",
"idp": map[string]any{
"provider": "google",
"clientId": map[string]string{"$env": "GOOGLE_CLIENT_ID"},
"clientSecret": map[string]string{"$env": "GOOGLE_CLIENT_SECRET"},
"redirectUri": "https://mcp.yourcompany.com/oauth/callback",
},
"jwtSecret": map[string]string{"$env": "JWT_SECRET"},
"encryptionKey": map[string]string{"$env": "ENCRYPTION_KEY"},
},
},
"mcpServers": map[string]any{
"postgres": map[string]any{
"transportType": "stdio",
"command": "docker",
"args": []any{
"run", "--rm", "-i",
"mcp/postgres:latest",
map[string]string{"$env": "POSTGRES_URL"},
"run", "--rm", "-i", "--network", "host",
"-e", "POSTGRES_HOST",
"-e", "POSTGRES_PORT",
"-e", "POSTGRES_DATABASE",
"-e", "POSTGRES_USER",
"-e", "POSTGRES_PASSWORD",
"us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest",
"--stdio", "--prebuilt", "postgres",
},
"env": map[string]any{
"POSTGRES_HOST": map[string]string{"$env": "POSTGRES_HOST"},
"POSTGRES_PORT": map[string]string{"$env": "POSTGRES_PORT"},
"POSTGRES_DATABASE": map[string]string{"$env": "POSTGRES_DATABASE"},
"POSTGRES_USER": map[string]string{"$env": "POSTGRES_USER"},
"POSTGRES_PASSWORD": map[string]string{"$env": "POSTGRES_PASSWORD"},
},
},
},
Expand Down
9 changes: 6 additions & 3 deletions config-admin-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
"auth": {
"kind": "oauth",
"issuer": "https://mcp.example.com",
"idp": {
"provider": "google",
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"redirectUri": "https://mcp.example.com/oauth/callback"
},
"allowedDomains": ["example.com"],
"allowedOrigins": ["https://claude.ai"],
"tokenTtl": "1h",
"storage": "memory",
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"googleRedirectUri": "https://mcp.example.com/oauth/callback",
"jwtSecret": {"$env": "JWT_SECRET"},
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
},
Expand Down
9 changes: 6 additions & 3 deletions config-inline-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
"auth": {
"kind": "oauth",
"issuer": "https://mcp.example.com",
"idp": {
"provider": "google",
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"redirectUri": "https://mcp.example.com/oauth/callback"
},
"allowedDomains": ["example.com"],
"allowedOrigins": ["https://claude.ai"],
"tokenTtl": "1h",
"storage": "memory",
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"googleRedirectUri": "https://mcp.example.com/oauth/callback",
"jwtSecret": {"$env": "JWT_SECRET"},
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
}
Expand Down
9 changes: 6 additions & 3 deletions config-inline-test.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
"auth": {
"kind": "oauth",
"issuer": "http://localhost:8080",
"idp": {
"provider": "google",
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"redirectUri": "http://localhost:8080/oauth/callback"
},
"allowedDomains": ["gmail.com"],
"allowedOrigins": ["https://claude.ai"],
"tokenTtl": "1h",
"storage": "memory",
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"googleRedirectUri": "http://localhost:8080/oauth/callback",
"jwtSecret": {"$env": "JWT_SECRET"},
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
}
Expand Down
24 changes: 18 additions & 6 deletions config-oauth-firestore.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
"kind": "oauth",
"issuer": {"$env": "OAUTH_ISSUER"},
"gcpProject": {"$env": "GCP_PROJECT"},
"idp": {
"provider": "google",
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"redirectUri": {"$env": "GOOGLE_REDIRECT_URI"}
},
"allowedDomains": ["yourcompany.com", "contractors.yourcompany.com"],
"allowedOrigins": ["https://claude.ai", "https://yourcompany.com"],
"tokenTtl": "24h",
"storage": "firestore",
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"googleRedirectUri": {"$env": "GOOGLE_REDIRECT_URI"},
"jwtSecret": {"$env": "JWT_SECRET"},
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
}
Expand All @@ -25,11 +28,20 @@
"command": "docker",
"args": [
"run", "--rm", "-i", "--network", "host",
"mcp/postgres",
{"$env": "DATABASE_URL"}
"-e", "POSTGRES_HOST",
"-e", "POSTGRES_PORT",
"-e", "POSTGRES_DATABASE",
"-e", "POSTGRES_USER",
"-e", "POSTGRES_PASSWORD",
"us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest",
"--stdio", "--prebuilt", "postgres"
],
"env": {
"PGPASSWORD": {"$env": "POSTGRES_PASSWORD"}
"POSTGRES_HOST": {"$env": "POSTGRES_HOST"},
"POSTGRES_PORT": {"$env": "POSTGRES_PORT"},
"POSTGRES_DATABASE": {"$env": "POSTGRES_DATABASE"},
"POSTGRES_USER": {"$env": "POSTGRES_USER"},
"POSTGRES_PASSWORD": {"$env": "POSTGRES_PASSWORD"}
}
},
"notion": {
Expand Down
24 changes: 18 additions & 6 deletions config-oauth.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
"kind": "oauth",
"issuer": {"$env": "OAUTH_ISSUER"},
"gcpProject": {"$env": "GCP_PROJECT"},
"idp": {
"provider": "google",
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"redirectUri": {"$env": "GOOGLE_REDIRECT_URI"}
},
"allowedDomains": ["yourcompany.com", "contractors.yourcompany.com"],
"allowedOrigins": ["https://claude.ai", "https://yourcompany.com"],
"tokenTtl": "24h",
"storage": "memory",
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"googleRedirectUri": {"$env": "GOOGLE_REDIRECT_URI"},
"jwtSecret": {"$env": "JWT_SECRET"},
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
}
Expand All @@ -25,11 +28,20 @@
"command": "docker",
"args": [
"run", "--rm", "-i", "--network", "host",
"mcp/postgres",
{"$env": "DATABASE_URL"}
"-e", "POSTGRES_HOST",
"-e", "POSTGRES_PORT",
"-e", "POSTGRES_DATABASE",
"-e", "POSTGRES_USER",
"-e", "POSTGRES_PASSWORD",
"us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest",
"--stdio", "--prebuilt", "postgres"
],
"env": {
"PGPASSWORD": {"$env": "POSTGRES_PASSWORD"}
"POSTGRES_HOST": {"$env": "POSTGRES_HOST"},
"POSTGRES_PORT": {"$env": "POSTGRES_PORT"},
"POSTGRES_DATABASE": {"$env": "POSTGRES_DATABASE"},
"POSTGRES_USER": {"$env": "POSTGRES_USER"},
"POSTGRES_PASSWORD": {"$env": "POSTGRES_PASSWORD"}
}
},
"notion": {
Expand Down
31 changes: 23 additions & 8 deletions config-oauth.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,41 @@
"kind": "oauth",
"issuer": "https://mcp-internal.yourcompany.org",
"gcpProject": {"$env": "GCP_PROJECT"},
"idp": {
"provider": "google",
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"redirectUri": "https://mcp-internal.yourcompany.org/oauth/callback"
},
"allowedDomains": ["yourcompany.com"],
"allowedOrigins": ["https://claude.ai"],
"tokenTtl": "24h",
"storage": "memory",
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"googleRedirectUri": "https://mcp-internal.yourcompany.org/oauth/callback",
"jwtSecret": {"$env": "JWT_SECRET"},
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
}
},
"mcpServers": {
"postgres": {
"transportType": "stdio",
"command": "docker",
"command": "docker",
"args": [
"run", "--rm", "-i",
"mcp/postgres:latest",
"postgresql://user:password@localhost:5432/database"
]
"run", "--rm", "-i", "--network", "host",
"-e", "POSTGRES_HOST",
"-e", "POSTGRES_PORT",
"-e", "POSTGRES_DATABASE",
"-e", "POSTGRES_USER",
"-e", "POSTGRES_PASSWORD",
"us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest",
"--stdio", "--prebuilt", "postgres"
],
"env": {
"POSTGRES_HOST": {"$env": "POSTGRES_HOST"},
"POSTGRES_PORT": {"$env": "POSTGRES_PORT"},
"POSTGRES_DATABASE": {"$env": "POSTGRES_DATABASE"},
"POSTGRES_USER": {"$env": "POSTGRES_USER"},
"POSTGRES_PASSWORD": {"$env": "POSTGRES_PASSWORD"}
}
},
"notion": {
"transportType": "stdio",
Expand Down
9 changes: 7 additions & 2 deletions config-token.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@
"command": "docker",
"args": [
"run", "--rm", "-i", "--network", "host",
"mcp/postgres",
"postgresql://testuser:testpass@localhost:5432/testdb"
"-e", "POSTGRES_HOST=localhost",
"-e", "POSTGRES_PORT=5432",
"-e", "POSTGRES_DATABASE=testdb",
"-e", "POSTGRES_USER=testuser",
"-e", "POSTGRES_PASSWORD=testpass",
"us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest",
"--stdio", "--prebuilt", "postgres"
],
"serviceAuths": [
{
Expand Down
24 changes: 18 additions & 6 deletions config-user-tokens-example.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
"kind": "oauth",
"issuer": {"$env": "OAUTH_ISSUER"},
"gcpProject": {"$env": "GCP_PROJECT"},
"idp": {
"provider": "google",
"clientId": {"$env": "GOOGLE_CLIENT_ID"},
"clientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"redirectUri": {"$env": "GOOGLE_REDIRECT_URI"}
},
"allowedDomains": ["yourcompany.com"],
"allowedOrigins": ["https://claude.ai"],
"tokenTtl": "24h",
"storage": "memory",
"googleClientId": {"$env": "GOOGLE_CLIENT_ID"},
"googleClientSecret": {"$env": "GOOGLE_CLIENT_SECRET"},
"googleRedirectUri": {"$env": "GOOGLE_REDIRECT_URI"},
"jwtSecret": {"$env": "JWT_SECRET"},
"encryptionKey": {"$env": "ENCRYPTION_KEY"}
}
Expand Down Expand Up @@ -57,11 +60,20 @@
"command": "docker",
"args": [
"run", "--rm", "-i", "--network", "host",
"mcp/postgres",
{"$env": "DATABASE_URL"}
"-e", "POSTGRES_HOST",
"-e", "POSTGRES_PORT",
"-e", "POSTGRES_DATABASE",
"-e", "POSTGRES_USER",
"-e", "POSTGRES_PASSWORD",
"us-central1-docker.pkg.dev/database-toolbox/toolbox/toolbox:latest",
"--stdio", "--prebuilt", "postgres"
],
"env": {
"PGPASSWORD": {"$env": "POSTGRES_PASSWORD"}
"POSTGRES_HOST": {"$env": "POSTGRES_HOST"},
"POSTGRES_PORT": {"$env": "POSTGRES_PORT"},
"POSTGRES_DATABASE": {"$env": "POSTGRES_DATABASE"},
"POSTGRES_USER": {"$env": "POSTGRES_USER"},
"POSTGRES_PASSWORD": {"$env": "POSTGRES_PASSWORD"}
}
}
}
Expand Down
20 changes: 13 additions & 7 deletions docs-site/src/content/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,16 @@ For production, use OAuth with Google. Claude redirects users to Google for auth
"auth": {
"kind": "oauth",
"issuer": "https://mcp.company.com",
"idp": {
"provider": "google",
"clientId": { "$env": "GOOGLE_CLIENT_ID" },
"clientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
"redirectUri": "https://mcp.company.com/oauth/callback"
},
"allowedDomains": ["company.com"],
"allowedOrigins": ["https://claude.ai"],
"tokenTtl": "24h",
"storage": "memory",
"googleClientId": { "$env": "GOOGLE_CLIENT_ID" },
"googleClientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
"googleRedirectUri": "https://mcp.company.com/oauth/callback",
"jwtSecret": { "$env": "JWT_SECRET" },
"encryptionKey": { "$env": "ENCRYPTION_KEY" }
}
Expand All @@ -66,7 +69,7 @@ The `issuer` should match your `baseURL`. `allowedDomains` restricts access to s

`tokenTtl` controls how long JWT tokens are valid. Shorter times are more secure but require more frequent logins.

Security requirements: `googleClientSecret`, `jwtSecret`, and `encryptionKey` must be environment variables. The JWT secret must be at least 32 bytes. The encryption key must be exactly 32 bytes.
Security requirements: `idp.clientSecret`, `jwtSecret`, and `encryptionKey` must be environment variables. The JWT secret must be at least 32 bytes. The encryption key must be exactly 32 bytes.

For production, set `storage` to "firestore" and add `gcpProject`, `firestoreDatabase`, and `firestoreCollection` fields.

Expand Down Expand Up @@ -345,13 +348,16 @@ Set `MCP_FRONT_ENV=development` when testing OAuth locally. It allows http:// UR
"auth": {
"kind": "oauth",
"issuer": "https://mcp.company.com",
"idp": {
"provider": "google",
"clientId": { "$env": "GOOGLE_CLIENT_ID" },
"clientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
"redirectUri": "https://mcp.company.com/oauth/callback"
},
"allowedDomains": ["company.com"],
"allowedOrigins": ["https://claude.ai"],
"tokenTtl": "4h",
"storage": "firestore",
"googleClientId": { "$env": "GOOGLE_CLIENT_ID" },
"googleClientSecret": { "$env": "GOOGLE_CLIENT_SECRET" },
"googleRedirectUri": "https://mcp.company.com/oauth/callback",
"jwtSecret": { "$env": "JWT_SECRET" },
"encryptionKey": { "$env": "ENCRYPTION_KEY" },
"gcpProject": { "$env": "GOOGLE_CLOUD_PROJECT" },
Expand Down
Loading