跪拜 Guibai
← Back to the summary

ESQueryStudio Unifies Elasticsearch Operations: Six Query Modes, MCP for AI Clients, and a Spring Boot / Chrome Dual Transport

Building an Elasticsearch Query Workbench for Spring Boot Teams: Six Modes, Three MCP Integration Surfaces, and Direct Browser Connection

An open-source Elasticsearch query and operations console. The same Vue source code can be embedded in a Spring Boot application as a starter, or packaged as a Chrome MV3 extension that connects directly to ES. Online demo: https://dengmeiluan.github.io/esquerystudio/

MCP support has been added recently: 19 tools across three integration surfaces, so Claude Desktop, Cursor, and in-page agents can query ES directly.

Why build another ES console

Most Elasticsearch consoles split "querying" into disconnected tool pages: DSL builder on one page, SQL on another, Explain on a third. After building a condition tree you have to hand-copy JSON; autocomplete only understands keywords, not whether a field is text or keyword, not the analyzer or cluster version; score problems are a guessing game, and slow queries require digging through logs.

For Spring Boot teams there is an extra layer of friction: to get a query console you have to deploy a whole Kibana instance, and its login state, menus, permissions, and audit trail cannot be wired back into the host application.

ESQueryStudio targets this whole chain: it pulls "how to write, how to run, why it matched, why it is slow" into one continuous query context, and the console can be delivered as part of a Spring Boot application.

Six modes, sharing one context

The console is not six tools that jump between pages, but the same query context under different views:

Switching modes, paginating, or refreshing never clears a query you are halfway through writing; history, favorites, drafts, and shared deep links all use the same context.

A semantic layer that actually understands ES

Autocomplete and lint should not just recognize keywords. ESQueryStudio's semantic layer reads live information from the current index:

All of this feeds autocomplete, value enumeration, pre-execution checks, and semantic lint. For example: sorting directly on a text field will warn you to use .keyword; fields that don't exist, non-sortable types, mismatched date formats, and aggregation/sort conflicts all get actionable fixes before execution.

After you edit the condition tree, JSON updates immediately; after you edit JSON, the tree rebuilds semantically. One side silently going stale while the other is edited never happens.

Relevance Lab: from "why matched" to "why slow"

The query workbench and the relevance lab share the same query context:

One Vue codebase, two delivery forms

This is the architecture choice the project most wants to share: the console has exactly one set of Vue 3 sources, and only the bottom transport layer differs between server mode and browser mode.

ui/ (Vue 3, 52 pages)
  ├─ server mode  → /internal/es/index → Spring Boot console
  └─ browser mode → browserApi.ts      → Elasticsearch REST directly

Server mode: Spring Boot provides the /internal/es/index adapter layer; the console ships with the application, sharing the host's login state, routes, menus, and page-level permissions. Delivery forms include a standalone jar, an embedded console module, host SPI, and a rebuild-only engine.

Browser mode: the browser build of the same source runs inside a Chrome MV3 extension, connecting directly to Elasticsearch without a backend. The first connection asks for the ES address and credentials, and supports multiple local connection profiles with top-bar switching; monitoring, audit, rebuild/migration jobs all stay in local IndexedDB / localStorage.

The most important thing here is not "moving the UI into a plugin", but that capability coverage must be bounded and honest:

To prevent "implemented only in server mode, forgot pure frontend" from happening again, the repo adds scripts/check-browser-parity.mjs: it scans api.ts, backend Controller mappings, and page contract prefixes at the same time, and a new endpoint without a browser implementation will fail CI; the handful of endpoints that truly cannot be implemented must register a reason and show the real boundary in the UI.

MCP: three integration surfaces so AI can use ESQueryStudio directly

ESQueryStudio is not just a console for humans; it can also be called directly by AI clients as an MCP Server. Three surfaces share the same tool contract, avoiding "one set for server, another for frontend" capability drift:

Mode Connection Suitable for Boundaries
Server mode POST /mcp (JSON-RPC 2.0) + optional stdio bridge Claude Desktop, Cursor, any MCP client Requires esquerystudio.mcp.enabled; supports service-level Bearer token or per-login/per-role signed API keys
Pure frontend mode window.ESQueryStudioMCP In-page AI / Agent, automation inside console plugins Browser tabs cannot listen on TCP; external-process clients go through server or local Node
Local Node mode mcp/esquerystudio-local-mcp.mjs (stdio) Local Claude Desktop / Cursor / Agent, no Spring Boot, no browser Node 18+ connects directly to ES; multiple connection profiles stay local; write tools default off, need --allow-write

