Add an MCP client for reactome-mcp, harvested from #127 and #137 - #212
Merged
Merged
Conversation
@GovindhKishore's client, process manager and tool wrappers, reworked onto a main that has moved 140 commits since they were written. **The package is `reactome_mcp`, not `mcp`.** The official MCP Python SDK is published on PyPI as `mcp`. There is no such dependency here today, so nothing breaks now -- but it is the obvious library to adopt, and a local package of that name shadows it. The failure would arrive as an import resolving to the wrong thing rather than as an error. **Three protocol bugs fixed.** The original never sent the `initialize` handshake. The server accepts that today -- I checked -- because the SDK is lenient, but the protocol requires it, and depending on leniency means one SDK release breaks every call at once. Doing it properly also removed an arbitrary `sleep(1)` used to decide the server had started: a successful initialize is the readiness check. The original returned the next line on stdout, whatever it was. A notification between request and reply would be read as the answer, and every later call would be one reply out of step -- answering each question with the previous question's answer. Nothing raises. Two tests pin it, and both fail against the original behaviour. A lock now serialises each write/read pair. Two coroutines on one pipe is the same desync by another route. **Shapes are checked, not asserted.** `json.loads` returns Any, and casting it to the hoped-for shape is exactly how reactome-mcp shipped ten formatters that read fields the API never returns. **Five tools, not fifty-three, deliberately.** Every description is spent from the model's context before it answers anything, and a model choosing between 53 similar names chooses worse than one choosing between five. The five cover what the bundle cannot: live search, live pathway lookup, enrichment analysis, and the two metadata questions a snapshot cannot answer. A test pins the number so growing it is a decision. **`./bin/mcp-probe` checks the integration end to end.** Wrong path, missing node, stale build, Content Service down and a rejected handshake all look alike from inside the chatbot, and a question that quietly falls back to retrieval reports none of them. Nothing is wired into the chat graph yet; that is spec 007, and it belongs on the existing intent_classifier rather than in a second one. This is the piece that makes the analysis destination reachable at all. 18 tests, no network. Verified live against reactome-mcp 1.4.0: handshake, 53 tools listed, all five wrappers answering in 0.04-0.39s. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
@GovindhKishore's client, process manager and tool wrappers from #127 and #137, reworked onto a
mainthat has moved 140 commits since they were written. #127 and #142 are closed; #137 stays open until this lands.This is the piece that makes spec 007's analysis destination reachable at all.
The package is
reactome_mcp, notmcpThe official MCP Python SDK is published on PyPI as
mcp. There's no such dependency here today so nothing breaks now — but it's the obvious library to adopt, and a local package of that name shadows it. The failure would arrive as an import resolving to the wrong thing, not as an error.Three protocol bugs fixed
No
initializehandshake. The original went straight totools/call. The server accepts that today — I verified it — because the SDK is lenient. But the protocol requires it, and depending on leniency means one SDK release breaks every call at once. Doing it properly also removed an arbitrarysleep(1)used to decide the server had started: a successful initialize is the readiness check.Replies weren't matched to requests. The original returned the next line on stdout, whatever it was. A notification arriving between request and reply is read as the answer — and every later call is then one reply out of step, answering each question with the previous question's answer. Nothing raises. It just returns the wrong thing, plausibly.
Two tests pin it, and both fail against the original behaviour:
No serialisation. A lock now wraps each write/read pair. Two coroutines on one pipe is the same desync by another route.
Shapes are checked, not asserted
json.loadsreturnsAny, and casting it to the hoped-for shape is exactly how reactome-mcp shipped ten formatters reading fields the API never returns. A non-object result, a non-list tool list and a malformed content block each raise with a message saying what arrived.Five tools, not fifty-three
Deliberate, and a test pins the number so growing it is a decision. Every description is spent from the model's context before it answers anything, and a model choosing between 53 similarly-named tools chooses worse than one choosing between five. The five cover what the bundle can't do: live search, live pathway lookup, enrichment analysis, and the two metadata questions a snapshot can't answer.
One test asserts the analysis tool's description tells the model not to answer a gene list from retrieval — spec 007's edge case, where a retrieved answer looks like an analysis and isn't.
./bin/mcp-probeWrong path, missing node, stale build, Content Service down and a rejected handshake all look alike from inside the chatbot, and a question that quietly falls back to retrieval reports none of them. This separates them and exits non-zero, so it can gate a deployment.
Not wired into the graph
Deliberately. Routing belongs on the existing
intent_classifierrather than in a second one (the reason #142 was closed), and that change deserves its own review — it also has to answer where the subprocess lifecycle lives in a Chainlit app.bin/mcp-probemeans this is usable today rather than dormant.Verification
ruff,ruff formatandmypyclean across all 95 files🤖 Generated with Claude Code