This release includes 4 breaking changes for platform teams planning a safe upgrade.
✓ No known CVEs patched in this version
Affected surfaces
Summary
AI summaryMCP protocol handling switches to official Kotlin SDK with four breaking behavior changes.
Full changelog
Breaking
- MCP protocol handling now uses the official MCP Kotlin SDK instead of a hand-written JSON-RPC/SSE implementation. All 50 tools, their names, input schemas and response payloads are unchanged — the golden
tool-manifest.jsonandresult-shapes.txtsnapshots are byte-identical across the migration. Four client-visible behaviours did change:Accept: application/json, text/event-streamis now required onPOST /index-mcp/streamable-http, per the Streamable HTTP spec.Accept: application/jsonalone returns406 Not Acceptable, and a non-JSONContent-Typereturns415. Every real MCP client (Claude Code, Cursor, the official SDKs) already sends both; only hand-writtencurlneeds updating.- Tool failures are reported as
isError: trueresults instead of JSON-RPC errors. Dumb-mode (-32001), unknown tool (-32601) and disabled tool (-32602) previously came back as protocol errors, which clients surface as hard transport failures. The MCP spec puts tool-execution errors in the result so the model can read and act on them — which is what messages like "callide_index_statusuntil indexing finishes" were written for. The message text is unchanged. initializerequires spec-complete params.capabilitiesis mandatory per the MCP schema and is now validated.serverInfo.descriptionmoved toinstructions. MCP'sImplementationobject has nodescriptionfield;instructionsis the spec's slot for "how to use this server" text, and clients feed it to the model.
initializenegotiates the protocol version with the client across2024-11-05,2025-03-26,2025-06-18and2025-11-25, rather than answering with a fixed version per endpoint. A client asking for2024-11-05still gets2024-11-05.
Added
- Host header validation on all MCP endpoints, alongside the existing Origin check — DNS-rebinding protection. Applies only when the server is bound to loopback, which is where that attack lives: it tricks a browser into reaching a server on the user's own machine through an attacker-controlled name. The port is ignored. A server deliberately bound to
0.0.0.0or a LAN address is reached under whatever name or IP routes to it, so no allow-list is enforced there and such setups keep working exactly as before.
Changed
- Malformed JSON-RPC batches are processed per message rather than rejected wholesale, and a
DELETEon the Streamable HTTP endpoint no longer sends anAllowheader with its405. - The plugin no longer bundles
kotlin-stdlib,kotlinx-coroutines,kotlin-reflector a second copy of Ktor. It previously shipped two major Ktor versions (2.3.12 in use, plus a dead 3.0.2 tree pulled in by an MCP SDK dependency that no source file imported), along with artifacts the IntelliJ Platform forbids plugins from bundling.
Fixed
initializereported a stale server version.serverInfo.versionwas hardcoded to4.10.4while the plugin shipped 4.31.x; the build now stamps the real version into a resource the plugin reads at runtime. (Reading it off the plugin descriptor is not an option — every platform API that exposes it is@ApiStatus.Internalas of 2026.2, which the plugin verifier fails the build on.)ide_structural_search_replace— replace mode failed withMust not change PSI outside command or undo-transparent actionon every invocation that matched at least one element in a project file, applying no edits.Replacer.replaceAllopens its own write action but no command, whichPomModelImplrequires for changes to physical files; replacements are now wrapped in a command, matching the IDE's own Replace All. Search-only mode was unaffected.ide_find_definition,ide_find_references,ide_call_hierarchy,ide_find_implementations,ide_find_super_methods— symbol mode (language+symbol) returnednot_foundformodule#defaultwhen the file usedexport default function f() {}orexport default class C {}, the two most common default-export forms. Default-export detection probed a non-existentisDefaultExport()accessor; it now usesisExportedWithDefault(), which is where the modifier actually lives when there is noES6ExportDefault*wrapper node. Affects both JavaScript and TypeScript.- TypeScript overload resolution — TypeScript functions were never recognised as function-like, because detection matched on the class name containing
JSFunctionandTypeScriptFunctionImpldoes not. As a result, resolving an overloaded exported TypeScript function by symbol returnedambiguous_match, andide_call_hierarchyseeded from an overload signature reported the empty declaration (no callees, under-reported callers) instead of normalising to the implementation. Detection now tests against theJSFunctioninterface.
Breaking Changes
- `Accept: application/json, text/event-stream` is now required on `POST /index-mcp/streamable-http`; missing either media type returns 406 Not Acceptable.
- Tool failures are reported as `isError: true` results instead of JSON‑RPC error codes (e.g., -32001, -32601, -32602).
- `initialize` now mandates spec‑complete parameters; the `capabilities` field is mandatory and validated.
- `serverInfo.description` moved to `instructions`; no `description` field exists in the MCP spec.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About hechtcarmel/jetbrains-index-mcp-plugin
A JetBrains IDE plugin that exposes an MCP server, enabling AI coding assistants to leverage the IDE's indexing and refactoring capabilities (rename, safe delete, find references, call hierarchy, type hierarchy, diagnostics and more).
Related context
Beta — feedback welcome: [email protected]