package mcpserver import ( "fmt" "os" "strings" "github.com/modelcontextprotocol/go-sdk/mcp" "isphere-ai-bridge/internal/helperclient" "isphere-ai-bridge/internal/isphere" "isphere-ai-bridge/internal/msglib" "isphere-ai-bridge/internal/tools" ) const ( ServerName = "isphere-ai-bridge" ServerTitle = "iSphere AI Bridge" ServerVersion = "0.1.0" EnvPacketLogFileKey = "ISPHERE_PACKET_LOG_FILE" EnvPacketLogDirKey = "ISPHERE_PACKET_LOG_DIR" EnvMsgLibSidecarExeKey = "ISPHERE_MSGLIB_SIDECAR_EXE" EnvMsgLibSQLiteDLLKey = "ISPHERE_MSGLIB_SQLITE_DLL" EnvMsgLibDBKey = "ISPHERE_MSGLIB_DB" ) func NewServer() *mcp.Server { return NewServerWithReceiveSource(isphere.EncryptedPacketLogSource{}) } func NewServerFromEnv() (*mcp.Server, error) { var source tools.ReceiveMessagesSource = isphere.EncryptedPacketLogSource{} packetLogFile := strings.TrimSpace(os.Getenv(EnvPacketLogFileKey)) packetLogDir := strings.TrimSpace(os.Getenv(EnvPacketLogDirKey)) if packetLogFile != "" && packetLogDir != "" { return nil, fmt.Errorf("configure packet log source: set only one of %s or %s", EnvPacketLogFileKey, EnvPacketLogDirKey) } if packetLogFile != "" { loaded, err := isphere.LoadEncryptedPacketLogSourceFromFile(packetLogFile) if err != nil { return nil, fmt.Errorf("configure %s: %w", EnvPacketLogFileKey, err) } source = loaded } else if packetLogDir != "" { loaded, err := isphere.LoadEncryptedPacketLogSourceFromDirectory(packetLogDir) if err != nil { return nil, fmt.Errorf("configure %s: %w", EnvPacketLogDirKey, err) } source = loaded } displaySource, err := msgLibDisplayEntitySourceFromEnv() if err != nil { return nil, err } return NewServerWithSources(source, displaySource), nil } func msgLibDisplayEntitySourceFromEnv() (tools.DisplayEntitySource, error) { sidecarExe := strings.TrimSpace(os.Getenv(EnvMsgLibSidecarExeKey)) sqliteDLL := strings.TrimSpace(os.Getenv(EnvMsgLibSQLiteDLLKey)) dbPath := strings.TrimSpace(os.Getenv(EnvMsgLibDBKey)) configured := 0 for _, value := range []string{sidecarExe, sqliteDLL, dbPath} { if value != "" { configured++ } } if configured == 0 { return nil, nil } if configured != 3 { return nil, fmt.Errorf("configure MsgLib source: set all of %s, %s, and %s, or set none", EnvMsgLibSidecarExeKey, EnvMsgLibSQLiteDLLKey, EnvMsgLibDBKey) } cfg, err := msglib.ConfigFromEnv() if err != nil { return nil, fmt.Errorf("configure MsgLib source: %w", err) } return msglib.NewClient(cfg), nil } func NewServerWithReceiveSource(source tools.ReceiveMessagesSource) *mcp.Server { return NewServerWithSources(source, nil) } func NewServerWithSources(source tools.ReceiveMessagesSource, displaySource tools.DisplayEntitySource) *mcp.Server { server := mcp.NewServer(&mcp.Implementation{ Name: ServerName, Title: ServerTitle, Version: ServerVersion, }, nil) tools.RegisterWinHelperTools(server, helperclient.Client{}) tools.RegisterISphereReadTools(server, source) tools.RegisterISphereContactToolsWithDisplayEntities(server, source, displaySource) tools.RegisterISphereGroupToolsWithDisplayEntities(server, source, displaySource) tools.RegisterISphereFileTools(server, source) return server }