Skip to content

Commit 6947ce6

Browse files
committed
Refactor server configuration loading and enhance tray UI management
- Updated server configuration loading to synchronize with storage and upstream manager. - Improved handling of server states, including enabling/disabling and quarantine management. - Added config file watching to automatically reload settings and refresh UI. - Enhanced server action handling in the tray UI for better user experience.
1 parent 9513e2c commit 6947ce6

11 files changed

Lines changed: 1777 additions & 949 deletions

File tree

internal/config/loader.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,11 @@ func loadConfigFile(path string, cfg *Config) error {
159159
return fmt.Errorf("failed to parse config file: %w", err)
160160
}
161161

162-
// Enable all servers by default if not specified
162+
// Set created time if not specified
163163
for _, server := range cfg.Servers {
164164
if server.Created.IsZero() {
165-
server.Created = now()
166-
}
167-
// Default to enabled if not explicitly set
168-
if !server.Enabled && server.URL != "" || server.Command != "" {
169-
server.Enabled = true
165+
// Use a consistent time function if `now()` is not defined in this package
166+
server.Created = time.Now()
170167
}
171168
}
172169

internal/server/e2e_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ func (env *TestEnvironment) waitForServerReady() {
137137
case <-ticker.C:
138138
if env.proxyServer.IsRunning() {
139139
// Give it a bit more time to fully initialize
140-
time.Sleep(500 * time.Millisecond)
140+
time.Sleep(2 * time.Second)
141141
return
142142
}
143143
}

internal/server/mcp.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ func (p *MCPProxyServer) registerTools(debugSearch bool) {
118118
),
119119
mcp.WithObject("args",
120120
mcp.Description("Arguments to pass to the tool. Refer to the tool's inputSchema from retrieve_tools for required parameters."),
121+
mcp.AdditionalProperties(true),
121122
),
122123
)
123124
p.server.AddTool(callToolTool, p.handleCallTool)
@@ -158,6 +159,7 @@ func (p *MCPProxyServer) registerTools(debugSearch bool) {
158159
),
159160
mcp.WithObject("env",
160161
mcp.Description("Environment variables for stdio servers"),
162+
mcp.AdditionalProperties(true),
161163
),
162164
mcp.WithString("url",
163165
mcp.Description("Server URL for HTTP/SSE servers (e.g., 'http://localhost:3001')"),
@@ -168,6 +170,7 @@ func (p *MCPProxyServer) registerTools(debugSearch bool) {
168170
),
169171
mcp.WithObject("headers",
170172
mcp.Description("HTTP headers for authentication (e.g., {'Authorization': 'Bearer token'})"),
173+
mcp.AdditionalProperties(true),
171174
),
172175
mcp.WithBoolean("enabled",
173176
mcp.Description("Whether server should be enabled (default: true)"),
@@ -177,9 +180,11 @@ func (p *MCPProxyServer) registerTools(debugSearch bool) {
177180
),
178181
mcp.WithObject("cursor_config",
179182
mcp.Description("Cursor IDE mcpServers configuration object for direct import"),
183+
mcp.AdditionalProperties(true),
180184
),
181185
mcp.WithObject("patch",
182186
mcp.Description("Fields to update for patch operations"),
187+
mcp.AdditionalProperties(true),
183188
),
184189
)
185190
p.server.AddTool(upstreamServersTool, p.handleUpstreamServers)

internal/server/mcp_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package server
22

33
import (
4+
"bytes"
45
"context"
56
"encoding/json"
7+
"net/http"
8+
"net/http/httptest"
69
"strings"
710
"testing"
811
"time"
@@ -812,3 +815,63 @@ func TestE2E_QuarantineFunctionality(t *testing.T) {
812815
}
813816

814817
// Test: Error handling and recovery
818+
func TestHandleV1ToolProxy(t *testing.T) {
819+
tests := []struct {
820+
name string
821+
toolName string
822+
serverID string
823+
wantErr string
824+
result *mcp.CallToolResult
825+
client *mockToolClient
826+
}{
827+
{
828+
name: "disabled client",
829+
toolName: "disabled-tool",
830+
serverID: "disabled-server",
831+
wantErr: "client for server disabled-server is disabled",
832+
result: &mcp.CallToolResult{
833+
ToolName: "disabled-tool",
834+
},
835+
client: &mockToolClient{},
836+
},
837+
}
838+
839+
for _, tc := range tests {
840+
t.Run(tc.name, func(t *testing.T) {
841+
s := &MCPProxyServer{
842+
upstreamManager: upstream.NewManager(zap.NewNop()),
843+
logger: zap.NewNop(),
844+
}
845+
846+
s.upstreamManager.AddServer(&config.ServerConfig{
847+
ID: tc.serverID,
848+
Enabled: tc.name != "disabled client",
849+
})
850+
851+
if tc.client != nil {
852+
s.upstreamManager.AddClient(tc.serverID, tc.client)
853+
}
854+
855+
rec := httptest.NewRecorder()
856+
req := httptest.NewRequest(http.MethodPost, "/v1/tools", bytes.NewBufferString(`{"name": "`+tc.toolName+`"}`))
857+
req.Header.Set("Content-Type", "application/json")
858+
859+
s.handleV1ToolProxy(rec, req)
860+
861+
require.NoError(t, err)
862+
assert.Equal(t, http.StatusOK, rec.Code)
863+
864+
var result mcp.CallToolResult
865+
require.NoError(t, json.Unmarshal(rec.Body.Bytes(), &result))
866+
867+
if tc.wantErr != "" {
868+
require.Len(t, result.Outputs, 1)
869+
var content map[string]string
870+
require.NoError(t, json.Unmarshal([]byte(result.Outputs[0].Content), &content))
871+
assert.Equal(t, tc.wantErr, content["error"])
872+
} else {
873+
assert.Equal(t, "test-output", result.Outputs[0].Content)
874+
}
875+
})
876+
}
877+
}

0 commit comments

Comments
 (0)