P2.2-P2.9, P3.2-P3.10, P4.1-P4.3: Complete Phases 2, 3, and 4
11 work units built in parallel and merged: Agent handlers (Phase 2): - P2.2 Deploy: pull images, stop/remove/run containers, update registry - P2.3 Lifecycle: stop/start/restart with desired_state tracking - P2.4 Status: list (registry), live check (runtime), get status (drift+events) - P2.5 Sync: receive desired state, reconcile unmanaged containers - P2.6 File transfer: push/pull scoped to /srv/<service>/, path validation - P2.7 Adopt: match <service>-* containers, derive component names - P2.8 Monitor: continuous watch loop, drift/flap alerting, event pruning - P2.9 Snapshot: VACUUM INTO database backup command CLI commands (Phase 3): - P3.2 Login, P3.3 Deploy, P3.4 Stop/Start/Restart - P3.5 List/Ps/Status, P3.6 Sync, P3.7 Adopt - P3.8 Service show/edit/export, P3.9 Push/Pull, P3.10 Node list/add/remove Deployment artifacts (Phase 4): - Systemd units (agent service + backup timer) - Example configs (CLI + agent) - Install script (idempotent) All packages: build, vet, lint (0 issues), test (all pass). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
91
deploy/examples/mcp-agent.toml
Normal file
91
deploy/examples/mcp-agent.toml
Normal file
@@ -0,0 +1,91 @@
|
||||
# MCP Agent configuration
|
||||
#
|
||||
# Default location: /srv/mcp/mcp-agent.toml
|
||||
# Override with: mcp-agent server --config /path/to/mcp-agent.toml
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# gRPC server
|
||||
# ------------------------------------------------------------------
|
||||
[server]
|
||||
# Listen address for the gRPC server. Bind to the overlay network
|
||||
# interface only -- the agent does not sit behind mc-proxy.
|
||||
# Env override: MCP_AGENT_SERVER_GRPC_ADDR
|
||||
grpc_addr = "100.95.252.120:9444"
|
||||
|
||||
# TLS certificate and private key for the gRPC server. The certificate
|
||||
# should be issued by the Metacrypt CA and valid for the overlay IP.
|
||||
# Env overrides: MCP_AGENT_SERVER_TLS_CERT, MCP_AGENT_SERVER_TLS_KEY
|
||||
tls_cert = "/srv/mcp/certs/mcp-agent.crt"
|
||||
tls_key = "/srv/mcp/certs/mcp-agent.key"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Database
|
||||
# ------------------------------------------------------------------
|
||||
[database]
|
||||
# Path to the SQLite database. The agent stores desired state, observed
|
||||
# state, deployed specs, and events here. WAL mode, foreign keys on.
|
||||
# Env override: MCP_AGENT_DATABASE_PATH
|
||||
path = "/srv/mcp/mcp.db"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# MCIAS authentication
|
||||
# ------------------------------------------------------------------
|
||||
[mcias]
|
||||
# URL of the MCIAS server used to validate bearer tokens from the CLI.
|
||||
server_url = "https://mcias.svc.mcp.metacircular.net:8443"
|
||||
|
||||
# Path to the CA certificate that signed the MCIAS TLS certificate.
|
||||
# If empty, the system trust store is used.
|
||||
ca_cert = "/usr/local/share/ca-certificates/metacircular-ca.crt"
|
||||
|
||||
# Service name presented to MCIAS during token validation. Must match
|
||||
# a service registered in MCIAS.
|
||||
service_name = "mcp"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Agent settings
|
||||
# ------------------------------------------------------------------
|
||||
[agent]
|
||||
# Unique name for this node. Must match the name used in [[nodes]]
|
||||
# entries in the CLI config.
|
||||
# Env override: MCP_AGENT_NODE_NAME
|
||||
node_name = "rift"
|
||||
|
||||
# Container runtime binary. Currently only "podman" is supported.
|
||||
# Env override: MCP_AGENT_CONTAINER_RUNTIME
|
||||
container_runtime = "podman"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Monitoring
|
||||
# ------------------------------------------------------------------
|
||||
[monitor]
|
||||
# How often the monitor checks container state against desired state.
|
||||
# Default: 60s
|
||||
interval = "60s"
|
||||
|
||||
# Command to execute when an alert fires. Uses exec-style invocation
|
||||
# (argv array, no shell). The alert message is passed as the final
|
||||
# argument. Omit to disable alerting.
|
||||
# alert_command = ["/usr/local/bin/notify", "--channel", "ops"]
|
||||
|
||||
# Minimum time between repeated alerts for the same condition.
|
||||
# Default: 15m
|
||||
cooldown = "15m"
|
||||
|
||||
# Number of state transitions within flap_window that triggers a
|
||||
# flapping alert. Default: 3
|
||||
flap_threshold = 3
|
||||
|
||||
# Time window for flap detection. Default: 10m
|
||||
flap_window = "10m"
|
||||
|
||||
# How long to retain event records in the database. Default: 30d
|
||||
retention = "30d"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Logging
|
||||
# ------------------------------------------------------------------
|
||||
[log]
|
||||
# Log level: debug, info, warn, error. Default: info
|
||||
# Env override: MCP_AGENT_LOG_LEVEL
|
||||
level = "info"
|
||||
56
deploy/examples/mcp.toml
Normal file
56
deploy/examples/mcp.toml
Normal file
@@ -0,0 +1,56 @@
|
||||
# MCP CLI configuration
|
||||
#
|
||||
# Default location: ~/.config/mcp/mcp.toml
|
||||
# Override with: mcp --config /path/to/mcp.toml
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Service definitions
|
||||
# ------------------------------------------------------------------
|
||||
[services]
|
||||
# Directory containing service definition TOML files (one per service).
|
||||
# Each file declares the components, images, ports, and volumes for a
|
||||
# service. The CLI reads these files to push intent to agents.
|
||||
dir = "~/.config/mcp/services"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# MCIAS authentication
|
||||
# ------------------------------------------------------------------
|
||||
[mcias]
|
||||
# URL of the MCIAS server used for login and token validation.
|
||||
server_url = "https://mcias.svc.mcp.metacircular.net:8443"
|
||||
|
||||
# Path to the CA certificate that signed the MCIAS TLS certificate.
|
||||
# If empty, the system trust store is used.
|
||||
ca_cert = "/usr/local/share/ca-certificates/metacircular-ca.crt"
|
||||
|
||||
# Service name presented to MCIAS during authentication. This must
|
||||
# match a service registered in MCIAS.
|
||||
service_name = "mcp"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Token storage
|
||||
# ------------------------------------------------------------------
|
||||
[auth]
|
||||
# Path where the CLI stores the MCIAS bearer token after login.
|
||||
# The file is created with 0600 permissions.
|
||||
token_path = "~/.config/mcp/token"
|
||||
|
||||
# Optional: username for unattended (non-interactive) operation.
|
||||
# When set alongside password_file, "mcp login" uses these
|
||||
# credentials automatically instead of prompting.
|
||||
# username = "admin"
|
||||
|
||||
# Optional: path to a file containing the password. The file should
|
||||
# be owned by the operator and have 0600 permissions.
|
||||
# password_file = "~/.config/mcp/password"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Managed nodes
|
||||
# ------------------------------------------------------------------
|
||||
# Each [[nodes]] entry registers a node that the CLI can target.
|
||||
# The name must match the node_name in the agent's config. The
|
||||
# address is host:port on the overlay network.
|
||||
|
||||
[[nodes]]
|
||||
name = "rift"
|
||||
address = "100.95.252.120:9444"
|
||||
92
deploy/scripts/install-agent.sh
Executable file
92
deploy/scripts/install-agent.sh
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env bash
|
||||
# install-agent.sh -- Install and configure the MCP agent.
|
||||
#
|
||||
# Usage: install-agent.sh [path-to-mcp-agent-binary]
|
||||
#
|
||||
# This script is idempotent and safe to run multiple times.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "$(id -u)" -ne 0 ]]; then
|
||||
echo "error: this script must be run as root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DEPLOY_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
BINARY="${1:-./mcp-agent}"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 1. Create mcp user and group
|
||||
# ------------------------------------------------------------------
|
||||
if ! id -u mcp &>/dev/null; then
|
||||
useradd --system --shell /sbin/nologin --home-dir /srv/mcp --no-create-home mcp
|
||||
echo "Created system user: mcp"
|
||||
else
|
||||
echo "User mcp already exists"
|
||||
fi
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 2. Create directories
|
||||
# ------------------------------------------------------------------
|
||||
install -d -o mcp -g mcp -m 0750 /srv/mcp
|
||||
install -d -o mcp -g mcp -m 0750 /srv/mcp/certs
|
||||
install -d -o mcp -g mcp -m 0750 /srv/mcp/backups
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 3. Install binary
|
||||
# ------------------------------------------------------------------
|
||||
if [[ ! -f "${BINARY}" ]]; then
|
||||
echo "error: binary not found: ${BINARY}" >&2
|
||||
echo "Usage: $0 [path-to-mcp-agent-binary]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install -o root -g root -m 0755 "${BINARY}" /usr/local/bin/mcp-agent
|
||||
echo "Installed mcp-agent to /usr/local/bin/mcp-agent"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 4. Install example config if none exists
|
||||
# ------------------------------------------------------------------
|
||||
if [[ ! -f /srv/mcp/mcp-agent.toml ]]; then
|
||||
install -o mcp -g mcp -m 0640 "${DEPLOY_DIR}/examples/mcp-agent.toml" /srv/mcp/mcp-agent.toml
|
||||
echo "Installed example config to /srv/mcp/mcp-agent.toml (edit before starting)"
|
||||
else
|
||||
echo "Config /srv/mcp/mcp-agent.toml already exists, skipping"
|
||||
fi
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 5. Install systemd units
|
||||
# ------------------------------------------------------------------
|
||||
install -o root -g root -m 0644 "${DEPLOY_DIR}/systemd/mcp-agent.service" /etc/systemd/system/
|
||||
install -o root -g root -m 0644 "${DEPLOY_DIR}/systemd/mcp-agent-backup.service" /etc/systemd/system/
|
||||
install -o root -g root -m 0644 "${DEPLOY_DIR}/systemd/mcp-agent-backup.timer" /etc/systemd/system/
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 6. Reload systemd
|
||||
# ------------------------------------------------------------------
|
||||
systemctl daemon-reload
|
||||
echo "Systemd units installed and daemon reloaded"
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# 7. Next steps
|
||||
# ------------------------------------------------------------------
|
||||
cat <<'NEXT'
|
||||
|
||||
--- Next steps ---
|
||||
1. Edit /srv/mcp/mcp-agent.toml:
|
||||
- Set server.grpc_addr to this node's overlay IP
|
||||
- Set agent.node_name to this node's name
|
||||
- Set mcias.server_url to the MCIAS server address
|
||||
- Place TLS cert/key in /srv/mcp/certs/
|
||||
|
||||
2. Enable and start the agent:
|
||||
systemctl enable --now mcp-agent
|
||||
|
||||
3. Enable the daily backup timer:
|
||||
systemctl enable --now mcp-agent-backup.timer
|
||||
|
||||
4. Verify the agent is running:
|
||||
systemctl status mcp-agent
|
||||
journalctl -u mcp-agent -f
|
||||
NEXT
|
||||
25
deploy/systemd/mcp-agent-backup.service
Normal file
25
deploy/systemd/mcp-agent-backup.service
Normal file
@@ -0,0 +1,25 @@
|
||||
[Unit]
|
||||
Description=MCP Agent database backup
|
||||
After=mcp-agent.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/bin/mcp-agent snapshot --config /srv/mcp/mcp-agent.toml
|
||||
|
||||
User=mcp
|
||||
Group=mcp
|
||||
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictSUIDSGID=true
|
||||
RestrictNamespaces=true
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
RestrictRealtime=true
|
||||
ReadWritePaths=/srv
|
||||
10
deploy/systemd/mcp-agent-backup.timer
Normal file
10
deploy/systemd/mcp-agent-backup.timer
Normal file
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Daily MCP Agent database backup
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-* 02:00:00
|
||||
RandomizedDelaySec=300
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
31
deploy/systemd/mcp-agent.service
Normal file
31
deploy/systemd/mcp-agent.service
Normal file
@@ -0,0 +1,31 @@
|
||||
[Unit]
|
||||
Description=MCP Agent
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/local/bin/mcp-agent server --config /srv/mcp/mcp-agent.toml
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
User=mcp
|
||||
Group=mcp
|
||||
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
PrivateDevices=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectKernelModules=true
|
||||
ProtectControlGroups=true
|
||||
RestrictSUIDSGID=true
|
||||
RestrictNamespaces=true
|
||||
LockPersonality=true
|
||||
MemoryDenyWriteExecute=true
|
||||
RestrictRealtime=true
|
||||
ReadWritePaths=/srv
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user