OpenSearch MCP Server
Provides read-only tools for searching and inspecting an OpenSearch cluster, including listing indices, retrieving mappings and settings, running Query DSL document searches, checking cluster health and statistics, listing ISM policies and index templates, viewing shard allocation, hot threads, running tasks, and shard recovery status, and generating OpenSearch Dashboards Discover links.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OpenSearch MCP ServerList the indices in my cluster and show the cluster health."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
OpenSearch MCP Server
A Model Context Protocol (MCP) server that lets AI assistants such as Claude, ChatGPT and Cursor search and inspect an OpenSearch cluster.
It runs in two modes:
Local (stdio): the AI app starts the server as a child process on your machine. No network exposure and no token needed.
Remote (Streamable HTTP): one shared server (production:
https://opensearch-mcp.monotype.com) that clients reach over HTTPS. Every request must carry a valid API token or an OAuth token derived from one.
Tools
Area | Tool | What it does |
Indices |
| List all indices |
| Mapping of an index | |
| Settings of an index | |
Documents |
| Search an index with Query DSL (default size 20) |
Cluster |
| Cluster health |
| Cluster-wide statistics | |
Dashboards |
| Index patterns stored in |
| Build an OpenSearch Dashboards Discover link for a query | |
Admin |
| Index State Management policies |
| Index templates and their shard counts | |
| Shard distribution across nodes | |
| Hot threads on all nodes | |
| Running cluster tasks | |
| Shard recovery progress and ETA |
All tools are read-only.
Related MCP server: opensearch-mcp-server
Repository layout
This is the code repository. Deployment lives in a separate build repository (Helm chart, image
Dockerfile, Jenkins pipeline). Jenkins checks out both and builds the image from this repository's src/.
src/opensearch_mcp_server/
server.py entry point (stdio, or Streamable HTTP with --transport streamable-http)
es_client.py OpenSearch client (reads OPENSEARCH_* variables)
tools/ the MCP tools listed above
auth/
store.py SQLite store for API tokens and OAuth grants (hashes only)
provider.py OAuth 2.1 authorization server backed by API tokens
http_app.py authenticated Streamable HTTP app (discovery, sign-in page, /mcp)
cli.py opensearch-mcp-token command
tests/ pytest suite, including a fake OpenSearch serverThe build repository's image replaces server.py with its own k8s/api_image/app/server.py and installs with its
own pyproject.toml and constraints.txt. That version uses the official MCP SDK's FastMCP, serves the endpoint
under a secret MCP_PATH_TOKEN prefix and adds a Host-header check. It still uses the tools/ and auth/ packages
from this repository. When you change tools or authentication here, the next pipeline run picks them up. If you add
a dependency, add it to the build repository's app/pyproject.toml and constraints.txt too.
Requirements
Python 3.10 or newer (the production image uses 3.11)
uv for local development
Network access to an OpenSearch cluster and credentials for it
git clone <code-repo-url> opensearch-mcp-server
cd opensearch-mcp-server
uv syncConfiguration
Settings come from environment variables. For local work, copy .env-template to .env (git-ignored); the server
loads it automatically.
Variable | Default | Purpose |
| OpenSearch URL, e.g. | |
| OpenSearch credentials (required) | |
| OpenSearch Dashboards URL, used by | |
|
|
|
|
| Listen address for HTTP mode |
|
| Public origin, no path, e.g. |
|
| Path of the MCP endpoint (the production image derives it from |
|
| Token database. The server and |
| Comma-separated Host header values accepted on the MCP endpoint (DNS-rebinding protection) | |
|
| Proxies trusted for |
|
| OAuth access token lifetime, seconds |
|
| OAuth refresh token lifetime, seconds (30 days) |
| Claude, ChatGPT, Cursor, loopback | Comma-separated redirect URIs clients may register; a trailing |
|
| Stateless Streamable HTTP (for several replicas without sticky sessions) |
|
| Answer POSTs with plain JSON instead of an SSE stream |
Local use with Claude Desktop (stdio)
Add this to claude_desktop_config.json, with --directory pointing at your clone:
{
"mcpServers": {
"opensearch": {
"command": "uv",
"args": ["--directory", "/path/to/opensearch-mcp-server", "run", "opensearch-mcp-server"],
"env": {
"OPENSEARCH_HOST": "https://localhost:9200",
"OPENSEARCH_USERNAME": "",
"OPENSEARCH_PASSWORD": "",
"DASHBOARDS_HOST": "https://localhost:5601"
}
}
}
}The file is at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS and
%APPDATA%\Claude\claude_desktop_config.json on Windows. Restart Claude Desktop, then ask things like
"List all indices in the cluster" or "Show me the cluster health status".
Running the remote (HTTP) server locally
uv run opensearch-mcp-token create --name local-dev --expires 1d # prints the token once
uv run opensearch-mcp-server --transport streamable-http # http://127.0.0.1:8000/mcpThen check it:
curl -i -X POST http://127.0.0.1:8000/mcp # 401 with a WWW-Authenticate header
curl -i -X POST http://127.0.0.1:8000/mcp \
-H "Authorization: Bearer osmcp_..." \
-H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'MCP Inspector (npx @modelcontextprotocol/inspector) also
works. Choose Streamable HTTP and add the Authorization header.
Authentication
How it works
API tokens are created by an operator with
opensearch-mcp-token. They look likeosmcp_<id>_<secret>. Clients that can send a fixed header useAuthorization: Bearer osmcp_...directly.OAuth is for clients that only support MCP OAuth, such as Claude custom connectors and ChatGPT. The client discovers this server's authorization server from the
401response, registers itself (Dynamic Client Registration) and opens a sign-in page in the browser. There the user pastes an API token. The client then gets short-lived access tokens and rotating refresh tokens. These are tied to that API token: they never outlive it, and they stop working the moment it expires, is revoked or is rotated.Requests without a valid token get
401and never reach OpenSearch. Tool calls re-check the token right before running. A session opened with one token cannot be used with another.Only SHA-256 hashes of tokens, authorization codes and client secrets are stored, in a SQLite file created with mode
0600. Tokens and the secret URL prefix are redacted from logs.
Managing tokens
opensearch-mcp-token create --name <label> # asks for an expiration
opensearch-mcp-token list [--all] # id, name, status, created, expires, last used
opensearch-mcp-token rotate <id> [--grace 1h] # new token (asks for its expiration); old one revoked
opensearch-mcp-token revoke <id> # immediate, including OAuth sessions created with itEvery create and rotate asks "When should this token expire?". Accepted answers:
a date,
2026-12-31, meaning the end of that day in UTCa date and time,
2026-12-31T18:00(UTC) or2026-12-31T18:00+05:30a duration from now:
30m,12h,90d,8wnonefor a token that never expires (you are asked to confirm)
Past or unreadable values are asked again. --expires <value> skips the prompt for scripts. The token is printed
once on stdout (other messages go to stderr), so TOKEN=$(opensearch-mcp-token create --name ci --expires 30d)
works. It cannot be shown again; create a new one if it is lost.
Changes apply on the next request, with no restart. Use one token per person or integration so you can revoke
them separately. With rotate --grace 1h, the old token keeps working for an hour so clients can switch over.
Connecting clients
Use the endpoint URL https://opensearch-mcp.monotype.com/<MCP_PATH_TOKEN>/mcp in production, or
http://127.0.0.1:8000/mcp locally. Ask the operator for the URL and an API token.
Claude (claude.ai, Desktop, mobile)
Claude custom connectors use OAuth by default. Sending a fixed Authorization header is a
beta that only some organizations have.
OAuth (works on every plan):
Open Settings → Connectors → Add custom connector. On Team/Enterprise, an Owner first adds it under Organization settings → Connectors → Add → Custom → Web.
Enter a name and the endpoint URL. Leave the OAuth client ID and secret empty.
Click Connect. A browser page from this server opens.
Paste your API token and click Authorize. Claude lists the 14 tools.
When the API token expires or is revoked, Claude asks you to connect again. Paste a new token.
Request headers (beta organizations only): when adding the connector, choose no sign-in. Add the header
Authorization with the value Bearer osmcp_.... Type the Bearer prefix yourself, because Claude sends the
value exactly as entered.
Claude Code
claude mcp add --transport http opensearch https://opensearch-mcp.monotype.com/<MCP_PATH_TOKEN>/mcp \
--header "Authorization: Bearer osmcp_..."Or leave out --header and run /mcp in Claude Code to sign in through the browser.
Claude API (MCP connector)
Pass the endpoint URL as the MCP server url and the API token as authorization_token.
ChatGPT
Enable developer mode, add a custom MCP server with the endpoint URL and choose OAuth. Leave the client fields empty; ChatGPT registers itself, and you sign in with your API token.
Cursor, VS Code and other clients
Any client that can set headers works with the token directly, e.g. in Cursor's mcp.json:
{
"mcpServers": {
"opensearch": {
"url": "https://opensearch-mcp.monotype.com/<MCP_PATH_TOKEN>/mcp",
"headers": { "Authorization": "Bearer osmcp_..." }
}
}
}Production deployment
Production runs on EKS behind an internet-facing AWS NLB (TLS terminated with ACM) and Cloudflare. Everything for it is in the build repository.
Build repo path | Purpose |
| Image |
| Chart: Deployment, Service, NLB, ConfigMap, Secret, PersistentVolumeClaim for the token database |
|
|
|
|
| Jenkins pipeline: check out both repos, build, deploy with |
Pipeline
Jenkins checks out this repository (the "Codeget" stage) and the build repository. prebuildsteps.sh moves
k8s/api_image/* to the workspace root and builds and pushes <ECR>/opensearch-mcp:<build>. Then
make deploy_image_to_prod_k8 runs helm secrets upgrade --install --atomic. A failed rollout is rolled back
automatically.
Before the first run: the "Codeget" stage in push_to_env/prod.groovy must point at this code repository's
URL and branch.
What the chart sets up
MCP_TRANSPORT=streamable-http.MCP_PUBLIC_URLandMCP_ALLOWED_HOSTScome fromINGRESS_HOST(opensearch-mcp.monotype.com).MCP_PATH_TOKEN(sops secret) is a secret URL prefix on top of token authentication. It is not a replacement for it.A 1Gi ReadWriteOnce volume,
opensearch-mcp-data, is mounted at/datawithMCP_AUTH_DB=/data/auth.db. It is annotatedhelm.sh/resource-policy: keep, so uninstalling the release does not delete the tokens. It uses the cluster's default StorageClass; setpersistence.storageClassName(e.g.gp3) inprod.yamlif there is none. Check withkubectl get storageclass. To reuse a restored volume, setpersistence.existingClaim.Strategy
Recreate: only one pod can mount the volume, so the old pod stops before the new one starts. Expect about a minute of downtime per deploy. The chart refuses to render with a rolling update while persistence is on.One replica. Sessions are held in memory and the volume is single-attach.
The NLB, the kubelet probes and
helm testuse/health, which needs no token.
First deploy and token management
After the first deploy there are no tokens, so every MCP request is rejected. From the build repository, with the production kube context selected:
make token_create NAME=rajan-claude # interactive: asks for the expiration
make token_create NAME=ci-bot EXPIRES=90d # non-interactive
make token_list [ALL=1]
make token_rotate ID=<id> [GRACE=1h] [EXPIRES=...]
make token_revoke ID=<id>These run opensearch-mcp-token inside the running pod
(kubectl -n opensearch exec -it deploy/opensearch-mcp -- opensearch-mcp-token ...).
Network and proxy requirements
All of these paths must reach the pod:
/<MCP_PATH_TOKEN>/mcp,/.well-known/oauth-protected-resource/<MCP_PATH_TOKEN>/mcp,/.well-known/oauth-authorization-server,/authorize,/token,/register,/revoke,/oauth/login,/health. The NLB forwards everything.Cloudflare: Bot Fight Mode, WAF challenges or Cloudflare Access on these paths will break Claude and ChatGPT. Claude's traffic comes from
160.79.104.0/21. Rate limiting on/oauth/login,/registerand/tokenis recommended.The
Authorizationheader must be passed through. Responses must not be buffered, and OAuth endpoints must answer within Claude's 10 second limit.
Backups
The token database is the only state. Back it up with
kubectl -n opensearch exec deploy/opensearch-mcp -- python -c "import sqlite3; s=sqlite3.connect('/data/auth.db'); d=sqlite3.connect('/tmp/backup.db'); s.backup(d)"
followed by kubectl cp, or with EBS snapshots. It contains only hashes; if it is lost, issue new tokens.
Testing
uv sync
uv run pytestThe suite starts the real server against a fake OpenSearch (tests/fake_opensearch.py), so no cluster is needed.
It covers:
MCP initialization, tool discovery and tool calls
valid, invalid, expired, non-expiring, revoked and rotated tokens, including revocation in the middle of a session
the full Claude OAuth flow, from the
401to discovery, registration, PKCE sign-in, code exchange, refresh rotation and revocationthe stdio transport
the token CLI prompts
tests/test_deploy_image.py covers the production image: secret prefix, Host-header check and log redaction. It
is skipped unless the installed package is the image build. To run it, copy src/ plus the build repository's
app/server.py, app/pyproject.toml and constraints.txt into a directory as the Dockerfile does,
pip install --constraint constraints.txt . into a Python 3.11 virtualenv, then run python -m pytest from this
repository with that interpreter.
Security notes and limitations
The sign-in page asks for the API token itself. Users should only paste it into a sign-in they started from their own AI client. The page shows where it will redirect, and redirect URIs are limited by
MCP_OAUTH_REDIRECT_ALLOWLIST.Everyone who uses the same token shares one identity, and every token can use every tool. There are no per-tool scopes.
OpenSearch is accessed with a single service account (
OPENSEARCH_USERNAME), whatever the MCP caller. The client is created with certificate verification disabled (verify_certs=False).Client ID Metadata Documents are not supported, so Claude and ChatGPT use Dynamic Client Registration, which creates one client record per connection.
Authentication covers Streamable HTTP only. The old SSE transport is not available in HTTP mode. stdio stays local and unauthenticated by design.
This server cannot be deployed
Maintenance
Related MCP Connectors
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
- mcpOAuthcom.vibgrate
Query your team's drift, vulnerability, and upgrade data from any AI assistant. OAuth 2.1, 51 tools.
Query your Postgres from ChatGPT or Claude without exposing the database or handing over credentials. Run npx boltschema connect next to your database and it dials out over HTTPS — no inbound firewall rule, no open port, works with localhost and VPC-private databases. Read-only is enforced by a SQL guard, a Postgres READ ONLY transaction, and a scoped role generated for you.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables LLMs to interact with OpenSearch clusters to monitor cluster health, manage indices, and perform data searches. It provides a standardized interface for real-time OpenSearch operations within MCP-compatible environments like Open WebUI.-
- AlicenseBqualityFmaintenanceEnables interaction with OpenSearch clusters, providing tools to list indices, retrieve mappings, search using query DSL, and get shard information.41Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables natural language querying and analysis of OpenTelemetry traces, metrics, and logs stored in Elasticsearch/OpenSearch, allowing AI assistants to investigate performance issues, find root causes, and explore system behavior.7 npm14MIT
- AlicenseAqualityDmaintenanceRead-only MCP server for exploring and searching OpenSearch clusters, enabling log analysis, index exploration, and query execution.8MIT