Implements the walking skeleton from the roadmap: agents connect to one HTTP
endpoint and Nexus aggregates upstream MCP servers behind it with namespaced
tools. Written in Go (single static binary), no external services required.
What works end-to-end (verified live + hermetic e2e tests):
- MCP protocol layer: JSON-RPC 2.0 + initialize/tools.list/tools.call
(internal/mcp), with stdio (subprocess) and Streamable HTTP client
transports, and a reusable stream transport for in-process wiring.
- Router + Dynamic Tool Registry: connects/initializes upstreams in parallel,
loads tools, namespaces them as {namespace}.{tool}, dispatches tools/call to
the owning upstream; refreshes on list_changed. A failed upstream stays
not-ready without taking down the gateway (data plane stays up).
- Gateway: single MCP endpoint (POST /mcp) that is an MCP server to agents,
plus /healthz and a minimal /metrics exposition.
- CLI (cmd/nexus): `serve`, `connect` (stdio<->HTTP bridge for local agents),
`demo-mcp` (built-in zero-dep demo server: echo/add/now), `version`.
- Config: declarative YAML with env expansion + validation.
- Store: persistence interfaces + in-memory impl (SQLite lands later).
Foundations for later phases: domain types (ARCHITECTURE §7), two-plane
split, event-driven refresh seam.
Tooling: Makefile (build/test/vet/fmt with version ldflags), config.example
.yaml. GOPATH moved to /go so it doesn't collide with the module root at /root;
.gitignore whitelist extended to track Go sources while ignoring build output.
Tests: unit (registry/namespacing) + full e2e (client -> demo server over
pipes -> router -> HTTP gateway: initialize, aggregated tools/list, tool-call
routing, unknown-tool error). go vet + gofmt clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
37 lines
936 B
Makefile
37 lines
936 B
Makefile
SHELL := /bin/bash
|
|
BINARY := nexus
|
|
PKG := gitea.thetempleofdoom.com/drjones/mcp-gateway-nexus
|
|
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo 0.1.0-dev)
|
|
COMMIT ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
|
|
DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
LDFLAGS := -s -w \
|
|
-X '$(PKG)/internal/version.Version=$(VERSION)' \
|
|
-X '$(PKG)/internal/version.Commit=$(COMMIT)' \
|
|
-X '$(PKG)/internal/version.Date=$(DATE)'
|
|
|
|
.PHONY: all build test vet fmt tidy run clean
|
|
|
|
all: vet test build
|
|
|
|
build: ## Build the nexus binary into ./bin
|
|
@mkdir -p bin
|
|
go build -ldflags "$(LDFLAGS)" -o bin/$(BINARY) ./cmd/nexus
|
|
|
|
test: ## Run all tests
|
|
go test ./...
|
|
|
|
vet: ## Static analysis
|
|
go vet ./...
|
|
|
|
fmt: ## Format code
|
|
gofmt -s -w .
|
|
|
|
tidy: ## Tidy go.mod
|
|
go mod tidy
|
|
|
|
run: build ## Build and run the gateway with the example config
|
|
./bin/$(BINARY) serve -config config.example.yaml
|
|
|
|
clean:
|
|
rm -rf bin
|