package main import ( "context" "flag" "fmt" "os" "runtime" "strings" "github.com/modelcontextprotocol/go-sdk/mcp" "git.julianfamily.org/keepassgo/internal/browserbridge" "git.julianfamily.org/keepassgo/internal/grpcaddr" "git.julianfamily.org/keepassgo/internal/mcpserver" ) var version = "dev" func main() { if err := run(context.Background(), os.Args[1:]); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } func run(ctx context.Context, args []string) error { fs := flag.NewFlagSet("keepassgo-mcp-server", flag.ContinueOnError) grpcAddress := fs.String("grpc-addr", envOrDefault("KEEPASSGO_GRPC_ADDR", grpcaddr.Default(runtime.GOOS)), "KeePassGO gRPC address") if err := fs.Parse(args); err != nil { return err } token := mcpToken() if token == "" { return fmt.Errorf("KeePassGO MCP bearer token is required; set KEEPASSGO_MCP_TOKEN or KEEPASSGO_BEARER_TOKEN") } conn, client, callCtx, err := browserbridge.Dial(ctx, browserbridge.Connection{ GRPCAddress: strings.TrimSpace(*grpcAddress), BearerToken: token, }) if err != nil { return err } defer func() { _ = conn.Close() }() server := mcpserver.New(client, mcpserver.Config{ GRPCAddress: strings.TrimSpace(*grpcAddress), Version: version, }) return server.Run(callCtx, &mcp.StdioTransport{}) } func envOrDefault(name, fallback string) string { if value := strings.TrimSpace(os.Getenv(name)); value != "" { return value } return fallback } func mcpToken() string { if token := strings.TrimSpace(os.Getenv("KEEPASSGO_MCP_TOKEN")); token != "" { return token } return strings.TrimSpace(os.Getenv("KEEPASSGO_BEARER_TOKEN")) }