Repository navigation
feat: port to the mcp 2.x SDK; grammar prefetch retries; pilot grammar cache; serverInfo version (#124, #128, #127, #131) - #132
Merged
Conversation
…rsion (#124, #128) - Require mcp>=2.2,<3 (co-installs with pmcp 3.x) and jsonschema; refresh uv.lock. - Register list_tools/call_tool through the 2.x constructor handlers. A tools/call adapter keeps the v1 decorator contract: jsonschema input validation and exceptions as isError results. - mcp 2.x removed the experimental Tasks runtime. A repo-owned TaskRuntime keeps task-augmented reindex/write_summaries, the tasks capability and tasks/get|result|list|cancel on handshake-era connections. - serverInfo.version is mcp_server.__version__, not the mcp library version. - outputSchemas carry the top-level "type": "object" the MCP schema requires and the 2.x SDK enforces. - Port camelCase attribute access, MCPError, task timestamps, sampling deprecation, the installed smoke and the PMCP pilot client to the 2.x API. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…131) `mcp-index grammars prefetch` made one attempt at the language pack's GitHub release assets, so a transient 504 failed CI, image builds and release automation. Prefetch now retries HTTP 5xx and 429, connection resets and timeouts with equal-jitter exponential backoff (5 attempts, 4s doubling to a 60s cap, within a 120s budget). 4xx such as 404, checksum mismatches and unrecognized failures fail on the first attempt. Retries and the final error name only the URL (no credentials, query or fragment) and the status; the pack's raw message, which carries the full URL, is not logged or chained. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… grammar cache (#127) The pilot gave its fixture a fresh XDG_CACHE_HOME and no grammar location, so network-denied sandbox workers could not load grammars and offline mode's reindex failed with grammar_unavailable. - prepare resolves an explicit cache (--grammar-cache, else the caller's TREE_SITTER_LANGUAGE_PACK_CACHE_DIR, else <root>/grammar-cache, mode 0700), prefetches into it with the installed wheel's CLI, and binds it in the manifest. - Every mode re-checks the cache offline before running (grammar_cache_unavailable otherwise). - Fixture, server, registration and lifecycle environments get TREE_SITTER_LANGUAGE_PACK_CACHE_DIR, which sandbox workers keep, plus the offline manifest URL, so no pilot process downloads a grammar after prepare. - Contract tests, including an end-to-end STDIO reindex with downloads refused: passes from the prefetched cache, fails closed from a cold one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#124, #128, #127, #131) - CHANGELOG [Unreleased]: the port, the serverInfo version, prefetch retries, the pilot grammar cache, and upgrade notes, including dropping any mcp<2 pin installed alongside index-it-mcp. - SUPPORT_MATRIX: the mcp>=2.2,<3 requirement, PMCP 3.x co-install, and the protocol revisions each verified client negotiates. - README, GETTING_STARTED, MCP_CONFIGURATION: source and main wheels need mcp>=2.2,<3 and co-install with PMCP 3.x. - A wire test pins 2026-07-28 parity with the handshake era: same tools and results, no Tasks surface. - black/isort on touched files; snake_case ToolAnnotations and typed helpers, so the mypy ratchet adds nothing beyond main's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This was referenced Nov 9, 2026
… tasks/result, nits) S1: cap mcp at >=2.2,<2.4 (still locked at 2.3.0; co-installs with pmcp 3.0.3 and phase-loop-runtime 0.7.30). The Tasks runtime depends on Server.middleware, which mcp marks provisional. TaskRuntime.install() now checks the middleware contract (a list of (ctx, call_next) middleware) and refuses to start with an actionable message if it is missing; the guarded import does the same. The cap, and re-testing each mcp minor before widening it, are noted in CHANGELOG and SUPPORT_MATRIX. S2: concurrent tasks/result requests for one task are all answered. The registry keeps one shared event per task that notify_update sets and drops, so every waiter wakes. Deleting, expiring or evicting a task wakes its waiters, which then get -32602. N1: task TTLs are clamped to 1 h (default 1 h; the effective ttl is returned). Expiry starts when a task finishes. At most 256 tasks are kept: the oldest finished tasks are evicted first, and a new task is refused only while 256 are running. N2: skip MCP sampling on 2026-07-28 sessions, which have no back-channel; log once. N3: answer malformed STDIO lines with JSON-RPC -32700 (id null) or -32600 (echoing a valid id) instead of dropping them; log only size and code. N4: prefetch also retries refused connections, DNS lookup failures and HTTP 408; the docstring says the budget bounds the backoff, not one attempt. N5: the runtime docstring says Tasks are served on every handshake revision, as v1 did, and that the spec defines them only from 2025-11-25. N6: the CHANGELOG's error-code line now notes the -32601 exception. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ViperJuice
added a commit
that referenced
this pull request
Nov 9, 2026
test_fixture_server_and_workers_get_the_prefetched_cache_with_downloads_denied (added in #132) calls create_fixture, which imports the sibling module v13_pilot_estimate the way the pilot does when run as a script. It passed only when an earlier test on the same xdist worker had put scripts/ on sys.path. The ai full suite on 93b7e9f hit the other ordering (ModuleNotFoundError), and running the test alone reproduces it. Prepend scripts/ with monkeypatch, as the file's other create_fixture test already does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ViperJuice
added a commit
that referenced
this pull request
Nov 9, 2026
…acity error (#132 re-check nits) (#135) * fix(mcp): task retention floor, drop malformed responses, clearer capacity error (#132 re-check nits) R1: task TTLs have a one-minute floor (MIN_TASK_TTL_MS), so `ttl: 0` can no longer expire a finished task before a woken tasks/result reads it. Expiry and eviction never remove a finished task that still has a tasks/result waiter (counted in wait_for_update, so a woken waiter that has not yet resumed is covered) or that finished within the floor. Eviction takes the oldest evictable finished task. With every slot running, awaited or just finished, a new task is refused instead. R2: the POSIX STDIO pre-check drops a malformed JSON-RPC response (`result` or `error` with no `method`) with a debug log. It is not answered, so its id, which belongs to the server's own request-id space, is never echoed. R3: the CHANGELOG says the malformed-line replies apply to the POSIX STDIO transport; Windows uses the SDK's reader, which still drops them silently. R4: a full registry raises TaskCapacityError, which TaskRuntime.run_task re-raises as MCPError. The client therefore gets "Too many tasks (N running or awaiting retrieval); retry after one finishes" instead of "details": "ValueError". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(pilot): do not depend on test order for the pilot's helper import test_fixture_server_and_workers_get_the_prefetched_cache_with_downloads_denied (added in #132) calls create_fixture, which imports the sibling module v13_pilot_estimate the way the pilot does when run as a script. It passed only when an earlier test on the same xdist worker had put scripts/ on sys.path. The ai full suite on 93b7e9f hit the other ordering (ModuleNotFoundError), and running the test alone reproduces it. Prepend scripts/ with monkeypatch, as the file's other create_fixture test already does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Merged
ViperJuice
added a commit
that referenced
this pull request
Nov 10, 2026
Prepare index-it-mcp 1.6.0: the mcp 2.x port (#124 with #128, #131 and #127 in #132, re-check fixes in #135), so index-it-mcp co-installs with PMCP 3.x, and the watcher sweep, incremental sync and generation-retention fixes (#114 and #111 in #129, follow-ups in #130). - Bump to 1.6.0 in pyproject, __version__, the project's uv.lock entry, the Release Automation default, both Docker installers, the release docs and the release-gate tests. - Turn [Unreleased] into [1.6.0] - 2026-11-09 (Changed / Fixed / Upgrade notes / Known follow-ups). Upgrade notes: mcp>=2.2,<2.4 is required, so drop any mcp<2 pin; PMCP 3.x co-install; Claude Code negotiates 2026-07-28 without Tasks; the cap widens per re-tested mcp minor; retention is automatic but never prunes pre-upgrade generations. Follow-ups #133, #134, #121, #117. - Docs: 1.6.0 is the prepared candidate, 1.5.1 is published with partial delivered acceptance, and 1.3.0 through 1.5.0 are yanked on PyPI. - The raw JSON-RPC initialize probe now requires serverInfo.version to equal the installed index-it-mcp version (#128), so release smoke guards it. Co-authored-by: Claude Opus 5.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.
Summary
Code changes for the next minor release (1.6.0). The version is not bumped and nothing is released, deployed or restarted.
mcp2.x SDK. The requirement ismcp>=2.2,<2.4(locked at 2.3.0; capped per review S1, see below), plusjsonschemaas a direct dependency.uv lock --checkpasses.initializereportsserverInfo.version=mcp_server.__version__, not themcplibrary version.mcp-index grammars prefetchretries transient download failures with bounded, jittered backoff. URLs are logged with their query strings stripped.prepareand passes it, with downloads refused, to every fixture, server and sandbox worker.Fixes #124
Fixes #128
Fixes #127
Fixes #131
mcp 2.0–2.3 API changes that applied
Sources:
docs/migration.mdatv2.3.0and the v2.0.0–v2.3.0 release notes.McpError→MCPErrorstdio_runnerre-raisesMCPError;MCPError(code, message)constructor@server.list_tools(),@server.call_tool()) replaced byServer(..., on_list_tools=, on_call_tool=)with(ctx, params)handlers that return full result types_build_server(),_on_list_tools,_make_call_tool_handler()request_ctxcontextvar andserver.request_contextremovedctx.sessionand is passed tocall_tool(..., session=, task_request=)call_tooldecorator's jsonschema input validation was removedinputSchemaand returns the identicalInput validation error: ...resultisErrorresults (they become JSON-RPC errors)isErrorresultserver.experimental.enable_tasks,ServerTaskContext,mcp.shared.experimental.*); only theTask*wire types remainmcp_server/cli/task_runtime.py:TaskRuntime(background task group,tasks/get/tasks/result/tasks/list/tasks/cancelviaadd_request_handler),TaskContext,TaskRequest.MCPTaskRegistryno longer subclasses the removedTaskStoreand inlinescreate_task_state/is_terminal.tools/callsurface accepts onlyCallToolResultCreateTaskResultfor task-augmented calls on handshake-era connections. The customtasks/resultpayload is passed through the publicmcp.types.methods.serialize_server_resultso no 2026-era fields leak.Tool.outputSchemamust betype: object_tool()adds top-level"type": "object"; everyoneOfbranch was already an objectis_error,structured_content,input_schema,task_id,client_info,read_only_hint, ...)Task.created_at/last_updated_attypedstr(weredatetime)wire_time()serializes them byte-identically to v1's pydantic datetime JSONtasks/resultreturns a wire dict instead ofGetTaskPayloadResult.model_validate(...), which would dropcontentandstructuredContent""(1.x reported the mcp version, which was #128)Server(name, version=__version__)instructions=on the constructorServer(_SERVER_NAME, version=..., instructions=...)initializeno longer sendsexperimental: {}create_initialization_options(experimental_capabilities={})keeps v1's capability objectServerSession.create_message) deprecated (SEP-2577,MCPDeprecationWarning)summarization.py)streamablehttp_clientremoved;streamable_http_client(url, http_client=httpx2.AsyncClient)yields a 2-tuplegateway(), keeping v1'sTimeout(30, read=300)andtrust_env=Falsefloatseconds, nottimedeltaClientRequestunions are notRootModels; the 2.xClientSessionhas no Tasks clienthttpx/httpx-sse→httpx2;pydantic-settingsdropped from mcp's depsuv.lockrefreshed; the repo imports neitherhttpx_ssenorpydantic_settings(httpxremains a direct project dependency)stdio_server()signature unchanged (moves the wire to private fds)Not ported:
scripts/patch_mcp_server.pyand the twoscripts/cli/servers it generates (mcp_server_cli_patched.py,mcp_server_bm25.py). They are unreferenced legacy generators, andmcp_server_cli_patched.pyalready imports a module that does not exist (fix_mcp_bm25_integration).Behavior-equivalence evidence
Raw STDIO wire diff, v1 vs v2. One request script (27 steps) ran against
origin/main(mcp 1.27.0) and this branch (mcp 2.3.0) on the production-matrix fixture. It covers initialize, ping, tools/list, every tool, ready / not-found / fail-closedindex_unavailable/path_outside_allowed_rootssearches, invalid arguments, unknown tool, task mode on a non-task tool, a whole-repo task refusal (task_scope_unsupported), a file-scoped reindex task withtasks/result,tasks/list, thentasks/getandtasks/cancelon unknown and terminal tasks (a live cancel is covered by the in-process lifecycle test),write_summaries,summarize_sample, unservedresources/list/prompts/list, and an unknown method. After normalizing paths, UUIDs, timestamps and SHAs, the only differences are:serverInfo.version:1.27.0→1.5.1(STDIO initialize reports the mcp library version instead of the package version #128, intended).outputSchemas gains top-level"type": "object"(required by the spec and enforced by the 2.x SDK; no change to what validates).tasks/resultcontent blocks no longer carry"_meta": null, "annotations": null, a v1 serialization artifact. Every value is otherwise identical.-32601with the method name indata(v1:-32601withoutdatafor unserved spec methods, and-32602 "Invalid request parameters"for unknown methods). This is SDK protocol behaviour (migration guide: "Unknown request methods now return -32601").Every tool result,
isErrorflag,structuredContent, readiness payload, error code and task status is otherwise byte-identical.In-process wire tests (
tests/test_mcp2_stdio_wire.py, 15 tests) pin: the v1 capability set,serverInfo.version, negotiation of each handshake revision, protocol-validtools/listwithexecutiononly onreindex/write_summaries, the exact v1 input-validation and exception results, task-mode refusal, the full task lifecycle (create,_metaimmediate response, list, cancel, result with related-task_meta, terminal-cancel code 0, unknown-task-32602), failed work →failed, and 2026-07-28 parity.Protocol negotiation
Run against the wheel installed from this branch (
index-it-mcp1.5.1, mcp 2.3.0). Each client also completed reindex and search on a registered repo, except Claude Code, whose check covers only discover andtools/list.ClientSession.initialize()initializeClient(mode="auto")server/discoverexecution), reindex OK, search hitClientSessioninitializeinitialize(clientInfomcp-gateway 1.0.0)complete, catalog lists all 8 tools,gateway.invokereindex / search_code / get_status OKclaude mcp list, isolated HOME and config, no LLM call)server/discovertools/listservedBehaviour change for Claude Code: against
origin/main(v1 SDK), Claude Code'sserver/discoverprobe failed and it fell back toinitializeat 2025-11-25. With this port it stays on 2026-07-28. On that revision the tools and results are the same (test_modern_revision_serves_the_same_tools_and_results); results add the spec'sresultType: "complete"and aserverInfo_metastamp (version 1.5.1),tools/listomitsexecution, and the Tasks surface is absent (the revision has no Tasks). Claude Code never used tasks. This is recorded in CHANGELOG and SUPPORT_MATRIX.Co-install proof
uv build→index_it_mcp-1.5.1-py3-none-any.whl(originallyRequires-Dist: mcp<3,>=2.2; re-proven after review withmcp<2.4,>=2.2, see Review fixes),jsonschema>=4.20.0. Each case is a fresh Python 3.12.14 venv withuv pip install --no-config:uv pip checkmcpcode-index-mcp-fast-search 1.5.1, 8 tools, get_status OKpmcp(latest → pmcp 3.0.3)phase-loop-runtime==0.7.30scripts/release_smoke.py --wheel --stdio --unconstrainedalso passed on the final head: the locked wheel (source contract, schema, Python client, two STDIO sessions, six lifecycle cases) and the unconstrained wheel (resolvedmcp2.3.0, raw initialize with 8 tools, two STDIO sessions).#131: prefetch retries
The language pack raises
RuntimeError("Download error: Failed to fetch manifest from <url>: http status: 504"), and resets readio: Connection reset by peer; both shapes were confirmed against a local HTTP server. Prefetch now behaves as follows:ChecksumMismatchErroror message), anything unrecognized.GrammarPrefetchErrorname only the URL, without credentials, query or fragment, and the status. The pack's raw text, which includes the full query string, is not logged or chained.Dockerfile.productionalready callmcp-index grammars prefetch, so all of them retry.tests/test_grammar_prefetch_retry.py(16 tests, fake downloader and fake clock): 504 then success passes after one sleep; persistent 504 fails after exactly 5 attempts with sleeps[4, 8, 16, 32]≤ 120 s; 404 fails immediately with no sleep; 403, checksum and other failures are not retried; 429, 500, 502, reset and timeout are retried; the deadline stops retries; URL sanitization; and the CLI prints a sanitized error.#127: pilot grammar cache
prepare: resolves--grammar-cache, else the caller'sTREE_SITTER_LANGUAGE_PACK_CACHE_DIR, else<root>/grammar-cache(0700). It then prefetches with the installed wheel's own CLI and recordsgrammar_cachein the manifest.validate_manifestrefuses a missing cache, and withexecute=Truerunsmcp-index grammars checkoffline (grammar_cache_unavailable)..mcp.jsonserver env, registration commands and the lifecycle smokes getTREE_SITTER_LANGUAGE_PACK_CACHE_DIR(kept bycaps_applyfor sandbox workers) andTREE_SITTER_LANGUAGE_PACK_MANIFEST_URL=sandbox-offline://network-denied, so no pilot process can download a grammar afterprepare.tests/test_v13_pmcp_pilot.py, 168 passing:preparewith the default, argument and environment cache sources;Tests
nice, headroom-checked), all passing. Highlights:test_mcp2_stdio_wire.py(new, 15),test_grammar_prefetch_retry.py(new, 16),test_v13_pmcp_pilot.py(168),smoke/test_mcpbase_stdio_smoke.py(now also assertsserverInfo.version == __version__),smoke/test_mcpeval_sdk_surface.py(SDK metadata, structured and fail-closed surfaces, plus the task lifecycle over raw JSON-RPC), themcptasks/mcpstruct/mcpmetadoc contracts, release metadata and the release smoke contract, and 66 doc-contract files.origin/main: one pre-existing F401 in the pilot.origin/main(all in files this PR does not touch, or pre-existing ingrammar_cache.py).Full suite on host
ai, before the review fixes: passed at head8941315: 4362 passed, 127 skipped, exit 0 in 14m22s (coverage 56.53%, above the 35% floor). Run assystemd-run --userunitci-code-index-124-8941315(MemoryMax=16G, CPUQuota=400%) under the shared Code-Index-MCP project lock, with an isolated HOME outside~/tmp,~/.local/binonPATH, a prefetched privateTREE_SITTER_LANGUAGE_PACK_CACHE_DIR, and CI'sMCP_REQUIRE_GRAMMARS=1andMCP_SKIP_PLUGIN_PREINDEX=true. Fresh clone,uv sync --locked --extra dev --extra semantic --python 3.12(mcp 2.3.0),pytest tests/ -n 2 --timeout=300, logged to a durable file that was polled, not streamed.Review fixes
The independent review graded this PR MERGE-READY, with 0 blocking findings, 2 should-fix and 6 nits. All eight are applied in
b63bbc6, a new commit on top of the reviewed head; no history was rewritten.Server.middleware, marked provisional ("may change in a 2.x minor release"), andmcp>=2.2,<3would admit an untested 2.4mcp>=2.2,<2.4(lock unchanged at 2.3.0;uv lock --checkpasses).TaskRuntime.install()callsensure_middleware_contract(), which requiresServer.middlewareto be a list andServerMiddleware.__call__to take(ctx, call_next), and refuses to start with an actionable message otherwise; the guardedmcp.server.contextimport does the same. CHANGELOG and SUPPORT_MATRIX record the cap, with the follow-up to re-test and widen it per mcp minor.test_startup_refuses_an_mcp_without_the_middleware_contract. Capped wheel (Requires-Dist: mcp<2.4,>=2.2), each in a fresh Python 3.12 venv: alone → mcp 2.3.0; + pmcp → pmcp 3.0.3, mcp 2.3.0; +phase-loop-runtime==0.7.30→ mcp 2.3.0. All three have a cleanuv pip checkand answer initialize, tools/list and get_status. Floor check: wheel +mcp==2.2.0passes the guard and serves too.tasks/resultorphaned the first, which never got a reply (pre-existing in v1)anyio.Eventper task.notify_updatesets it and drops it, so every waiter wakes and re-checks. Deleting, expiring and evicting a task set the event, so parked waiters wake and get-32602.test_concurrent_task_results_for_one_task_are_all_answered(the reviewer's repro, now with 3 waiters; all answered).test_running_tasks_never_expire_and_deleting_wakes_waiters. The reviewer's disconnect repro is ported astest_client_disconnect_mid_task_finishes_the_task_without_crashing.ttlis clamped to 1 h, and defaults to 1 h when absent; the effective value is returned, as the spec allows. Expiry starts at the terminal transition, so a long reindex is never purged mid-run. At most 256 tasks are kept: the oldest terminal ones are evicted first, and a new task is refused only while 256 are running.test_task_ttl_is_clamped_and_defaulted(×3),test_task_retention_evicts_finished_tasks_and_refuses_when_all_run_has_sampling_capabilityreturns False when the session's protocol version is not a handshake version, and logs once per writertest_sampling_is_skipped_on_protocol_revisions_without_back_channel(×2)jsonrpc_message_adapter.validate_jsoncheck. Invalid JSON gets-32700(idnull); JSON that is not JSON-RPC gets-32600, echoing a string or integerid(JSON-RPC 2.0 §5.1). Blank lines are skipped. A warning logs only the size and the code.test_malformed_stdio_lines_get_json_rpc_errors_and_valid_lines_pass. End to end through the real server's pipes:not json→-32700,{"jsonrpc":"2.0","id":8}→-32600 id 8, then initialize and ping answered. A ping sent right before stdin EOF goes unanswered on both trees, because of the pre-existing EOF shutdown, unchanged here.connection refused,dns error/failed to lookup/temporary failure in name resolution/name or service not known, and HTTP 408. The docstring says the 120 s budget bounds the backoff, not a single attempt..invalidhost were captured locally and both classify as transient; 4 new parametrized cases, 20 tests totalsupports_tasks.Re-verification on dev0. Each affected file ran alone, serially, under
nice, with no xdist, after a load and I/O-pressure check (1-minute load 0.9–3.5):test_mcp2_stdio_wire.pytest_grammar_prefetch_retry.pytest_v13_pmcp_pilot.pytest_mcptasks_reindex.pytest_mcptasks_write_summaries.pydocs/test_mcptasks_protocol_contract.pytest_mcp_server_cli.pytest_mcpauth_stdio_contract.pydocs/test_mcpstruct_call_tool_contract.pysmoke/test_mcpbase_stdio_smoke.pysmoke/test_mcpeval_sdk_surface.pytest_release_metadata.pysmoke/test_release_smoke_contract.pytest_release_notes.pytest_grammar_registry.pytest_stdio_tool_descriptions.pytest_v13_safety.pyblack and isort are clean, and flake8 is clean on every changed file. The mypy ratchet output is identical to
origin/main.Full suite on host
aiat the final headb63bbc6: passed: 4377 passed, 127 skipped, exit 0 in 12m10s (coverage 56.62%). That is 15 more passing tests than at8941315, matching the new review-fix tests. It used the same isolation as the first run: unitci-code-index-124-b63bbc6undersystemd-run --user(MemoryMax=16G, CPUQuota=400%), the shared Code-Index-MCP project lock, a fresh clone, an isolated HOME outside~/tmp,~/.local/binonPATH, a freshly prefetched private grammar cache (47/47),MCP_REQUIRE_GRAMMARS=1,MCP_SKIP_PLUGIN_PREINDEX=true,uv sync --locked --extra dev --extra semantic --python 3.12(mcp 2.3.0), andpytest tests/ -n 2 --timeout=300, logged to a durable file that was polled.Follow-ups / not done here
mcp>=2.2,<2.4only after the Tasks middleware path, the wire tests and the co-installs pass on it (review S1).pmcp 2.7.3(prepare/validate_manifest), but the latest pmcp is 3.0.3, the version this PR co-installs with. Re-running PMCP offline and rehearsal acceptance, against 1.5.1 or this candidate, needs that pin decision and was not run here.🤖 Generated with Claude Code