490e688cc1
One lmcp server on a central host (typically hertz) that proxies
remote_* tools to every backend in a registry, with a clean SSH
fallback for hosts whose lmcp is temporarily down or not installed.
Tools: remote_list_hosts, remote_{shell,read_file,write_file,edit_file,
list_dir,search_files}. Each takes a `host` argument naming the target
in /opt/herding/etc/hub-backends.conf (or $LMCP_HUB_BACKENDS).
Lazy 30s health cache; `remote_list_hosts force=true` bypasses it.
Bearer auth on inbound (standard lmcp opts.conf / LMCP_TOKEN machinery);
backend Bearer tokens kept in the registry and forwarded per-call.
SSH fallback uses `ssh host 'bash -s' < local_script` — stdin-piped
script body is the canonical shell-escape-free technique. Covers
shell/read_file/write_file/list_dir/search_files. edit_file is lmcp-only
because the literal-match + uniqueness check is nontrivial to replicate
safely in shell.
Ships an example systemd unit and a commented backends.conf template
in examples/. No migration required for existing lmcp deployments —
hub.lua is additive alongside the existing server.lua.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
26 lines
745 B
Desktop File
26 lines
745 B
Desktop File
[Unit]
|
|
Description=lmcp hub — fleet MCP broker
|
|
After=network.target
|
|
Wants=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=mfritsche
|
|
Group=mfritsche
|
|
# When deploying, copy hub.lua to /opt/lmcp/ or adjust the path below.
|
|
ExecStart=/usr/bin/lua5.4 /usr/share/lua/5.4/hub.lua
|
|
Environment=LMCP_NAME=hub-tools
|
|
Environment=LMCP_PORT=8090
|
|
# Backend registry: space-separated "name ssh_host lmcp_url token" per line.
|
|
# See hub-backends.conf.example in this examples/ dir.
|
|
Environment=LMCP_HUB_BACKENDS=/opt/herding/etc/hub-backends.conf
|
|
# Bearer token file (key `.godparticle=<hex>`).
|
|
Environment=LMCP_HUB_CONF=/opt/herding/etc/lmcp-hub.conf
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|