Skip to content

fix(mcp): complete the initialize handshake instead of exiting on stdio (#211) - #217

Draft
Frankie-Xu wants to merge 1 commit into
trailhq:mainfrom
Frankie-Xu:fix/211-mcp-initialize-handshake
Draft

fix(mcp): complete the initialize handshake instead of exiting on stdio (#211)#217
Frankie-Xu wants to merge 1 commit into
trailhq:mainfrom
Frankie-Xu:fix/211-mcp-initialize-handshake

Conversation

@Frankie-Xu

@Frankie-Xu Frankie-Xu commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #211
Closes #212

Follow-up (still not this PR)

Pagination, resources, prompts, result-envelope fields (resultType, cache hints on list results), and subscriptions/listen were not verified in those issues because the handshake never completed. They are out of scope here.

After this lands they may start running in @hasmcp/mcp-spec-test and fail for real capability gaps rather than “server exited”. Local run of 2026-07-28 against this branch already shows that: handshake / discover / SDK interop pass; 4 remaining failures are envelope fields on tools/list and tools/call (resultType, cacheScope, ttlMs, _meta serverInfo).

Test plan

  • npm run build && npm test — 923/923
  • Fake-stdin unit tests: version-less initialize, unsupported version refused, tools/list, server/discover without a session
  • Spawned graft mcp <tmpdir>: initialize → initialized → tools/list → tools/call; process still running on a quiet stdin pipe
  • @hasmcp/mcp-spec-test@0.1.1 -c "node dist/cli.js mcp <abs>" --spec-version 2025-11-25: 14 passed, 0 failed (handshake, version negotiation, official SDK initialize + tools/list)
  • same suite --spec-version 2026-07-28: handshake, server/discover, and official SDK interop pass; 4 envelope failures left as follow-up

Made with Cursor

…io (trailhq#211)

Closes trailhq#211 trailhq#212 — same root cause on both spec revisions: the stdio
server loaded native grammars at boot (or returned before stdin was
armed), so official SDK clients saw Connection closed / timeout instead
of an initialize result.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

🌱 graft blast radius

3 areas changed → 2 areas can be affected. 7 dependent symbols, depth 2.
Tests: Source Parsing has tests the diff did not touch; 1 area updated its tests.

flowchart TB
  A0(("Workspace Graph<br/>5 symbols"))
  A1(("Engine Core<br/>2 symbols"))
  classDef reached fill:#D9EDF3,stroke:#3AA7C9,stroke-width:1.5px,color:#0E313C;
  class A0,A1 reached;
Loading
Can be affected Symbols Nearest hop Reached from
Workspace Graph 5 src/graph/build.ts:L147-L403 buildGraph — calls, depth 1 Source Parsing
Engine Core 2 src/engine.ts:L86-L95 graph — calls, depth 2 Source Parsing
All 7 dependent symbols, grouped by area

Workspace Graph — 5 symbols in 5 files

  • src/graph/build.ts:L147-L403 — buildGraph (calls, depth 1)
    257: ? extractFile(rel, source, lang)
  • src/graph/check.ts:L56-L133 — checkGraph (calls, depth 1)
    99: ? extractFile(relPosix(root, file), source, lang)
  • src/graph/container.ts:L151-L208 — extractContainer (calls, depth 1)
    171: inner = extractFile(rel, script, lang.inner);
  • src/graph/refresh.ts:L150-L223 — ensureFreshGraph (calls, depth 2)
  • src/graph/workspace.ts:L414-L439 — federateCheck (calls, depth 2)

Engine Core — 2 symbols in 1 file

  • src/engine.ts:L86-L95 — graph (calls, depth 2)
  • src/engine.ts:L77-L79 — checkGraph (calls, depth 2)
Test signal per changed area — 1 ✓ · 1 ⚠ · 1 –

Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.

  • Source Parsing — 1 of 4 reached · 7 test files reach it, none changed here
    • not reached: grammarOf, treeSitter, parseSource
  • MCP Protocol — 2 of 11 reached · 1 test file changed here: test/mcp-server.test.ts
    • not reached: send, reply, discoverResult, initializeResult, metaProtocolVersion, replyError, finish, stdoutWrite, …1 more
  • CLI Interface — no function, method or class changed here
35 test suites also reference this code

41 symbols, kept out of the diagram and the table so they cannot crowd out the areas a reviewer has to look at.

  • test/ask-index.test.ts
  • test/ask.test.ts
  • test/container-extract.test.ts
  • test/covers.test.ts
  • test/generic-extract.test.ts
  • test/graph-bindings.test.ts
  • test/graph-extract-dedup.test.ts
  • test/graph-follow-submodules.test.ts
  • test/graph-go.test.ts
  • test/graph-incremental.test.ts
  • test/graph-invariants.test.ts
  • test/graph-java.test.ts
  • test/graph-languages.test.ts
  • test/graph-load.test.ts
  • test/graph-php.test.ts
  • test/graph-posix-paths.test.ts
  • test/graph-python.test.ts
  • test/graph-r-classes.test.ts
  • test/graph-r-phase3.test.ts
  • test/graph-r-phase4.test.ts
  • …15 more

graft blast · origin/main...HEAD · depth 2 · 6 changed files

Open the interactive graph → — click an area to see its dependent symbols at file:line.

github-actions Bot added a commit that referenced this pull request Aug 25, 2026
github-actions Bot added a commit that referenced this pull request Aug 25, 2026
@Frankie-Xu
Frankie-Xu marked this pull request as draft August 26, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant