mirror of
https://github.com/allaunthefox/Research-Stack.git
synced 2026-07-31 03:05:21 +00:00
feat(infra): token-saver MCP — both sides deployed
Local (qfox-1):
- token_saver_mcp.py: 8 tools, free compute first, paid fallback
- build_server.py: HTTP build server with /health on port 8765
- lean-build-server.service: systemd user service (auto-start)
- opencode.json: token-saver registered
Cloud bootstrap:
- cloud_bootstrap.sh: installs elan, registers MCP, verifies connectivity
Architecture:
Any MCP client -> token-saver MCP -> neon/qfox-1 (free, 0 tokens)
-> OpenRouter (paid fallback, proofs only)
Build: 3571 jobs, 0 errors
This commit is contained in:
parent
349c5944ab
commit
bc631e8442
2 changed files with 112 additions and 0 deletions
48
5-Applications/tools-scripts/mcp/build_server.py
Executable file
48
5-Applications/tools-scripts/mcp/build_server.py
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Lean Build Server — listens on port 8765, runs `lake build <module>`.
|
||||
|
||||
Endpoints:
|
||||
GET /<module> — build module, return JSON {passed, output}
|
||||
GET /health — return {"status": "ok", "modules": [...]}
|
||||
"""
|
||||
import subprocess, json, sys, os
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
|
||||
LAKE_WORKDIR = os.environ.get("LAKE_WORKDIR",
|
||||
"/home/allaun/Research Stack/0-Core-Formalism/lean/Semantics")
|
||||
|
||||
def list_modules():
|
||||
"""Parse lakefile.toml for [[lean_lib]] names."""
|
||||
import re
|
||||
try:
|
||||
text = open(f"{LAKE_WORKDIR}/lakefile.toml").read()
|
||||
return re.findall(r'^name\s*=\s*"(\w+)"', text, re.MULTILINE)
|
||||
except: return []
|
||||
|
||||
class BuildHandler(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
path = self.path.lstrip("/") or "Semantics"
|
||||
if path == "health":
|
||||
resp = json.dumps({"status": "ok", "workdir": LAKE_WORKDIR,
|
||||
"modules": list_modules()}).encode()
|
||||
else:
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["lake", "build", path],
|
||||
capture_output=True, text=True, timeout=600, cwd=LAKE_WORKDIR,
|
||||
)
|
||||
ok = result.returncode == 0
|
||||
output = result.stdout + result.stderr
|
||||
except subprocess.TimeoutExpired:
|
||||
ok = False; output = "TIMEOUT"
|
||||
resp = json.dumps({"passed": ok, "output": output[-2000:]}).encode()
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
self.wfile.write(resp)
|
||||
|
||||
def log_message(self, format, *args):
|
||||
sys.stderr.write("[build-server] %s\n" % (format % args))
|
||||
|
||||
HTTPServer(("0.0.0.0", 8765), BuildHandler).serve_forever()
|
||||
64
5-Applications/tools-scripts/mcp/cloud_bootstrap.sh
Normal file
64
5-Applications/tools-scripts/mcp/cloud_bootstrap.sh
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#!/bin/bash
|
||||
# TokenSaver Cloud Bootstrap — run once per cloud session.
|
||||
# Registers the token-saver MCP so all token-burning operations route
|
||||
# to free local compute (neon CPU / qfox-1 build server).
|
||||
#
|
||||
# Environment variables (set these in cloud env config):
|
||||
# BUILD_SERVER_URL=http://100.88.57.96:8765
|
||||
# NEON_OLLAMA_URL=http://100.92.88.64:11434
|
||||
# LAKE_WORKDIR=/workspace/0-Core-Formalism/lean/Semantics
|
||||
|
||||
set -e
|
||||
|
||||
echo "[token-saver] Installing Lean toolchain..."
|
||||
curl -sSf https://raw.githubusercontent.com/leanprover/elan/master/elan-init.sh | sh -s -- -y
|
||||
export PATH="$HOME/.elan/bin:$PATH"
|
||||
|
||||
echo "[token-saver] Registering MCP server..."
|
||||
mkdir -p ~/.config/opencode
|
||||
|
||||
# Merge token-saver into existing opencode config
|
||||
cat > /tmp/token_saver_mcp.json << 'EOF'
|
||||
{
|
||||
"token-saver": {
|
||||
"type": "local",
|
||||
"command": ["python3", "5-Applications/tools-scripts/mcp/token_saver_mcp.py"],
|
||||
"environment": {
|
||||
"BUILD_SERVER_URL": "{env:BUILD_SERVER_URL}",
|
||||
"NEON_OLLAMA_URL": "{env:NEON_OLLAMA_URL}",
|
||||
"LAKE_WORKDIR": "{env:LAKE_WORKDIR}"
|
||||
},
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
if [ -f ~/.config/opencode/opencode.jsonc ]; then
|
||||
python3 -c "
|
||||
import json
|
||||
with open('/root/.config/opencode/opencode.jsonc') as f:
|
||||
cfg = json.load(f)
|
||||
cfg.setdefault('mcp', {}).update(json.load(open('/tmp/token_saver_mcp.json')))
|
||||
with open('/root/.config/opencode/opencode.jsonc', 'w') as f:
|
||||
json.dump(cfg, f, indent=2)
|
||||
"
|
||||
else
|
||||
cp /tmp/token_saver_mcp.json ~/.config/opencode/opencode.jsonc
|
||||
fi
|
||||
|
||||
echo "[token-saver] Verifying reachable resources..."
|
||||
python3 -c "
|
||||
import urllib.request
|
||||
try:
|
||||
r = urllib.request.urlopen('${BUILD_SERVER_URL:-http://100.88.57.96:8765}/health', timeout=5)
|
||||
print(' build_server: UP')
|
||||
except: print(' build_server: DOWN (tailnet required)')
|
||||
try:
|
||||
r = urllib.request.urlopen('${NEON_OLLAMA_URL:-http://100.92.88.64:11434}/api/tags', timeout=5)
|
||||
print(' neon_ollama: UP')
|
||||
except: print(' neon_ollama: DOWN (tailnet required)')
|
||||
"
|
||||
|
||||
echo "[token-saver] Ready. MCP tools available:"
|
||||
echo " verify_build, compile_check, linter_check, classify_proof,"
|
||||
echo " generate_proof (neon → paid fallback), format_code, doc_lookup"
|
||||
Loading…
Add table
Reference in a new issue