-
Notifications
You must be signed in to change notification settings - Fork 0
Add /mcp update command to reload MCP servers without restart #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -228,6 +228,57 @@ func (c *Client) Close() { | |
| } | ||
| } | ||
|
|
||
| // Reconnect closes existing connections, replaces the server list with new configs, | ||
| // re-initializes all servers, and re-embeds tools if embeddings were enabled. | ||
| // Returns the number of tools discovered after reconnect. | ||
| func (c *Client) Reconnect(ctx context.Context, configs map[string]config.MCPServerConfig) (int, error) { | ||
| // Close old connections. | ||
| c.Close() | ||
|
|
||
| // Reset state. | ||
| c.servers = make(map[string]*server) | ||
| c.tools = nil | ||
| c.toolServers = make(map[string]string) | ||
| c.embeddingsReady = false | ||
|
|
||
| // Build new servers (same logic as NewClient). | ||
| for name, cfg := range configs { | ||
| if err := validateServerURL(cfg.URL); err != nil { | ||
| c.logger.Warn("mcp server URL rejected", "server", name, "url", cfg.URL, "err", err) | ||
| continue | ||
| } | ||
| srv := &server{ | ||
| name: name, | ||
| url: cfg.URL, | ||
| headers: cfg.Headers, | ||
| http: &http.Client{Timeout: 30 * time.Second}, | ||
| } | ||
| if len(cfg.AllowTools) > 0 { | ||
| srv.allowTools = make(map[string]bool, len(cfg.AllowTools)) | ||
| for _, t := range cfg.AllowTools { | ||
| srv.allowTools[t] = true | ||
| } | ||
| } | ||
| if len(cfg.DenyTools) > 0 { | ||
| srv.denyTools = make(map[string]bool, len(cfg.DenyTools)) | ||
| for _, t := range cfg.DenyTools { | ||
| srv.denyTools[t] = true | ||
| } | ||
| } | ||
| c.servers[name] = srv | ||
| } | ||
|
|
||
| // Initialize and discover tools. | ||
| c.Initialize(ctx) | ||
|
|
||
| // Re-embed tools if embeddings were configured. | ||
| if c.embeddingCfg.APIKey != "" || c.embeddingCfg.BaseURL != "" { | ||
| c.EmbedTools(ctx) | ||
| } | ||
|
|
||
| return len(c.tools), nil | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Concurrent map access causes fatal runtime panicHigh Severity
Additional Locations (1) |
||
|
|
||
| // CallTool executes a tool on the appropriate MCP server. | ||
| // On network failure it attempts one reconnect before giving up. | ||
| func (c *Client) CallTool(ctx context.Context, name string, argsJSON string) (string, error) { | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicated server-building logic in Reconnect and NewClient
Low Severity
The server construction loop in
Reconnect(URL validation,serverstruct creation, allow/deny tool maps) is a near-exact copy ofNewClient. Duplicating this logic means future changes (e.g., new server fields or validation rules) need to be applied in both places, risking inconsistent behavior.Additional Locations (1)
internal/mcp/client.go#L64-L97