Skip to content

[Bug] tools/list never returns on main HEAD when launched with --context=claude-code (works on v1.1.2) #1416

@LZong-tw

Description

@LZong-tw

[Bug] tools/list never returns on main HEAD when launched with --context=claude-code (works on v1.1.2)

Summary

When launching Serena from main (current HEAD) via the documented uvx --from git+... recipe, the MCP server accepts initialize but never returns a response to tools/list, leaving Claude Code with no Serena tools registered. The same recipe pinned to v1.1.2 works correctly. Bisect points to the main commits landed on Apr 24 2026.

Environment

  • OS: Windows 11 Pro 26200 (also reported anecdotally on macOS via Codex)
  • Python: 3.13.3 (via uvx 0.11.2, 2026-03-26 build)
  • MCP client: Claude Code 2.1.118 (stdio)
  • Serena launch command (verbatim from ~/.claude.json):
    uvx --from git+https://github.com/oraios/serena \
        serena start-mcp-server --context=claude-code --project-from-cwd
    

Repro

Run a minimal stdio MCP handshake against Serena from any registered project root:

// node test.js
const { spawn } = require('node:child_process');
const proc = spawn('uvx', [
  '--from', 'git+https://github.com/oraios/serena',
  'serena', 'start-mcp-server', '--context=claude-code', '--project-from-cwd'
], { cwd: '/path/to/registered/project', stdio: ['pipe','pipe','pipe'], shell: true });

let buf = '';
proc.stdout.on('data', d => {
  buf += d;
  const lines = buf.split('\n'); buf = lines.pop();
  for (const line of lines) {
    if (!line.includes('"jsonrpc"')) continue;
    const msg = JSON.parse(line);
    if (msg.id === 1) {
      console.log('init OK at', Date.now());
      proc.stdin.write(JSON.stringify({jsonrpc:'2.0',id:2,method:'tools/list'})+'\n');
    } else if (msg.id === 2) {
      console.log('tools/list OK', msg.result.tools.length, 'tools');
      proc.kill();
    }
  }
});
proc.stderr.on('data', d => process.stderr.write(d));

setTimeout(() => proc.stdin.write(JSON.stringify({
  jsonrpc:'2.0', id:1, method:'initialize',
  params:{protocolVersion:'2024-11-05', capabilities:{}, clientInfo:{name:'t',version:'1'}}
})+'\n'), 500);
setTimeout(() => { console.log('TIMEOUT'); proc.kill(); }, 60_000);

Result on main (HEAD as of 2026-04-25, serverInfo reports version: 1.27.0)

[+5s]  initialize response received
[+5s]  tools/list sent
[+60s] TIMEOUT — no response

Last stderr line is the language-server "init complete in ~3.9 s" log. The mcp lib logs Processing request of type ListToolsRequest and then nothing further about that request — the response is never sent.

Result on @v1.1.2 (serverInfo reports version: 1.26.0)

[+6.7s] initialize response received
[+6.7s] tools/list sent
[+6.7s] tools/list response: 18 tools  ← ~9 ms after request

Same project, same OS, same uvx, same --context=claude-code.

Impact on Claude Code

Because Claude Code's MCP client waits for tools/list before registering the server's tools, no mcp__serena__* tools are exposed for the rest of the session. Audit of recent local sessions (cwd in registered projects, serena configured at user scope) shows tools registered correctly until ~Apr 21 and then absent across every subsequent session — matching the timing of the Apr 24 main commits.

cleanup-serena-style hooks don't help, since the server is running fine — it just never answers tools/list.

Suspected commits (Apr 24 on main)

Commits landed Apr 24 that touch the surface most relevant to this symptom:

The "lazy system prompt" change in particular looks suspicious — if tools/list now triggers a code path that awaits something which itself is waiting on the request to complete, the handler would deadlock the way we see here. Happy to bisect further if helpful.

Workaround

Pin to the last release tag in the user's MCP config:

"serena": {
  "type": "stdio",
  "command": "uvx",
  "args": [
    "--from", "git+https://github.com/oraios/serena@v1.1.2",
    "serena", "start-mcp-server",
    "--context=claude-code",
    "--project-from-cwd"
  ]
}

Restart the client. tools/list returns in <10 ms and tools register normally.

What would help

  • Confirm whether the lazy system-prompt change interacts with tools/list on the claude-code context specifically (could be context-gated logic)
  • A regression test that drives initializetools/list over stdio against each context (claude-code, codex, default) so this can't silently break again

Happy to provide more logs or run a bisect against the Apr 24 commits if you'd like.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions