Skip to content

Commit 456bccb

Browse files
authored
Merge pull request #59 from githubnext/lpcox/json-schema-v2
feat: Add MCP Gateway configuration spec validation and enhanced secuirty
2 parents b358ed9 + 9d3bfff commit 456bccb

20 files changed

Lines changed: 1868 additions & 116 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ go.work.sum
3737

3838
# env file
3939
.env
40+
.env.*
41+
.env.githubnext
4042

4143
# Editor/IDE
4244
# .idea/

AGENTS.md

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,30 @@ Quick reference for AI agents working with MCP Gateway (Go-based MCP proxy serve
1717
## Project Structure
1818

1919
- `internal/cmd/` - CLI (Cobra)
20-
- `internal/config/` - Config parsing (TOML/JSON)
20+
- `internal/config/` - Config parsing (TOML/JSON) with validation
21+
- `validation.go` - Variable expansion and fail-fast validation
22+
- `validation_test.go` - 21 comprehensive validation tests
2123
- `internal/server/` - HTTP server (routed/unified modes)
22-
- `internal/mcp/` - MCP protocol types
24+
- `internal/mcp/` - MCP protocol types with enhanced error logging
2325
- `internal/launcher/` - Backend process management
2426
- `internal/difc/` - Security labels (not enabled)
2527
- `internal/guard/` - Security guards (NoopGuard active)
2628
- `internal/logger/` - Debug logging framework (micro logger)
2729
- `internal/timeutil/` - Time formatting utilities
28-
- `internal/tty/` - Terminal detection utilities
2930

3031
## Key Tech
3132

3233
- **Go 1.25.0** with `cobra`, `toml`, `go-sdk`
3334
- **Protocol**: JSON-RPC 2.0 over stdio
3435
- **Routing**: `/mcp/{serverID}` (routed) or `/mcp` (unified)
3536
- **Docker**: Launches MCP servers as containers
37+
- **Validation**: Spec-compliant with fail-fast error handling
38+
- **Variable Expansion**: `${VAR_NAME}` syntax for environment variables
3639

3740
## Config Examples
3841

42+
**Configuration Spec**: See **[MCP Gateway Configuration Reference](https://github.com/githubnext/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md)** for complete specification.
43+
3944
**TOML** (`config.toml`):
4045
```toml
4146
[servers.github]
@@ -45,9 +50,29 @@ args = ["run", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "-i", "ghcr.io/gith
4550

4651
**JSON** (stdin):
4752
```json
48-
{"mcpServers": {"github": {"type": "local", "container": "ghcr.io/github/github-mcp-server:latest", "env": {"GITHUB_PERSONAL_ACCESS_TOKEN": ""}}}}
53+
{
54+
"mcpServers": {
55+
"github": {
56+
"type": "stdio",
57+
"container": "ghcr.io/github/github-mcp-server:latest",
58+
"env": {
59+
"GITHUB_PERSONAL_ACCESS_TOKEN": "",
60+
"CONFIG_PATH": "${GITHUB_CONFIG_DIR}"
61+
}
62+
}
63+
}
64+
}
4965
```
5066

67+
**Supported Types**: `"stdio"`, `"http"` (not implemented), `"local"` (alias for stdio)
68+
69+
**Validation Features**:
70+
- Environment variable expansion: `${VAR_NAME}` (fails if undefined)
71+
- Required fields: `container` for stdio, `url` for http
72+
- **Note**: The `command` field is not supported - stdio servers must use `container`
73+
- Port range validation: 1-65535
74+
- Timeout validation: positive integers only
75+
5176
## Go Conventions
5277

5378
- Internal packages in `internal/`
@@ -157,12 +182,25 @@ DEBUG_COLORS=0 DEBUG=* ./awmg --config config.toml
157182
- `GITHUB_PERSONAL_ACCESS_TOKEN` - GitHub auth
158183
- `DOCKER_API_VERSION` - 1.43 (arm64) or 1.44 (amd64)
159184
- `PORT`, `HOST`, `MODE` - Server config (via run.sh)
185+
- `DEBUG` - Enable debug logging (e.g., `DEBUG=*`, `DEBUG=server:*,launcher:*`)
186+
- `DEBUG_COLORS` - Control colored output (0 to disable, auto-disabled when piping)
187+
188+
## Error Debugging
189+
190+
**Enhanced Error Context**: Command failures include:
191+
- Full command, args, and environment variables
192+
- Context-specific troubleshooting suggestions:
193+
- Docker daemon connectivity checks
194+
- Container image availability
195+
- Network connectivity issues
196+
- MCP protocol compatibility checks
160197

161198
## Security Notes
162199

163200
- Auth: `Authorization: Bearer <token>` header
164201
- Sessions: `Mcp-Session-Id` header
165202
- DIFC: Implemented but disabled (NoopGuard active)
203+
- Stdio servers: Containerized execution only (no direct command support)
166204

167205
## Resources
168206

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ GOLANGCI_LINT_VERSION=v2.2.0
1313
# Build the CLI binary
1414
build:
1515
@echo "Building $(BINARY_NAME)..."
16+
@go mod tidy
1617
@go build -o $(BINARY_NAME) .
1718
@echo "Build complete: $(BINARY_NAME)"
1819

1920
# Run all linters
2021
lint:
2122
@echo "Running linters..."
23+
@go mod tidy
2224
@go vet ./...
2325
@echo "Running gofmt check..."
2426
@test -z "$$(gofmt -l .)" || (echo "The following files are not formatted:"; gofmt -l .; exit 1)
@@ -27,6 +29,7 @@ lint:
2729
# Run all tests
2830
test:
2931
@echo "Running tests..."
32+
@go mod tidy
3033
@go test -v ./...
3134

3235
# Run binary integration tests (requires built binary)
@@ -39,7 +42,7 @@ test-integration:
3942
@go test -v ./test/integration/...
4043

4144
# Run format, build, lint, and test (for agents before completion)
42-
agent-finished:
45+
agent-finished: clean
4346
@echo "Running agent-finished checks..."
4447
@echo ""
4548
@$(MAKE) format
@@ -71,6 +74,7 @@ coverage:
7174
# Run tests with coverage and JSON output for CI
7275
test-ci:
7376
@echo "Running tests with coverage and JSON output..."
77+
@go mod tidy
7478
@go test -v -parallel=8 -timeout=3m -coverprofile=coverage.out -json ./... | tee test-result-unit.json
7579
@echo "Test results saved to test-result-unit.json"
7680
@echo "Coverage profile saved to coverage.out"
@@ -87,6 +91,8 @@ clean:
8791
@rm -f $(BINARY_NAME)
8892
@rm -f coverage.out
8993
@rm -f test-result-unit.json
94+
@go mod tidy
95+
@go clean
9096
@echo "Clean complete!"
9197

9298
# Create and push a release tag

README.md

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,21 @@ A gateway for Model Context Protocol (MCP) servers.
44

55
This gateway is used with [GitHub Agentic Workflows](https://github.com/githubnext/gh-aw) via the `sandbox.mcp` configuration to provide MCP server access to AI agents running in sandboxed environments.
66

7+
📖 **[Full Configuration Specification](https://github.com/githubnext/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md)** - Complete reference for all configuration options and validation rules.
8+
79
## Features
810

911
- **Configuration Modes**: Supports both TOML files and JSON stdin configuration
12+
- **Spec-Compliant Validation**: Fail-fast validation with detailed error messages
13+
- **Variable Expansion**: Environment variable substitution with `${VAR_NAME}` syntax
14+
- **Type Normalization**: Automatic conversion of legacy `"local"` type to `"stdio"`
1015
- **Routing Modes**:
1116
- **Routed**: Each backend server accessible at `/mcp/{serverID}`
1217
- **Unified**: Single endpoint `/mcp` that routes to configured servers
1318
- **Docker Support**: Launch backend MCP servers as Docker containers
1419
- **Stdio Transport**: JSON-RPC 2.0 over stdin/stdout for MCP communication
20+
- **Container Detection**: Automatic detection of containerized environments with security warnings
21+
- **Enhanced Debugging**: Detailed error context and troubleshooting suggestions for command failures
1522

1623
## Getting Started
1724

@@ -52,21 +59,75 @@ args = ["/path/to/filesystem-server.js"]
5259

5360
### JSON Stdin Format
5461

62+
For the complete JSON configuration specification with all validation rules, see the **[MCP Gateway Configuration Reference](https://github.com/githubnext/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md)**.
63+
5564
```json
5665
{
5766
"mcpServers": {
5867
"github": {
59-
"type": "local",
68+
"type": "stdio",
6069
"container": "ghcr.io/github/github-mcp-server:latest",
70+
"entrypointArgs": ["--verbose"],
6171
"env": {
62-
"GITHUB_PERSONAL_ACCESS_TOKEN": ""
63-
},
72+
"GITHUB_PERSONAL_ACCESS_TOKEN": "",
73+
"EXPANDED_VAR": "${MY_HOME}/config"
74+
}
6475
}
76+
},
77+
"gateway": {
78+
"port": 8080,
79+
"apiKey": "your-api-key",
80+
"domain": "example.com",
81+
"startupTimeout": 30,
82+
"toolTimeout": 60
6583
}
6684
}
6785
```
6886

69-
**Environment Variable Passthrough**: Set the value to an empty string (`""`) to pass through the variable from the host environment.
87+
#### Server Configuration Fields
88+
89+
- **`type`** (optional): Server transport type
90+
- `"stdio"` - Standard input/output transport (default)
91+
- `"http"` - HTTP transport (not yet implemented)
92+
- `"local"` - Alias for `"stdio"` (backward compatibility)
93+
94+
- **`container`** (required for stdio): Docker container image (e.g., `"ghcr.io/github/github-mcp-server:latest"`)
95+
- Automatically wraps as `docker run --rm -i <container>`
96+
- **Note**: The `command` field is NOT supported per the specification
97+
- **`entrypointArgs`** (optional): Arguments passed to container entrypoint
98+
- **`env`** (optional): Environment variables
99+
- Set to `""` (empty string) for passthrough from host environment
100+
- Set to `"value"` for explicit value
101+
- Use `"${VAR_NAME}"` for environment variable expansion (fails if undefined)
102+
- **`url`** (required for http): HTTP endpoint URL for `type: "http"` servers
103+
104+
**Validation Rules:**
105+
106+
- **Stdio servers** must specify `container` (required)
107+
- **HTTP servers** must specify `url` (required)
108+
- Empty/"local" type automatically normalized to "stdio"
109+
- Variable expansion with `${VAR_NAME}` fails fast on undefined variables
110+
- All validation errors include JSONPath and helpful suggestions
111+
- **The `command` field is not supported** - stdio servers must use `container`
112+
113+
See **[Configuration Specification](https://github.com/githubnext/gh-aw/blob/main/docs/src/content/docs/reference/mcp-gateway.md)** for complete validation rules.
114+
115+
#### Gateway Configuration Fields (Reserved)
116+
117+
- **`port`** (optional): Gateway HTTP port (default: from `--listen` flag)
118+
- Valid range: 1-65535
119+
- **`apiKey`** (optional): API key for authentication
120+
- **`domain`** (optional): Domain name for the gateway
121+
- **`startupTimeout`** (optional): Seconds to wait for backend startup (default: 30)
122+
- Must be positive integer
123+
- **`toolTimeout`** (optional): Seconds to wait for tool execution (default: 60)
124+
- Must be positive integer
125+
126+
**Note**: Gateway configuration fields are validated and parsed but not yet fully implemented.
127+
128+
**Environment Variable Features**:
129+
- **Passthrough**: Set value to empty string (`""`) to pass through from host
130+
- **Expansion**: Use `${VAR_NAME}` syntax for dynamic substitution (fails if undefined)
70131

71132
## Usage
72133

@@ -109,17 +170,32 @@ Supported JSON-RPC 2.0 methods:
109170
- `tools/call` - Call a tool with parameters
110171
- Any other MCP method (forwarded as-is)
111172

173+
## Security Features
174+
175+
### Enhanced Error Debugging
176+
177+
Command failures now include extensive debugging information:
178+
179+
- Full command, arguments, and environment variables
180+
- Context-specific troubleshooting suggestions:
181+
- Docker daemon connectivity checks
182+
- Container image availability
183+
- Network connectivity issues
184+
- MCP protocol compatibility checks
185+
112186
## Architecture
113187

114188
This Go port focuses on core MCP proxy functionality with optional security features:
115189

116190
### Core Features (Enabled)
117191

118-
- ✅ TOML and JSON stdin configuration
119-
- ✅ Stdio transport for backend servers
192+
- ✅ TOML and JSON stdin configuration with spec-compliant validation
193+
- ✅ Environment variable expansion (`${VAR_NAME}`) with fail-fast behavior
194+
- ✅ Stdio transport for backend servers (containerized execution only)
120195
- ✅ Docker container launching
121196
- ✅ Routed and unified modes
122197
- ✅ Basic request/response proxying
198+
- ✅ Enhanced error debugging and troubleshooting
123199

124200
### DIFC Integration (Not Yet Enabled)
125201

go.mod

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,25 @@ require (
77
github.com/modelcontextprotocol/go-sdk v1.1.0
88
github.com/spf13/cobra v1.10.2
99
golang.org/x/term v0.38.0
10+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
11+
)
12+
13+
require (
14+
github.com/google/jsonschema-go v0.3.0 // indirect
15+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
16+
github.com/spf13/pflag v1.0.9 // indirect
17+
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
18+
golang.org/x/oauth2 v0.30.0 // indirect
19+
golang.org/x/sys v0.39.0 // indirect
20+
)
21+
22+
require (
23+
github.com/google/jsonschema-go v0.3.0 // indirect
24+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
25+
github.com/spf13/pflag v1.0.9 // indirect
26+
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
27+
golang.org/x/oauth2 v0.30.0 // indirect
28+
golang.org/x/sys v0.39.0 // indirect
1029
)
1130

1231
require (

0 commit comments

Comments
 (0)