Skip to content

Fix crash in gptel-mcp--activate-tools when requested servers return no tools#1321

Open
benthamite wants to merge 1 commit intokarthink:masterfrom
benthamite:fix/mcp-activate-tools-nil-crash
Open

Fix crash in gptel-mcp--activate-tools when requested servers return no tools#1321
benthamite wants to merge 1 commit intokarthink:masterfrom
benthamite:fix/mcp-activate-tools-nil-crash

Conversation

@benthamite
Copy link
Copy Markdown
Contributor

@benthamite benthamite commented Mar 28, 2026

Problem

gptel-mcp-connect has two bugs in its add-all-tools callback that surface when calling it programmatically for specific servers:

Bug 1: Crash on nil tools list

When the requested servers fail to start or return no tools, the callback passes nil to gptel-mcp--activate-tools. Its (unless tools ...) fallback fetches tools from all connected MCP servers and tries to look them up via gptel-get-tool, crashing on tools from servers that were never registered with gptel-make-tool:

No tool matches for ("mcp-home-assistant" "HassTurnOn")

even though home-assistant was never requested.

Bug 2: Active-but-unregistered servers skipped

When there is a mix of active-but-unregistered and inactive-but-unregistered servers, the callback's fallback (mapcar #'car inactive-servers) only processes the inactive ones. Tools from already-active servers that still need registration are silently dropped.

For example, if brave-search (active, connected) and slack (inactive, init) are both unregistered:

  1. mcp-hub-start-all-server starts only slack
  2. The callback falls back to inactive-servers → only slack
  3. brave-search tools are never registered despite being available

Fix

Two one-line changes in the add-all-tools lambda:

  1. Guard gptel-mcp--activate-tools with when so nil means "nothing to activate" rather than "activate everything".
  2. Change the fallback from inactive-servers to servers (all unregistered), so the callback registers tools from every server that needs it—both those just started and those already active.

Two bugs in the `add-all-tools` callback inside `gptel-mcp-connect`:

1. When called for specific servers that fail to start or return no
tools, the callback passes nil to `gptel-mcp--activate-tools`.  Its
`(unless tools ...)` fallback fetches tools from ALL connected MCP
servers and tries to look them up via `gptel-get-tool`, crashing on
tools never registered with `gptel-make-tool`.

Fix: guard the call with `when` so nil means "nothing to activate".

2. When there is a mix of active-but-unregistered and inactive servers,
only the inactive servers' tools are registered.  The callback's
fallback `(mapcar #'car inactive-servers)` skips the already-active
servers entirely, so their tools are never passed to `gptel-make-tool`.

Fix: use `servers` (all unregistered) instead of `inactive-servers`
in the fallback, so the callback registers tools from every server
that needs it.
@benthamite benthamite force-pushed the fix/mcp-activate-tools-nil-crash branch from 5a53975 to e6a6764 Compare March 28, 2026 23:59
@karthink
Copy link
Copy Markdown
Owner

karthink commented Apr 6, 2026

Thanks for the PR @benthamite. I took a brief look but didn't understand the logic. gptel-mcp-connect does too much, I think. I'll have to spend more time on it and verify the fix (and maybe the design of the function) before merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants