From 3f60e1d9d5fa3dc18f0003c78c6ea4ce9d32c02c Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Sat, 4 Jul 2026 21:53:35 +0000 Subject: [PATCH] fix: don't abort a turn when one MCP session can't list tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit usableTools returned an error if ANY mcpSession's ListTools/ListPrompts failed, so a single session that is momentarily unavailable (mid-reconnect, or being closed/rebuilt by a config reload — surfaced by the go-sdk as "client is closing: hanging GET: failed to reconnect") aborted the whole turn. This is what broke /learn in dante-desktop. Skip the unhealthy session for this turn and log a warning; its tools return once it is healthy again. Co-Authored-By: Claude Opus 4.8 (1M context) --- guidelines.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/guidelines.go b/guidelines.go index e932fdb..543b8ee 100644 --- a/guidelines.go +++ b/guidelines.go @@ -6,6 +6,7 @@ import ( "github.com/mudler/cogito/prompt" "github.com/mudler/cogito/structures" + "github.com/mudler/xlog" "github.com/sashabaranov/go-openai" ) @@ -154,7 +155,13 @@ func usableTools(llm LLM, fragment Fragment, opts ...Option) (Tools, Guidelines, for _, session := range o.mcpSessions { mcpTools, err := mcpToolsFromTransport(o.context, session, o.mcpToolFilter) if err != nil { - return Tools{}, Guidelines{}, nil, fmt.Errorf("failed to get MCP tools: %w", err) + // A single MCP session that is momentarily unavailable (e.g. a client + // mid-reconnect or being closed/rebuilt by a config reload — the go-sdk + // surfaces this as "client is closing: hanging GET: failed to reconnect") + // must not abort the whole turn. Skip this session's tools/prompts for + // this turn; they come back once the session is healthy again. + xlog.Warn("cogito: skipping MCP session whose tools could not be listed", "error", err) + continue } for _, tool := range mcpTools { tools = append(tools, tool) @@ -162,7 +169,8 @@ func usableTools(llm LLM, fragment Fragment, opts ...Option) (Tools, Guidelines, if o.mcpPrompts { toolPrompts, err := mcpPromptsFromTransport(o.context, session, o.mcpArgs) if err != nil { - return Tools{}, Guidelines{}, nil, fmt.Errorf("failed to get MCP prompts: %w", err) + xlog.Warn("cogito: skipping MCP session whose prompts could not be listed", "error", err) + continue } prompts = append(prompts, toolPrompts...)