mirror of
https://github.com/luxfi/mcp.git
synced 2026-09-24 00:25:04 +00:00
93 lines
2.6 KiB
Go
93 lines
2.6 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Command lux-mcp is the drop-in, READ-ONLY governance MCP server binary for the Lux
|
|
// AIVM (A-Chain) governance stack. It reads its EVM RPC URL and the four deployed
|
|
// contract addresses from the environment and serves the governance read tools over
|
|
// stdio (JSON-RPC 2.0) via the shared mcp transport. It holds no key and submits no
|
|
// transaction.
|
|
//
|
|
// Environment:
|
|
//
|
|
// LUX_GOV_EVM_RPC EVM RPC URL of the governance chain (required)
|
|
// LUX_AIPARAMS_ADDR AIParams contract address (required)
|
|
// LUX_AIGOVERNOR_ADDR AIGovernor contract address (required)
|
|
// LUX_AITHOUGHTREGISTRY_ADDR AIThoughtRegistry contract address (required)
|
|
// LUX_AIREPUTATION_ADDR AIReputation contract address (required)
|
|
//
|
|
// Drop into an MCP client (hanzo-dev / claude desktop) as a stdio server:
|
|
//
|
|
// { "command": "lux-mcp", "env": { "LUX_GOV_EVM_RPC": "https://…/v1/chain/C/rpc", … } }
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
|
|
"github.com/luxfi/geth/common"
|
|
|
|
"github.com/luxfi/mcp"
|
|
"github.com/luxfi/mcp/governance"
|
|
)
|
|
|
|
func main() {
|
|
if err := run(); err != nil {
|
|
fmt.Fprintln(os.Stderr, "lux-mcp:", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func run() error {
|
|
cfg, err := configFromEnv()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
|
defer stop()
|
|
|
|
surface, err := governance.New(ctx, cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// One transport, one surface: mcp.Serve runs the read-only stdio loop over the
|
|
// governance tools. Adding another domain is just another argument here.
|
|
return mcp.Serve(ctx, os.Stdin, os.Stdout, surface)
|
|
}
|
|
|
|
func configFromEnv() (governance.Config, error) {
|
|
var cfg governance.Config
|
|
cfg.EVMRPC = os.Getenv("LUX_GOV_EVM_RPC")
|
|
if cfg.EVMRPC == "" {
|
|
return cfg, fmt.Errorf("LUX_GOV_EVM_RPC is required")
|
|
}
|
|
var err error
|
|
if cfg.AIParams, err = envAddr("LUX_AIPARAMS_ADDR"); err != nil {
|
|
return cfg, err
|
|
}
|
|
if cfg.AIGovernor, err = envAddr("LUX_AIGOVERNOR_ADDR"); err != nil {
|
|
return cfg, err
|
|
}
|
|
if cfg.AIThoughtRegistry, err = envAddr("LUX_AITHOUGHTREGISTRY_ADDR"); err != nil {
|
|
return cfg, err
|
|
}
|
|
if cfg.AIReputation, err = envAddr("LUX_AIREPUTATION_ADDR"); err != nil {
|
|
return cfg, err
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func envAddr(name string) (common.Address, error) {
|
|
v := os.Getenv(name)
|
|
if v == "" {
|
|
return common.Address{}, fmt.Errorf("%s is required", name)
|
|
}
|
|
if !common.IsHexAddress(v) {
|
|
return common.Address{}, fmt.Errorf("%s=%q is not a valid address", name, v)
|
|
}
|
|
return common.HexToAddress(v), nil
|
|
}
|