P0.1: Repository and module setup
Go module, Makefile with standard targets, golangci-lint v2 config, CLAUDE.md, and empty CLI/agent binaries. Build, vet, and lint all pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
18
.gitignore
vendored
Normal file
18
.gitignore
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Binaries
|
||||
/mcp
|
||||
/mcp-agent
|
||||
|
||||
# Runtime data
|
||||
srv/
|
||||
|
||||
# Database files
|
||||
*.db
|
||||
*.db-wal
|
||||
*.db-shm
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
80
.golangci.yaml
Normal file
80
.golangci.yaml
Normal file
@@ -0,0 +1,80 @@
|
||||
version: "2"
|
||||
|
||||
run:
|
||||
timeout: 5m
|
||||
tests: true
|
||||
|
||||
linters:
|
||||
default: none
|
||||
enable:
|
||||
- errcheck
|
||||
- govet
|
||||
- ineffassign
|
||||
- unused
|
||||
- errorlint
|
||||
- gosec
|
||||
- staticcheck
|
||||
- revive
|
||||
|
||||
settings:
|
||||
errcheck:
|
||||
check-blank: false
|
||||
check-type-assertions: true
|
||||
|
||||
govet:
|
||||
enable-all: true
|
||||
disable:
|
||||
- shadow
|
||||
- fieldalignment
|
||||
|
||||
gosec:
|
||||
severity: medium
|
||||
confidence: medium
|
||||
excludes:
|
||||
- G104
|
||||
|
||||
errorlint:
|
||||
errorf: true
|
||||
asserts: true
|
||||
comparison: true
|
||||
|
||||
revive:
|
||||
rules:
|
||||
- name: error-return
|
||||
severity: error
|
||||
- name: unexported-return
|
||||
severity: error
|
||||
- name: error-strings
|
||||
severity: warning
|
||||
- name: if-return
|
||||
severity: warning
|
||||
- name: increment-decrement
|
||||
severity: warning
|
||||
- name: var-naming
|
||||
severity: warning
|
||||
- name: range
|
||||
severity: warning
|
||||
- name: time-naming
|
||||
severity: warning
|
||||
- name: indent-error-flow
|
||||
severity: warning
|
||||
- name: early-return
|
||||
severity: warning
|
||||
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
exclusions:
|
||||
paths:
|
||||
- vendor
|
||||
rules:
|
||||
- path: "_test\\.go"
|
||||
linters:
|
||||
- gosec
|
||||
text: "G101"
|
||||
58
CLAUDE.md
Normal file
58
CLAUDE.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# CLAUDE.md
|
||||
|
||||
## Project Overview
|
||||
|
||||
MCP (Metacircular Control Plane) is the orchestrator for the Metacircular platform. It manages container lifecycle, tracks what services run where, and transfers files between the operator's workstation and managed nodes.
|
||||
|
||||
## Architecture
|
||||
|
||||
MCP has two components:
|
||||
- **CLI** (`mcp`) — thin client on the operator's workstation. Reads local service definition files, pushes intent to agents, queries status. No database.
|
||||
- **Agent** (`mcp-agent`) — smart per-node daemon. Manages containers via podman, stores the registry (SQLite), monitors for drift, alerts the operator.
|
||||
|
||||
Services have one or more components (containers). Container naming: `<service>-<component>`.
|
||||
|
||||
## Build Commands
|
||||
|
||||
```bash
|
||||
make all # vet → lint → test → build both binaries
|
||||
make build # go build ./...
|
||||
make test # go test ./...
|
||||
make vet # go vet ./...
|
||||
make lint # golangci-lint run ./...
|
||||
make proto # regenerate gRPC code from .proto files
|
||||
make proto-lint # buf lint + buf breaking
|
||||
make mcp # build CLI binary
|
||||
make mcp-agent # build agent binary
|
||||
make clean # remove binaries
|
||||
```
|
||||
|
||||
Run a single test: `go test ./internal/registry/ -run TestComponentCRUD`
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `cmd/mcp/` — CLI entry point
|
||||
- `cmd/mcp-agent/` — Agent entry point
|
||||
- `internal/agent/` — Agent core (deploy, lifecycle, sync, adopt, status, files)
|
||||
- `internal/runtime/` — Container runtime abstraction (podman)
|
||||
- `internal/registry/` — SQLite registry (services, components, events)
|
||||
- `internal/monitor/` — Monitoring subsystem (watch loop, alerting)
|
||||
- `internal/servicedef/` — Service definition file parsing (TOML)
|
||||
- `internal/auth/` — MCIAS integration (token validation, interceptor)
|
||||
- `internal/config/` — Configuration loading (CLI + agent)
|
||||
- `proto/mcp/v1/` — Proto definitions
|
||||
- `gen/mcp/v1/` — Generated Go gRPC code
|
||||
|
||||
## Critical Rules
|
||||
|
||||
1. Agent is gRPC-only (no REST). This is a deliberate exception to the platform's REST+gRPC parity rule.
|
||||
2. Container naming convention: `<service>-<component>` (e.g., `metacrypt-api`, `metacrypt-web`).
|
||||
3. File operations are scoped to `/srv/<service>/`. Path traversal is rejected.
|
||||
4. Alert commands use exec-style invocation (argv array, no shell). Never use `sh -c`.
|
||||
5. The agent binds to the overlay interface only, not all interfaces. It does NOT sit behind MC-Proxy.
|
||||
6. Every RPC is audit-logged at info level (method, caller, timestamp).
|
||||
7. `active: true/false` in service definitions controls desired state. `mcp stop/start` update the file.
|
||||
|
||||
## Module Path
|
||||
|
||||
`git.wntrmute.dev/kyle/mcp`
|
||||
35
Makefile
Normal file
35
Makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
.PHONY: build test vet lint proto proto-lint clean all
|
||||
|
||||
LDFLAGS := -trimpath -ldflags="-s -w -X main.version=$(shell git describe --tags --always --dirty)"
|
||||
|
||||
mcp:
|
||||
CGO_ENABLED=0 go build $(LDFLAGS) -o mcp ./cmd/mcp
|
||||
|
||||
mcp-agent:
|
||||
CGO_ENABLED=0 go build $(LDFLAGS) -o mcp-agent ./cmd/mcp-agent
|
||||
|
||||
build:
|
||||
go build ./...
|
||||
|
||||
test:
|
||||
go test ./...
|
||||
|
||||
vet:
|
||||
go vet ./...
|
||||
|
||||
lint:
|
||||
golangci-lint run ./...
|
||||
|
||||
proto:
|
||||
protoc --go_out=. --go_opt=module=git.wntrmute.dev/kyle/mcp \
|
||||
--go-grpc_out=. --go-grpc_opt=module=git.wntrmute.dev/kyle/mcp \
|
||||
proto/mcp/v1/*.proto
|
||||
|
||||
proto-lint:
|
||||
buf lint
|
||||
buf breaking --against '.git#branch=master,subdir=proto'
|
||||
|
||||
clean:
|
||||
rm -f mcp mcp-agent
|
||||
|
||||
all: vet lint test mcp mcp-agent
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Phase 0: Project Scaffolding
|
||||
|
||||
- [ ] **P0.1** Repository and module setup
|
||||
- [x] **P0.1** Repository and module setup
|
||||
- [ ] **P0.2** Proto definitions and code generation
|
||||
|
||||
## Phase 1: Core Libraries
|
||||
|
||||
33
cmd/mcp-agent/main.go
Normal file
33
cmd/mcp-agent/main.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "dev"
|
||||
cfgPath string
|
||||
)
|
||||
|
||||
func main() {
|
||||
root := &cobra.Command{
|
||||
Use: "mcp-agent",
|
||||
Short: "Metacircular Control Plane agent",
|
||||
}
|
||||
root.PersistentFlags().StringVarP(&cfgPath, "config", "c", "", "config file path")
|
||||
|
||||
root.AddCommand(&cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(version)
|
||||
},
|
||||
})
|
||||
|
||||
if err := root.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
33
cmd/mcp/main.go
Normal file
33
cmd/mcp/main.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "dev"
|
||||
cfgPath string
|
||||
)
|
||||
|
||||
func main() {
|
||||
root := &cobra.Command{
|
||||
Use: "mcp",
|
||||
Short: "Metacircular Control Plane CLI",
|
||||
}
|
||||
root.PersistentFlags().StringVarP(&cfgPath, "config", "c", "", "config file path")
|
||||
|
||||
root.AddCommand(&cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print version",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println(version)
|
||||
},
|
||||
})
|
||||
|
||||
if err := root.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
10
go.mod
Normal file
10
go.mod
Normal file
@@ -0,0 +1,10 @@
|
||||
module git.wntrmute.dev/kyle/mcp
|
||||
|
||||
go 1.25.7
|
||||
|
||||
require github.com/spf13/cobra v1.10.2
|
||||
|
||||
require (
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.9 // indirect
|
||||
)
|
||||
10
go.sum
Normal file
10
go.sum
Normal file
@@ -0,0 +1,10 @@
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||
github.com/spf13/pflag v1.0.9 h1:9exaQaMOCwffKiiiYk6/BndUBv+iRViNW+4lEMi0PvY=
|
||||
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
Reference in New Issue
Block a user