All three modes share 19 tools: connection / index / cluster health, mapping / settings / aliases / templates / nodes / tasks, DSL query / count / ES-SQL, explain / index stats, document CRUD, raw REST passthrough. Read-only by default; write tools must be explicitly issued with write permission by an ADMIN.

When given to AI, the most valuable thing is not "being able to send a DSL", but handing over the query context and governance together:

Shortest configuration for Claude Desktop / Cursor:

{
  "mcpServers": {
    "esquerystudio": {
      "command": "node",
      "args": ["/path/to/esquerystudio/mcp/esquerystudio-mcp-stdio.mjs"],
      "env": {
        "ESQ_MCP_URL": "http://localhost:5601/mcp",
        "ESQ_MCP_TOKEN": "esq_mcp_xxxxxxxx.yyyyyyyy"
      }
    }
  }
}

Keys are not "issue a permanent token": plaintext appears only once in the creation response, storage keeps only SHA-256; supports per-minute / per-day / per-month quotas, connection-level read/write, tool whitelisting, rotation, and revocation. The server's Dev Tools → MCP panel can issue keys and view usage in real time.

MCP key management: set read and write permissions per connection

In one sentence: before it was "a human opens a console to query ES"; now "humans, in-page agents, Claude/Cursor can all query ES with the same toolset, and permissions and quotas remain the same set".

Engineering and quality

A few real console screenshots

Query workbench: condition tree, raw DSL, results, and histogram on the same screen.

Query workbench

Score anatomy: BM25 factor tree for each matched document.

Score anatomy

Chrome extension: same 52-page Vue console runs inside the extension and connects directly to ES.

Chrome extension

5-minute experience

Standalone deployment:

java -jar esquerystudio-server-1.0.0.jar
# open http://localhost:5601/esquerystudio.html

Embedded in Spring Boot:

<dependency>
  <groupId>io.github.dengmeiluan</groupId>
  <artifactId>esquerystudio-console</artifactId>
  <version>1.0.0</version>
</dependency>

The ES client stack is provided by the host as a provided contract; at startup, actual type signatures are compared, and mismatches reject startup directly with a repair path.

Who it's for

Finally

The project is open source under Apache-2.0, currently in initial-version rolling updates. If you are doing Elasticsearch querying, relevance tuning, or Spring Boot console integration, you're welcome to try it, file issues, or talk about use cases directly.

Comments

Top 2 from juejin.cn, machine-translated. The original thread is authoritative.

蜗牛875 1 likes

Recently patched in MCP: three access surfaces — server /mcp, browser window.ESQueryStudioMCP, local Node stdio — sharing 19 tools; read-only by default, authorized per connection, Claude Desktop / Cursor can query ES directly. The MCP deep-dive is updated in the article (visible once the review passes), docs: https://github.com/dengmeiluan/esquerystudio/blob/main/docs/mcp.md

蜗牛875

One more implementation layer: MCP is not 'just add an endpoint' — it's the same 19-tool contract aligned across three transports: server /mcp, in-page window.ESQueryStudioMCP, local Node stdio. The repo includes server/frontend/docs contract alignment tests (with negative controls) to prevent capability drift. Permissions are clamped by 'connection × tool': keys are issued per login user/role, connection-level read/write (QA/UAT writable, production read-only), tool whitelist, rpm/day/month quotas, rotation/revocation; plaintext appears only once in the creation response, storage keeps only SHA-256. Raw REST also classifies read/write: GET/HEAD read-only, POST query APIs read-only, write APIs and unknown POST/PUT/DELETE fail closed — a valid key doesn't automatically open writes. The version layer walks EsIndexAdmin: SQL, explain, update paths auto-rollback for ES 6/7/8/9; browser mode is zero-port and write tools are off by default; local Node connects directly to ES, so Claude Desktop / Cursor don't need to start Spring Boot. The management surface lives in Dev Tools → MCP panel, issuing keys and showing tools/call request counts and quotas. Deep usage for AI: fetch es_get_mapping/settings first, then generate DSL, lint/explain before execution; slow queries use list_tasks + profile + explain_doc; production read-only, QA writable relies on connection-level permissions, not prompt constraints.