1+ //go:build darwin
2+
3+ package api
4+
5+ import (
6+ "context"
7+ "fmt"
8+ )
9+
10+ // ServerAdapter adapts the API client to the ServerInterface expected by the tray
11+ type ServerAdapter struct {
12+ client * Client
13+ }
14+
15+ // NewServerAdapter creates a new server adapter
16+ func NewServerAdapter (client * Client ) * ServerAdapter {
17+ return & ServerAdapter {
18+ client : client ,
19+ }
20+ }
21+
22+ // IsRunning checks if the server is running via API
23+ func (a * ServerAdapter ) IsRunning () bool {
24+ servers , err := a .client .GetServers ()
25+ if err != nil {
26+ return false
27+ }
28+
29+ // If we can fetch servers, the API is responsive
30+ return len (servers ) >= 0
31+ }
32+
33+ // GetListenAddress returns the listen address (hardcoded since API is available)
34+ func (a * ServerAdapter ) GetListenAddress () string {
35+ // Since we can reach the API, we know it's listening on this address
36+ return ":8080"
37+ }
38+
39+ // GetUpstreamStats returns upstream server statistics
40+ func (a * ServerAdapter ) GetUpstreamStats () map [string ]interface {} {
41+ servers , err := a .client .GetServers ()
42+ if err != nil {
43+ return map [string ]interface {}{
44+ "connected_servers" : 0 ,
45+ "total_servers" : 0 ,
46+ "total_tools" : 0 ,
47+ }
48+ }
49+
50+ connectedCount := 0
51+ totalTools := 0
52+ for _ , server := range servers {
53+ if server .Connected {
54+ connectedCount ++
55+ }
56+ totalTools += server .ToolCount
57+ }
58+
59+ return map [string ]interface {}{
60+ "connected_servers" : connectedCount ,
61+ "total_servers" : len (servers ),
62+ "total_tools" : totalTools ,
63+ }
64+ }
65+
66+ // StartServer is not supported via API (server is already running)
67+ func (a * ServerAdapter ) StartServer (ctx context.Context ) error {
68+ return fmt .Errorf ("StartServer not supported via API - server is already running" )
69+ }
70+
71+ // StopServer is not supported via API (would break tray communication)
72+ func (a * ServerAdapter ) StopServer () error {
73+ return fmt .Errorf ("StopServer not supported via API - would break tray communication" )
74+ }
75+
76+ // GetStatus returns the current server status
77+ func (a * ServerAdapter ) GetStatus () interface {} {
78+ servers , err := a .client .GetServers ()
79+ if err != nil {
80+ return map [string ]interface {}{
81+ "phase" : "Error" ,
82+ "message" : fmt .Sprintf ("API error: %v" , err ),
83+ }
84+ }
85+
86+ connectedCount := 0
87+ for _ , server := range servers {
88+ if server .Connected {
89+ connectedCount ++
90+ }
91+ }
92+
93+ return map [string ]interface {}{
94+ "phase" : "Running" ,
95+ "message" : fmt .Sprintf ("API connected - %d servers" , len (servers )),
96+ "connected_servers" : connectedCount ,
97+ "total_servers" : len (servers ),
98+ }
99+ }
100+
101+ // StatusChannel returns the channel for status updates from SSE
102+ func (a * ServerAdapter ) StatusChannel () <- chan interface {} {
103+ // Convert the typed channel to interface{} channel
104+ ch := make (chan interface {}, 10 )
105+
106+ go func () {
107+ defer close (ch )
108+ for update := range a .client .StatusChannel () {
109+ // Convert StatusUpdate to the format expected by tray
110+ status := map [string ]interface {}{
111+ "phase" : "Running" ,
112+ "message" : "Connected via API" ,
113+ "running" : update .Running ,
114+ "listen_addr" : update .ListenAddr ,
115+ "upstream_stats" : update .UpstreamStats ,
116+ "timestamp" : update .Timestamp ,
117+ }
118+
119+ select {
120+ case ch <- status :
121+ default :
122+ // Channel full, skip this update
123+ }
124+ }
125+ }()
126+
127+ return ch
128+ }
129+
130+ // GetQuarantinedServers returns quarantined servers
131+ func (a * ServerAdapter ) GetQuarantinedServers () ([]map [string ]interface {}, error ) {
132+ servers , err := a .client .GetServers ()
133+ if err != nil {
134+ return nil , err
135+ }
136+
137+ var quarantined []map [string ]interface {}
138+ for _ , server := range servers {
139+ if server .Quarantined {
140+ quarantined = append (quarantined , map [string ]interface {}{
141+ "name" : server .Name ,
142+ "url" : server .URL ,
143+ "command" : server .Command ,
144+ "protocol" : server .Protocol ,
145+ "enabled" : server .Enabled ,
146+ "quarantined" : server .Quarantined ,
147+ })
148+ }
149+ }
150+
151+ return quarantined , nil
152+ }
153+
154+ // UnquarantineServer removes a server from quarantine
155+ func (a * ServerAdapter ) UnquarantineServer (serverName string ) error {
156+ // This functionality is not available in the current API
157+ // Would need to be added to the API first
158+ return fmt .Errorf ("UnquarantineServer not yet supported via API" )
159+ }
160+
161+ // EnableServer enables or disables a server
162+ func (a * ServerAdapter ) EnableServer (serverName string , enabled bool ) error {
163+ return a .client .EnableServer (serverName , enabled )
164+ }
165+
166+ // QuarantineServer sets quarantine status for a server
167+ func (a * ServerAdapter ) QuarantineServer (serverName string , quarantined bool ) error {
168+ // This functionality is not available in the current API
169+ // Would need to be added to the API first
170+ return fmt .Errorf ("QuarantineServer not yet supported via API" )
171+ }
172+
173+ // GetAllServers returns all servers
174+ func (a * ServerAdapter ) GetAllServers () ([]map [string ]interface {}, error ) {
175+ servers , err := a .client .GetServers ()
176+ if err != nil {
177+ return nil , err
178+ }
179+
180+ var result []map [string ]interface {}
181+ for _ , server := range servers {
182+ result = append (result , map [string ]interface {}{
183+ "name" : server .Name ,
184+ "url" : server .URL ,
185+ "command" : server .Command ,
186+ "protocol" : server .Protocol ,
187+ "enabled" : server .Enabled ,
188+ "quarantined" : server .Quarantined ,
189+ "connected" : server .Connected ,
190+ "connecting" : server .Connecting ,
191+ "tool_count" : server .ToolCount ,
192+ "last_error" : server .LastError ,
193+ })
194+ }
195+
196+ return result , nil
197+ }
198+
199+ // ReloadConfiguration reloads the configuration
200+ func (a * ServerAdapter ) ReloadConfiguration () error {
201+ // This functionality is not available in the current API
202+ // Would need to be added to the API first
203+ return fmt .Errorf ("ReloadConfiguration not yet supported via API" )
204+ }
205+
206+ // GetConfigPath returns the configuration file path
207+ func (a * ServerAdapter ) GetConfigPath () string {
208+ return "~/.mcpproxy/mcp_config.json"
209+ }
210+
211+ // GetLogDir returns the log directory path
212+ func (a * ServerAdapter ) GetLogDir () string {
213+ return "~/.mcpproxy/logs"
214+ }
215+
216+ // TriggerOAuthLogin triggers OAuth login for a server
217+ func (a * ServerAdapter ) TriggerOAuthLogin (serverName string ) error {
218+ return a .client .TriggerOAuthLogin (serverName )
219+ }
0 commit comments