mcp-opensearch
This server provides a read-only MCP bridge to OpenSearch and OpenSearch Dashboards, enabling secure log data search, aggregation, and exploration.
Connectivity & Health: Verify server connectivity, monitor cluster health (status, nodes, shards), and identify the authenticated user.
Index & Field Discovery: List indices with size/health, view saved Dashboards index patterns, retrieve field mappings, discover fields by sampling documents, and inspect index settings (shard count, replicas, ILM policies).
Search & Query: Perform full-text searches using Lucene syntax, count matching documents, build chronological timelines for entities across multiple fields, explain query scoring, and execute PPL (Piped Processing Language) pipelines for advanced multi-step operations.
Aggregations & Analytics: Generate term frequency tables, run multi-field aggregations, create time-series histograms, compute numeric statistics (min, max, avg, std), and compare top field values between two time windows to detect changes.
Alerting & Anomaly Detection: List Alerting monitors and their status, fetch active/historical alerts, list Anomaly Detection detectors, and retrieve ML-detected anomaly results.
Escape Hatch: Make arbitrary read-only GET requests to any OpenSearch REST endpoint not covered by dedicated tools (write/admin operations are blocked).
Prompts: Reusable investigation templates for triaging alerts, identifying top offenders, comparing time windows, and conducting single-agent deep dives.
Safety: Enforces read-only access, hard caps on search results (200 documents) and histogram buckets (2,000), warnings on text-field aggregations and missing time ranges.
Provides read-only tools for searching, aggregating, and exploring log data in OpenSearch clusters, including index discovery, mapping retrieval, field sampling, full-text search, count, terms and multi-terms aggregations, histogram, and numeric stats.
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., "@mcp-opensearchsearch for 'timeout' in logs from today"
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.
mcp-opensearch
/\ /\
/ \___/ \
/ (o) (o) \
| ~~ v ~~ |
| `-----` | mcp-opensearch
| / \ | ─────────────────────────────────────
| | ─ | | Read-only MCP server for
\| |/ OpenSearch & OpenSearch Dashboards.
| | Fuzzy log hunting.
/| |\
/ | | \
( | | )~~~~~
\_|_________|_/ ~~
Read-only MCP server for OpenSearch and OpenSearch Dashboards — search, aggregate, and explore your log data from Claude Code or any MCP-compatible AI assistant.
Features
22 tools covering connectivity checks, index/field discovery, full-text search, entity timelines, aggregations, time-series histograms, numeric stats, PPL queries, index settings, document explain, comparative analysis, Alerting-plugin monitors and alerts, Anomaly Detection detectors and results, and a generic GET escape hatch
4 investigation prompts — reusable templates for common log analysis workflows (single-agent investigation, top-offenders sweep, alert triage, baseline comparison)
Parallel requests — all tools support concurrent execution; Claude Code can fire multiple queries in a single turn (e.g.
opensearch_count+opensearch_terms+opensearch_searchsimultaneously) for faster investigationsTwo backends: OpenSearch Dashboards proxy (preferred) or direct OpenSearch REST API
Hard limits on search result size (default 200) and histogram bucket count (default 2,000) to protect cluster health
Text field aggregation warnings (fielddata heap pressure)
No-time-range warnings on potentially expensive full-history queries
Read-only write guard — only safe endpoints are in the allowlist
Configurable via environment variables or
~/.config/mcp-opensearch/config.jsonDocker image or bare Python (no Docker required)
Related MCP server: Elastic MCP Server
Requirements
Python 3.10+ or Docker
OpenSearch ≥ 2.x or OpenSearch Dashboards ≥ 2.x
Basic auth credentials
Quick Start
1. Clone
git clone https://github.com/bunnyiesart/mcp-opensearch.git
cd mcp-opensearch2. Configure
Create a .env file with your credentials:
# ~/.config/mcp-opensearch/.env
OPENSEARCH_DASHBOARDS_URL=https://opensearch.example.com
OPENSEARCH_USERNAME=myuser
OPENSEARCH_PASSWORD=mypassword
OPENSEARCH_VERIFY_SSL=trueOr run the interactive setup script:
./setup.sh3a. Docker (recommended)
Pull the pre-built image from GHCR:
docker pull ghcr.io/bunnyiesart/mcp-opensearch:latestOr build locally:
make buildVerify it works:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0"}}}' | \
docker run --rm -i --network host --env-file ~/.config/mcp-opensearch/.env ghcr.io/bunnyiesart/mcp-opensearch:latest3b. PyPI (recommended for Python users)
pip install mcp-opensearchThis installs the mcp-opensearch command directly into your PATH — no cloning or Docker required.
3c. From source
pip install -r requirements.txt
python3 server.py4. Register with Claude Code
Add the server to ~/.claude.json under your project path.
Via PyPI (mcp-opensearch command):
{
"projects": {
"/your/project": {
"mcpServers": {
"opensearch": {
"type": "stdio",
"command": "mcp-opensearch",
"args": [],
"env": {
"OPENSEARCH_DASHBOARDS_URL": "https://opensearch.example.com",
"OPENSEARCH_USERNAME": "myuser",
"OPENSEARCH_PASSWORD": "mypassword"
}
}
}
}
}
}Via Docker:
{
"projects": {
"/your/project": {
"mcpServers": {
"opensearch": {
"type": "stdio",
"command": "docker",
"args": [
"run", "--rm", "-i", "--network", "host",
"--env-file", "/home/youruser/.config/mcp-opensearch/.env",
"ghcr.io/bunnyiesart/mcp-opensearch:latest"
],
"env": {}
}
}
}
}
}Restart Claude Code, then call opensearch_test to confirm the connection is healthy.
Configuration
Environment variables take priority over the config file. At least one of OPENSEARCH_DASHBOARDS_URL or OPENSEARCH_URL is required. The config file at ~/.config/mcp-opensearch/config.json must be chmod 600.
Variable | Config key | Default | Description |
|
| — | Dashboards URL, tried first (e.g. |
|
| — | Direct OpenSearch URL, used as fallback (e.g. |
|
| — | Basic auth username |
|
| — | Basic auth password |
|
|
| Set |
|
|
| Request timeout in seconds |
|
|
| Hard cap on search |
|
|
| Reject histogram requests exceeding this estimated bucket count |
Tool Reference
Connectivity
opensearch_test
Call first in every session to confirm connectivity and see the active backend. The username field immediately explains why certain tools return 403 — it shows exactly which role is authenticated.
No parameters.
{
"ok": true,
"backend": "dashboards",
"version": "2.19.3",
"url": "https://opensearch.example.com",
"username": "myuser"
}opensearch_cluster_health ⚠️
Requires
cluster:monitor/healthprivilege. If you get 403, useopensearch_testfor basic connectivity instead.
No parameters. Returns cluster status (green/yellow/red), node count, and active/unassigned shard counts.
Index Discovery
opensearch_list_indices ⚠️
Requires
_cat/indicesaccess via the Dashboards proxy. If you get 403, useopensearch_list_index_patternsinstead.
No parameters. Returns a list sorted by index name:
[
{"index": "wazuh-alerts-4.x-2026.06.24", "docs.count": "559359", "store.size": "1.2gb", "health": "green"}
]opensearch_list_index_patterns
Dashboards-only alternative to opensearch_list_indices when _cat/indices access is blocked. Returns saved index patterns as configured in the Dashboards UI.
No parameters.
[
{"id": "abc123", "title": "wazuh-alerts-*", "timeFieldName": "@timestamp"}
]opensearch_get_mapping ⚠️
Requires
indices:admin/mappings/getprivilege. If you get 403, useopensearch_discover_fieldsinstead (only requires search privilege).
Parameter | Type | Default | Description |
| str | — | Index name or wildcard, e.g. |
Returns all fields flattened to dot-notation:
{
"wazuh-alerts-4.x-2026.06.24": {
"agent.name": "keyword",
"rule.level": "integer",
"@timestamp": "date"
}
}opensearch_discover_fields
Fallback for opensearch_get_mapping when the mapping API is blocked. Samples live documents instead of reading schema metadata — only returns fields present in the sampled documents.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard |
| str |
| Lucene filter to narrow the sample |
| str | — | ISO 8601 UTC start time |
| str | — | ISO 8601 UTC end time |
| str |
| Timestamp field name |
| int |
| Documents to sample (max 100) |
{
"agent.id": "str",
"agent.name": "str",
"rule.level": "int",
"@timestamp": "str"
}opensearch_index_settings
Get index operational settings: shard count, replicas, refresh interval, and ILM policy. Use when diagnosing unexpected index behaviour — slow writes, data retention issues, or replication risk. Prefer opensearch_get_mapping for field schema exploration.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard, e.g. |
{
"wazuh-alerts-4.x-2026.06.24": {
"number_of_shards": "3",
"number_of_replicas": "1",
"refresh_interval": "1s",
"lifecycle_name": "wazuh-alerts-policy",
"creation_date_ms": "1750550400000"
}
}May require
indices:monitor/settings/getprivilege. Returns 403 if blocked.
Search
opensearch_search
Full-document retrieval using Lucene syntax — the same syntax as the OpenSearch Dashboards search bar. Always pass source_fields to limit response size (50 full docs ≈ 237 KB). Omitting from_ts/to_ts scans the full index history; adding a time range reduces query time by up to 15×.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard pattern |
| list | — | Strongly recommended. Fields to include, e.g. |
| str |
| Lucene query, e.g. |
| str | — | ISO 8601 UTC start time |
| str | — | ISO 8601 UTC end time |
| str |
| Timestamp field name |
| int |
| Max documents to return (hard cap: 200) |
| int |
| Pagination offset — increment by |
| str |
| Field to sort by |
| str |
|
|
{
"total": 19824851,
"hits": [{"agent.name": "WIN-DC01", "rule.level": 12, "@timestamp": "2026-06-24T10:23:11Z"}],
"warning": "No time range specified — this query scans the full index history..."
}warning is present when the limit was capped or no time range was given.
opensearch_count
Fastest way to check how many documents match a condition. Never returns document content, so it never fills context. Without from_ts/to_ts, scans the full index (can take 4–5 s on 50 M docs).
Parameter | Type | Default | Description |
| str | — | Index name or wildcard |
| str |
| Lucene query |
| str | — | ISO 8601 UTC start time |
| str | — | ISO 8601 UTC end time |
| str |
| Timestamp field name |
{"count": 559359}opensearch_timeline
Build a chronological event timeline for a single entity (IP, host, user) matched across several fields at once — the core DFIR pivot. Instead of running opensearch_search repeatedly to chase an entity through data.srcip, data.dstip, agent.ip, etc., this ORs all fields together and returns events oldest-first.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard |
| str | — | Value to trace, e.g. |
| list | — | Fields the entity may appear in, e.g. |
| str | — | ISO 8601 UTC start time |
| str | — | ISO 8601 UTC end time |
| str |
| Timestamp field name |
| int |
| Max events, oldest-first (cap 200) |
| list | — | Fields to include per event (strongly recommended) |
| str | — | Optional Lucene filter ANDed with the entity match |
{"total": 42, "entity": "10.0.0.5", "fields": ["data.srcip","data.dstip"], "events": [ ... ]}opensearch_ppl
Execute a PPL (Piped Processing Language) query. Prefer over opensearch_search when you need multi-step pipeline operations (filter → stats → sort) in a single query. PPL is not interchangeable with Lucene — it uses a different syntax native to OpenSearch observability workloads.
Returns 404 if the PPL plugin is not installed on the cluster.
Parameter | Type | Default | Description |
| str | — | Full PPL query string |
PPL syntax: source=<index> | <command> [| <command> ...]
Common commands:
Command | Description |
| Filter rows |
| Aggregate |
| Select columns |
| Order results (- = descending) |
| Limit rows |
source=wazuh-alerts-4.x-* | where rule.level > 10
| stats count() as hits by agent.name | sort -hits | head 20{
"schema": [{"name": "agent.name", "type": "keyword"}, {"name": "hits", "type": "integer"}],
"datarows": [["WIN-DC01", 4821], ["srv-web01", 2103]]
}opensearch_explain
Explain why a specific document matches (or doesn't match) a query. Use after opensearch_search returns unexpected results and you have a known document ID. Requires an exact index name — no wildcards.
Parameter | Type | Default | Description |
| str | — | Exact index name, e.g. |
| str | — | Document |
| str |
| Lucene query to evaluate against the document |
{
"matched": true,
"explanation": {
"value": 1.0,
"description": "ConstantScore(agent.name:WIN-DC01)",
"details": []
}
}Requires
indices:data/read/explainprivilege.
Aggregations
opensearch_terms
Frequency table for a keyword field — top N values with their document counts. If results look wrong or you see a heap warning, append .keyword to the field name (e.g. agent.name.keyword). Never use on analyzed text fields like rule.description — it loads fielddata into cluster heap.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard |
| str | — | Keyword field to aggregate, e.g. |
| str |
| Lucene filter |
| str | — | ISO 8601 UTC start time |
| str | — | ISO 8601 UTC end time |
| str |
| Timestamp field name |
| int |
| Number of top values to return |
{
"WIN-DC01": 4821,
"srv-web01": 2103,
"_warning": "Field 'rule.description' looks like a text field. Try 'rule.description.keyword'..."
}_warning is present if the field name suggests an analyzed text type.
opensearch_multi_terms
Preferred over calling opensearch_terms in a loop — runs multiple field frequency analyses in a single round-trip. Significantly faster when you need counts for several fields at once.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard |
| list | — | List of aggregation specs (see below). Must not be empty. |
| str |
| Lucene filter |
| str | — | ISO 8601 UTC start time |
| str | — | ISO 8601 UTC end time |
| str |
| Timestamp field name |
Each item in aggregations:
{"id": "agents", "field": "agent.name", "size": 20}{
"agents": {"WIN-DC01": 4821, "srv-web01": 2103},
"rules": {"550": 12000, "5710": 8400},
"sources": {"192.168.1.10": 3200}
}opensearch_histogram
Event count over time. Always specify from_ts and to_ts (meaningless without a range). Use interval="auto" when unsure — it picks ~50 buckets and is always safe. Fine intervals over long ranges (e.g. "1m" over a week) are rejected before the query runs.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard |
| str | — | Required. ISO 8601 UTC start time |
| str | — | Required. ISO 8601 UTC end time |
| str |
| Timestamp field name |
| str |
| Bucket size. Format: |
| str |
| Lucene filter |
{
"interval_used": "1h",
"results": {
"2026-06-24T00:00:00.000Z": 1203,
"2026-06-24T01:00:00.000Z": 987
}
}interval_used reflects the actual bucket size chosen when interval="auto".
opensearch_stats
Min/max/avg/std for a numeric field. Only works on numeric types (integer, float, long) — passing a text field returns a 400 error with a clear message.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard |
| str | — | Numeric field, e.g. |
| str |
| Lucene filter |
| str | — | ISO 8601 UTC start time |
| str | — | ISO 8601 UTC end time |
| str |
| Timestamp field name |
{
"count": 559359,
"min": 0,
"max": 15,
"avg": 7.4,
"sum": 4139834,
"std_deviation": 3.1
}opensearch_list_monitors
List OpenSearch Alerting-plugin monitors (detection rules) and whether they are enabled. Use to see what detections exist before investigating why something did — or did not — fire.
Requires the Alerting plugin and monitor-search privilege. Returns 403/404 otherwise.
Parameter | Type | Default | Description |
| int |
| Max monitors to return |
[{"id": "abc123", "name": "High severity alerts", "enabled": true, "type": "query_level_monitor", "schedule": {"period": {"interval": 1, "unit": "MINUTES"}}}]opensearch_get_alerts
Fetch alerts raised by Alerting-plugin monitors — the "what is firing right now?" tool. Start a triage session here, then pivot on the offending entity with opensearch_timeline.
Requires the Alerting plugin. Returns 403/404 otherwise.
Parameter | Type | Default | Description |
| str | — | Filter: |
| str | — | Restrict to one monitor |
| int |
| Max alerts, newest-first |
{"total": 3, "alerts": [{"id": "a1", "monitor_name": "High severity alerts", "trigger_name": "level>=12", "state": "ACTIVE", "severity": "1", "start_time": 1719100800000}]}opensearch_list_detectors
List OpenSearch Anomaly Detection detectors and the indices they watch. Use before pulling results with opensearch_get_anomaly_results.
Requires the Anomaly Detection plugin and detector-search privilege. Returns 403/404 otherwise.
Parameter | Type | Default | Description |
| int |
| Max detectors to return |
[{"id": "det1", "name": "srcip-beaconing", "description": "outbound beaconing", "indices": ["wazuh-alerts-*"], "detection_interval": {"period": {"interval": 10, "unit": "Minutes"}}}]opensearch_get_anomaly_results
Fetch ML-detected anomalies (beaconing, spikes, rare activity), highest anomaly-grade first — no hand-written aggregations needed.
Requires the Anomaly Detection plugin. Returns 403/404 otherwise.
Parameter | Type | Default | Description |
| str | — | Restrict to one detector (recommended) |
| str | — | Filter on |
| str | — | Filter on |
| float |
| Only anomalies with |
| int |
| Max anomalies, highest grade first |
{"total": 12, "anomalies": [{"detector_id": "det1", "anomaly_grade": 0.92, "confidence": 0.88, "data_start_time": 1719100200000, "data_end_time": 1719100800000}]}opensearch_compare
Compare the top values of a field between two time windows. Returns a structured diff with added, removed, and changed values sorted by absolute delta. Prefer over calling opensearch_terms twice manually.
Parameter | Type | Default | Description |
| str | — | Index name or wildcard |
| str | — | Keyword field, e.g. |
| str | — | Baseline window start, ISO 8601 UTC |
| str | — | Baseline window end, ISO 8601 UTC |
| str | — | Selection window start, ISO 8601 UTC |
| str | — | Selection window end, ISO 8601 UTC |
| str |
| Lucene filter applied to both windows |
| str |
| Timestamp field name |
| int |
| Top N values to fetch per window |
{
"added": {"new-host-01": 342},
"removed": {"decommissioned-srv": 12},
"changed": {
"WIN-DC01": {"baseline": 1200, "selection": 4821, "delta": 3621, "pct_change": 301.8}
},
"unchanged": {"srv-web01": {"baseline": 2100, "selection": 2103}},
"baseline_warning": null,
"selection_warning": null
}changed is sorted by absolute delta descending so the most significant shifts appear first.
Escape Hatch
opensearch_api
Generic GET escape hatch for any read endpoint not covered by the other tools. Use when you know the OpenSearch REST path but no dedicated tool exists. For search, aggregations, and histograms, use the dedicated tools — they add safety guards and better error messages.
Write and admin paths are blocked: any path containing _delete, _bulk, _update, _create, _reindex, _rollover, _shrink, _split, _clone, _open, _freeze, _unfreeze, or _forcemerge raises an error before any request is made.
Parameter | Type | Default | Description |
| str | — | OpenSearch path starting with |
Example valid paths:
/_nodes/stats/_plugins/_ism/policies/my-index/_alias/my-index/_shard_stores
Returns the raw JSON response from OpenSearch.
Prompts
MCP Prompts are reusable investigation templates. In compatible clients they appear as slash commands. Each prompt returns a step-by-step workflow pre-filled with the parameters you provide.
investigate_alert
Step-by-step investigation guide for a specific agent's alerts in a time window. Walks through: total count → rule distribution → rule descriptions → event timeline → highest-severity sample → summary questions.
Parameter | Description |
| Index name or wildcard, e.g. |
| Agent to investigate, e.g. |
| Window start, ISO 8601 UTC |
| Window end, ISO 8601 UTC |
top_offenders
Find the top agents, rules, and source/destination IPs in a time window. Runs five independent aggregations in parallel, then guides you through correlating spikes, pivot points, and anomalous counts.
Parameter | Description |
| Index name or wildcard |
| Window start, ISO 8601 UTC |
| Window end, ISO 8601 UTC |
compare_time_windows
Compare alert patterns between a baseline period and a selection period. Uses opensearch_compare across rule IDs, agent names, and source IPs, then guides you through drilling into new threats, increased activity, and agents that went quiet.
Parameter | Description |
| Index name or wildcard |
| Baseline start, ISO 8601 UTC |
| Baseline end, ISO 8601 UTC |
| Selection start, ISO 8601 UTC |
| Selection end, ISO 8601 UTC |
Safety & Limits
Guard | Default | Override |
Max search results | 200 docs |
|
Max histogram buckets | 2,000 |
|
Max | 100 docs | hardcoded |
Write guard | all writes blocked | hardcoded |
| blocked | hardcoded |
Bucket pre-check — Histogram requests are validated before execution. The expected bucket count is calculated as (to_ts − from_ts) / interval. If it exceeds the limit, the request is rejected with an actionable error message instead of firing a query that would hold OpenSearch threads for minutes.
Text field warnings — opensearch_terms and opensearch_multi_terms detect field names that suggest analyzed text types and include a _warning in the response. Aggregating on unindexed text fields triggers fielddata loading on the OpenSearch heap.
No-time-range warnings — opensearch_search and opensearch_count include a warning when no from_ts/to_ts is given. A full-index scan on tens of millions of documents is slow and expensive; adding a time range typically reduces query time by 10–15×.
Write-fragment blocklist — opensearch_api checks the path for 14 keywords that indicate write or admin operations before making any request.
Known Limitations
Some tools require elevated privileges or plugins not available on all deployments:
Tool | Required privilege | Alternative |
|
|
|
|
|
|
|
|
|
|
| — |
| PPL plugin must be installed |
|
| Alerting plugin + alerting read privilege | — |
| Anomaly Detection plugin + AD read privilege | — |
These tools return a structured error message (not a raw stack trace) when the privilege is missing. The opensearch_test tool includes the authenticated username in its response, which immediately clarifies why specific calls fail.
Development
make build # build Docker image (opensearch-mcp:dev)
make run # run interactively (reads ~/.config/mcp-opensearch/.env)
make shell # open a bash shell inside the container for debuggingOverride the env file path:
make run ENV_FILE=/path/to/other.envLicense
MIT
Available Tools
17 toolsopensearch_apiA
Escape hatch for any read GET endpoint not covered by other tools.
Use when you know the OpenSearch REST path but no dedicated tool exists. For search/count/terms/histogram use the dedicated tools — they add safety guards and better error messages. Only GET is supported; write/admin paths (_delete, _bulk, _update, _reindex, etc.) are blocked.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | OpenSearch path starting with "/", e.g. "/_nodes/stats". |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It discloses that only GET is supported, write/admin paths are blocked, and that dedicated tools have safety guards and better error messages, implying reduced safety for this tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Extremely concise with three short sentences. First sentence states primary purpose, second gives usage guidance, third clarifies limitations. No redundant words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema (context indicates exists), description does not need to explain return values. It covers allowed operations, usage context, and limitations completely for a single-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a description for the 'path' parameter. The description adds value by specifying it must start with '/' and giving an example ('/_nodes/stats'), which complements the schema well.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it is an 'escape hatch for any read GET endpoint not covered by other tools', specifying the verb (GET), the resource (OpenSearch endpoints), and distinguishing it from sibling tools by naming dedicated tools for specific operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use (when no dedicated tool exists) and when not to (use dedicated tools for search/count/terms/histogram). Also warns that write/admin paths are blocked, providing clear guidance on appropriate usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_cluster_healthA
Requires cluster:monitor/health privilege — if you get 403, use opensearch_test instead.
Returns cluster status (green/yellow/red), node count, active shards, and unassigned shards. Useful to confirm the backend is not degraded before trusting query results.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses required privilege (cluster:monitor/health) and error handling (403). Without annotations, this is transparent about access and safety. Could explicitly state it is a read-only operation, but the description is still informative.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences cover privilege, returns, and usage without wasted words. Information is front-loaded and well-organized.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and an output schema, the description adequately covers privilege, return fields, and use case. It is complete for tool selection and basic invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist in the input schema, and schema coverage is 100%. Baseline score of 4 applies as there is nothing to add beyond what the schema already defines.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool returns cluster status with specific fields (green/yellow/red, node count, active shards, unassigned shards). It distinguishes itself from sibling opensearch_test by suggesting fallback on 403, clarifying its purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises when to use: to confirm backend is not degraded before trusting query results. Also provides a conditional alternative: if 403, use opensearch_test. This gives clear when-to and when-not-to guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_compareA
Compare the top values of a field between two time windows.
Prefer over calling opensearch_terms twice manually — computes the diff and percent change automatically. Use to detect new patterns, increased/decreased activity, or disappeared sources between a baseline and a selection period.
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | Top N values to fetch per window (default 20). | |
| field | Yes | Keyword field to compare, e.g. "rule.id", "agent.name", "data.srcip". | |
| index | Yes | Index name or wildcard pattern. | |
| ts_field | No | Timestamp field (default "@timestamp"). | @timestamp |
| baseline_to | Yes | Baseline window end, UTC ISO 8601. | |
| query_string | No | Lucene filter applied to both windows (default "*"). | * |
| selection_to | Yes | Selection window end, UTC ISO 8601. | |
| baseline_from | Yes | Baseline window start, UTC ISO 8601. | |
| selection_from | Yes | Selection window start, UTC ISO 8601. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It mentions computing diff and percent change automatically but does not disclose any other behavioral traits (e.g., rate limits, auth needs, destructive actions). Adequate for a read-like operation but lacks full transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences: first states core action, second gives usage guidance, third lists use cases. Front-loaded, no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Has output schema, so return values need not be explained. Description covers purpose, usage, and intended outcomes. Could mention aggregation behavior, but adequate for context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description does not add extra meaning beyond the schema; it explains the overall purpose but not individual parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it compares top values of a field between two time windows, and distinguishes from sibling opensearch_terms by emphasizing automatic diff/percent change calculation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly recommends using this tool over manual double calls to opensearch_terms, and lists use cases (detect new patterns, activity changes). No explicit when-not or alternatives beyond opensearch_terms.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_countA
Fastest way to check how many documents match a condition; never returns content.
Prefer over opensearch_search when you only need the count — it never fills context with document data. Without from_ts/to_ts, scans the full index (4–5 s on 50 M docs).
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | Index name or wildcard pattern. | |
| to_ts | No | End time, UTC ISO 8601. | |
| from_ts | No | Start time, UTC ISO 8601. | |
| ts_field | No | Timestamp field name (default "@timestamp"). | @timestamp |
| query_string | No | Lucene query string (default "*" = all documents). | * |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description does well to disclose key behaviors: never returns content, and full index scan timing. Could mention that it returns a single count value, but output schema likely covers that.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, efficient and front-loaded with the most important information about purpose and when to use. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and presence of an output schema, the description covers all necessary context: what it does, when to use it, and a performance note. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. Description does not add significant meaning beyond what is already in the schema for parameters like from_ts, to_ts, query_string, etc.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it is the fastest way to count documents matching a condition and explicitly says it never returns content. This distinguishes it from sibling tools like opensearch_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Directly advises to prefer this tool over opensearch_search when only a count is needed, and provides performance context about full index scan duration when time filters are omitted.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_discover_fieldsA
Fallback for opensearch_get_mapping when the mapping API is blocked; samples live documents.
Only returns fields that actually appear in the sampled documents — fields absent from the sample won't be listed. Unlike opensearch_get_mapping, only requires search privilege. Increase sample_size for broader field coverage (max 100).
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | Index name or wildcard pattern. | |
| to_ts | No | Sample up to this timestamp, UTC ISO 8601. | |
| from_ts | No | Sample from this timestamp, UTC ISO 8601 (e.g. "2026-06-01T00:00:00Z"). | |
| ts_field | No | Timestamp field name (default "@timestamp"). | @timestamp |
| sample_size | No | Number of documents to sample (default 10, max 100). | |
| query_string | No | Lucene filter to narrow the sample (default "*"). | * |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description fully carries the burden of behavioral disclosure. It reveals key traits: only returns fields that appear in sampled documents, fields absent won't be listed, requires search privilege, and sample_size max 100. It could be more explicit about the trade-off of small sample sizes leading to incomplete results, but overall it provides sufficient behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is only three sentences, each serving a distinct purpose: stating the primary use case, explaining a key limitation, and comparing with a sibling tool while giving actionable advice. No words are wasted, and the most important information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the presence of an output schema, the description does not need to detail return values. It covers purpose, usage, behavioral traits, and parameter guidance. It could mention that the index must exist or how errors are handled, but for a relatively simple tool, it is highly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds some context around sample_size by suggesting increasing it for broader coverage and mentioning the max of 100. However, it does not add significant new meaning beyond what the schema already provides for other parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description explicitly states the tool's purpose as a fallback for opensearch_get_mapping when the mapping API is blocked, and that it samples live documents to discover fields. It clearly distinguishes itself from the sibling tool opensearch_get_mapping, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use this tool (as a fallback when the mapping API is blocked) and why it is preferred in certain contexts (only requires search privilege). It also provides guidance on adjusting sample_size for broader coverage, giving clear usage recommendations.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_explainA
Explain why a specific document matches (or doesn't match) a query.
Use after opensearch_search returns unexpected results and you have a known document ID. Get the doc ID from a prior search by including "_id" in source_fields (note: _id is a metadata field — use opensearch_search and read the _id from hits). Exact index name only — no wildcards.
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | Exact index name, e.g. "wazuh-alerts-4.x-2026.06.24". | |
| doc_id | Yes | Document _id as returned by a prior search. | |
| query_string | No | Lucene query to evaluate against the document (default "*"). | * |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It adds constraints ('Exact index name only — no wildcards') and metadata context (_id field), but does not disclose authorization needs, side effects (likely read-only, but unstated), or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences: purpose, usage context, constraint. Front-loaded with the core action, no wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given output schema exists and schema coverage is high, description provides sufficient context for an agent to use the tool. Lacks mention of error scenarios or output structure, but output schema compensates.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters. Description adds clarifying context: 'Exact index name only' for index, 'as returned by a prior search' for doc_id, and Lucene query format for query_string. Adds value beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the verb 'explain' and resource 'why a document matches or doesn't match a query'. Differentiates from siblings by specifying use after opensearch_search and requiring a known document ID.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use ('after opensearch_search returns unexpected results') and prerequisites ('known document ID'). Does not explicitly state when not to use, but context implies it's only for analysis of specific docs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_get_mappingA
Use to see all field names and types; if you get 403 use opensearch_discover_fields instead.
opensearch_discover_fields only requires search privilege (not indices:admin/mappings/get) but only returns fields present in sampled documents. Returns nested fields flattened to dot-notation, e.g. "rule.level": "integer".
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | Index name or wildcard pattern, e.g. "wazuh-alerts-*". |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It reveals that nested fields are returned flattened to dot-notation, which is a key behavioral detail. It also implies the operation is read-only and requires specific permissions. Lacks mention of error formats or pagination, but the output schema provides additional structure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose, no fluff. Every sentence adds value: the first states what it does, the second provides the alternative and behavioral detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter tool with an output schema, the description is complete. It covers purpose, usage guidance, and a key behavioral trait. The sibling tool is mentioned, providing full context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the sole parameter 'index' is well-described in the schema. The description does not add extra semantic meaning beyond the schema, meeting the baseline expectation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'see all field names and types', specifying the verb 'see' and resource 'field names and types'. It distinguishes itself from the sibling tool opensearch_discover_fields by explaining the permission difference and data scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use this tool versus the alternative: 'if you get 403 use opensearch_discover_fields instead'. Also explains the privilege difference (indices:admin/mappings/get vs search privilege), giving clear context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_histogramA
Event count over time; always specify from_ts and to_ts (meaningless without a range).
Use interval="auto" when unsure — it picks ~50 buckets and is always safe. Fine intervals over long ranges (e.g. "1m" over a week) are rejected before the query runs to protect cluster resources.
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | Index name or wildcard pattern. | |
| to_ts | Yes | End time, UTC ISO 8601 (required), e.g. "2026-06-24T00:00:00Z". | |
| from_ts | Yes | Start time, UTC ISO 8601 (required), e.g. "2026-06-23T00:00:00Z". | |
| interval | No | Bucket size — e.g. "1h", "30m", "1d", "15m", or "auto". | 1h |
| ts_field | No | Timestamp field name (default "@timestamp"). | @timestamp |
| query_string | No | Lucene filter (default "*"). | * |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations available, so the description carries full burden. It discloses that fine intervals over long ranges are rejected for resource protection, but does not explicitly state that the tool is read-only or describe other behavioral traits like idempotency or authorization needs. Some transparency provided, but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences with no filler. First sentence states purpose, second gives primary usage guideline, third warns of a constraint. Front-loaded and every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With output schema present, return values need no elaboration. The description covers key usage nuances (range necessity, interval behavior) and constraints. Minor omission: explicit mention that it produces histograms, but purpose implies that. Good completeness for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds meaningful context beyond schema: mandates from_ts/to_ts usage, recommends 'auto' interval, and explains rejection of fine intervals. This extra guidance raises the score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Event count over time' with specific verb (count) and resource (events over time), and emphasizes the range requirement which distinguishes it from search or raw data retrieval tools. Siblings like opensearch_search, opensearch_terms, etc., have different purposes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly advises to 'always specify from_ts and to_ts' and recommends using interval='auto' when unsure. Warns that fine intervals over long ranges are rejected pre-query, providing clear when-to-use and safety constraints.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_index_settingsA
Get index settings: shard count, replicas, refresh interval, and ILM policy name.
Use to understand why an index behaves unexpectedly — e.g. slow writes from a short refresh interval, data loss risk from zero replicas, or unexpected retention from an ILM policy. Prefer opensearch_get_mapping for field schema exploration.
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | Index name or wildcard pattern, e.g. "wazuh-alerts-*". |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It implies a read operation but does not explicitly state read-only behavior, permissions, or potential side effects. For a simple read tool this is adequate but not fully transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core purpose, followed by motivational examples and a sibling reference. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple input (one parameter with full schema coverage) and existence of an output schema, the description sufficiently explains what the tool does and when to use it, with illustrative examples.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with a clear parameter description. The tool description adds value by listing what settings are retrieved for the given index, giving context beyond the parameter name.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool gets index settings, listing specific items (shard count, replicas, etc.). It also distinguishes from a sibling by advising to use opensearch_get_mapping for field schema exploration.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use: to understand unexpected index behavior, with concrete examples. Also gives an alternative tool for a different purpose, providing clear usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_list_index_patternsA
Dashboards-only alternative to opensearch_list_indices when _cat/indices access is blocked.
Returns id, title, and time field name for each index pattern as configured in the OpenSearch Dashboards UI. Requires the Dashboards backend to be active.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries burden. It states the tool is read-like, returns specific fields, and requires Dashboards backend. However, it omits behavior if backend is down (e.g., empty result vs error) and does not explicitly label as read-only, but it is sufficiently transparent for its simplicity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, front-loaded with purpose and alternative, no wasted words. Each sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool is simple (0 parameters, output schema exists). Description covers purpose, use case, return fields, and dependency. No gaps given the context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema has zero parameters (100% coverage trivially). Baseline for 0 params is 4. No parameter information needed; description focuses on output and usage, which is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it is a 'Dashboards-only alternative to opensearch_list_indices' that 'returns id, title, and time field name for each index pattern'. It uses specific verbs and resource (list index patterns) and distinguishes from sibling opensearch_list_indices.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use: when '_cat/indices access is blocked'. Also mentions prerequisite: 'Requires the Dashboards backend to be active'. This clearly distinguishes from alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_list_indicesA
If you get 403, use opensearch_list_index_patterns instead (lower privilege requirement).
Returns all indices sorted by name with doc count, store size, and health. Use this to find the exact index name before querying — date-sharded indices follow a pattern like wazuh-alerts-4.x-2026.06.24.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, but the description adds valuable behavioral context: the tool returns specific fields (doc count, store size, health), sorting behavior, and the potential for a 403 error with an alternative. However, it does not explicitly state if the operation is read-only or mention other constraints like rate limits, so one point off.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences efficiently cover the fallback, return data, and usage hint. No fluff or redundancy; every sentence serves a purpose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and an existing output schema, the description provides complete context: return structure, sorting, error handling, and a concrete use case. There is no missing information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters and schema coverage is 100%, so the baseline is 4. The description does not need to add parameter semantics, but it does add usage context beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns all indices sorted by name with doc count, store size, and health. It also explains the use case of finding exact index name before querying and describes the date-sharded naming pattern, distinguishing it from sibling tools like opensearch_search or opensearch_cluster_health.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides a fallback alternative (opensearch_list_index_patterns) for lower privilege requirements, and explains when to use the tool (before querying for exact index name). This gives clear guidance on when to use this tool vs. alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_multi_termsA
Preferred over calling opensearch_terms in a loop — single round-trip for multiple fields.
Inherits the .keyword guidance from opensearch_terms: append .keyword to any text-like field name to avoid fielddata heap pressure.
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | Index name or wildcard pattern. | |
| to_ts | No | End time, UTC ISO 8601. | |
| from_ts | No | Start time, UTC ISO 8601. | |
| ts_field | No | Timestamp field name (default "@timestamp"). | @timestamp |
| aggregations | Yes | List of aggregation specs, each a dict with: - id (str): Label for this aggregation in the result. - field (str): Keyword field to aggregate. - size (int, optional): Top N values (default 50). Example: [{"id": "agents", "field": "agent.name", "size": 20}, {"id": "rules", "field": "rule.id", "size": 10}, {"id": "sources", "field": "data.srcip", "size": 30}] | |
| query_string | No | Lucene filter (default "*"). | * |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description mentions single round-trip and fielddata heap avoidance, but with no annotations, more behavioral details (limits, errors) would be helpful.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two focused sentences, no fluff, front-loaded with key benefit.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema covers return values. Description covers usage context and a gotcha. Lacks error/permission info but adequate for a simple aggregation tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema does the heavy lifting. Description adds .keyword context but little extra semantic meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it performs multi-field terms aggregation in a single round-trip, distinguishing it from looping opensearch_terms.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly recommends over looping opensearch_terms and provides .keyword guidance, but lacks explicit when-not-to-use scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_pplA
Execute a PPL (Piped Processing Language) query against OpenSearch.
Prefer over opensearch_search when you need multi-step pipeline operations (filter → stats → sort) in a single query. Not interchangeable with Lucene — different syntax. Returns 404 if the PPL plugin is not installed.
PPL syntax: source= | [| ...] Common commands: where — filter rows stats count() by — aggregate fields , — select columns sort - — order results (- = descending) head — limit rows
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Full PPL query string. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses a critical failure mode (404 if PPL plugin not installed) and explains that it executes a query (implying read operation). However, it does not explicitly state whether the tool is read-only or if it can mutate data, which is a minor gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise and well-structured: a one-line purpose, a usage guideline, syntax format, and a list of common commands. Every sentence adds value with no fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the single parameter with complete schema coverage and presence of an output schema, the description thoroughly covers syntax, common commands, alternative tool guidance, and a failure case. It is fully sufficient for correct agent invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter 'query' with 100% schema coverage. The description adds significant value by providing PPL syntax, common commands (where, stats, fields, sort, head) and their usage, far exceeding the schema's bare description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool executes a PPL query against OpenSearch, using a specific verb and resource. It distinguishes from sibling tool opensearch_search by noting PPL vs Lucene syntax, making the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to prefer over opensearch_search for multi-step pipeline operations, warns about non-interchangeability with Lucene, and mentions a specific failure condition (404 if plugin missing). Provides clear when-to-use and not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_searchA
Full-document retrieval using Lucene syntax (same as the Dashboards search bar).
Always pass source_fields to limit response size — 50 full docs ≈ 237 KB and will fill context quickly. Omitting from_ts/to_ts scans the full index history, which is slow and expensive; adding a time range reduces query time by up to 15×.
| Name | Required | Description | Default |
|---|---|---|---|
| index | Yes | Index name or wildcard pattern, e.g. "wazuh-alerts-*". | |
| limit | No | Max documents to return (default 50, hard cap 200). | |
| to_ts | No | End time, UTC ISO 8601, e.g. "2026-06-24T00:00:00Z". | |
| offset | No | Pagination offset — skip this many documents before returning results (default 0). Increment by limit to page: offset=0 → page 1, offset=50 → page 2, etc. | |
| from_ts | No | Start time, UTC ISO 8601, e.g. "2026-06-23T00:00:00Z". | |
| sort_dir | No | "desc" = newest first (default), "asc" = oldest first. | desc |
| ts_field | No | Timestamp field name (default "@timestamp"). | @timestamp |
| sort_field | No | Field to sort by (default: ts_field). | |
| query_string | No | Lucene query, e.g. "rule.level:[12 TO *] AND agent.name:WIN-DC01". Use "*" for all documents. | * |
| source_fields | No | Fields to include, e.g. ["agent.name", "rule.level", "@timestamp"]. Strongly recommended — omitting returns all fields. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses concrete behavior: 50 full docs ≈ 237 KB, omitting time filters scans full index (slow/expensive), and adding time range reduces query time up to 15×. With no annotations, this adds significant behavioral context beyond mere functionality.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two well-structured sentences with no fluff. First sentence defines purpose, second provides critical usage advice. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 10 parameters and output schema, the description covers the core purpose and most critical performance considerations. Output schema makes return format documentation unnecessary. A minor omission is lack of guidance on offset pagination, but offset is well-described in schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description adds meaning by explaining why source_fields and from_ts/to_ts are important for performance and context usage, going beyond their schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Full-document retrieval using Lucene syntax', which is specific and distinguishes from sibling tools like opensearch_count or opensearch_stats that do not return full documents. However, it does not explicitly mention when to use this over alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides important best practices (pass source_fields to limit size, add time range to reduce cost) but does not explicitly state when to use this tool versus alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_statsA
Min/max/avg/std for a numeric field. Only works on numeric types (integer, float, long).
Passing a text field returns a 400 error with a clear message. Use opensearch_terms if you want frequency counts for a keyword field instead.
| Name | Required | Description | Default |
|---|---|---|---|
| field | Yes | Numeric field, e.g. "rule.level", "data.bytes". | |
| index | Yes | Index name or wildcard pattern. | |
| to_ts | No | End time, UTC ISO 8601. | |
| from_ts | No | Start time, UTC ISO 8601. | |
| ts_field | No | Timestamp field name (default "@timestamp"). | @timestamp |
| query_string | No | Lucene filter (default "*"). | * |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description discloses that the tool errors gracefully on non-numeric fields, implying safety. It does not cover other behaviors like performance or pagination, but the output schema exists to describe return values.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two paragraphs: first states purpose and constraint, second details error handling and alternative. Every sentence adds value, and it is front-loaded with the essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple stats tool with full schema coverage and an output schema, the description covers the numeric constraint, error behavior, and alternative tool. It provides sufficient context for correct agent usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, baseline 3. The description adds critical context: the field must be numeric and provides example formats ('rule.level', 'data.bytes'), which is not evident from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool computes min/max/avg/std for a numeric field, with a specific verb and resource. It distinguishes itself from opensearch_terms by noting the alternative for keyword fields.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the tool only works on numeric fields, warns of a 400 error for text fields, and recommends opensearch_terms for keyword fields. This provides clear when-to-use and when-not-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_termsA
Frequency table for a keyword field — top N values with their document counts.
If results look wrong or you see a heap warning, append .keyword to the field name (e.g. agent.name.keyword). Never use on analyzed text fields like rule.description — aggregations on text fields load fielddata into cluster heap.
| Name | Required | Description | Default |
|---|---|---|---|
| size | No | Number of top values to return (default 50). | |
| field | Yes | Keyword field to aggregate, e.g. "agent.name", "rule.id", "data.srcip". | |
| index | Yes | Index name or wildcard pattern. | |
| to_ts | No | End time, UTC ISO 8601. | |
| from_ts | No | Start time, UTC ISO 8601. | |
| ts_field | No | Timestamp field name (default "@timestamp"). | @timestamp |
| query_string | No | Lucene filter (default "*"). | * |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Since no annotations are present, the description carries the full burden. It discloses the heap warning and fielddata loading concerns for analyzed fields, but doesn't describe the return format or pagination behavior. Output schema covers return format, making this adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the core purpose, every sentence adds essential information with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the output schema exists and parameters are fully described, the description provides all necessary context: purpose, usage rules, and behavioral caveats, making it complete for effective tool use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage, baseline is 3. The description adds value by giving concrete field examples ('agent.name', 'rule.id') and usage advice, enhancing understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it's a 'frequency table for a keyword field' returning 'top N values with their document counts,' which precisely defines the tool's purpose and distinguishes it from siblings like opensearch_multi_terms and opensearch_search.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit when-to-use advice (keyword fields), a concrete fix for common issues ('append .keyword'), and a clear prohibition ('never use on analyzed text fields') with a reason, offering complete guidance for correct invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
opensearch_testA
Call first in every session to confirm connectivity and see the active backend.
Check the username field in the response to explain 403 errors on other tools —
it shows exactly which role is authenticated. Returns backend ("dashboards" or
"opensearch"), server version, URL, and username.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It describes return values (backend, version, URL, username) and how to interpret the username for error diagnosis. Could mention if it has side effects, but it's a simple test.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences with purpose front-loaded. Every sentence adds value: first states the primary action, second gives actionable diagnostic advice.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple test tool with no parameters and an output schema presumably documenting return fields, the description is complete. It covers purpose, usage order, and key output interpretation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters, so baseline 4. Description adds meaning by explaining the output fields and their use, which adds value beyond the empty schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool is for confirming connectivity and seeing the active backend. It uses specific verbs like 'call first' and explains the purpose, distinguishing it from data retrieval siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Call first in every session' and explains why, including debugging 403 errors. It lacks explicit when-not-to-use, but the context strongly implies it's the initial connectivity check.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
17 tool updates
v0.3.2- First observed
opensearch_api - First observed
opensearch_cluster_health - First observed
opensearch_compare - First observed
opensearch_count - First observed
opensearch_discover_fields - First observed
opensearch_explain - First observed
opensearch_get_mapping - First observed
opensearch_histogram - First observed
opensearch_index_settings - First observed
opensearch_list_index_patterns - First observed
opensearch_list_indices - First observed
opensearch_multi_terms - First observed
opensearch_ppl - First observed
opensearch_search - First observed
opensearch_stats - First observed
opensearch_terms - First observed
opensearch_test
TDQS
Scored across 17 tools
Each tool has a clearly distinct purpose: search, count, terms, histogram, stats, compare, explain, etc. No two tools overlap in functionality, and the descriptions make the differences explicit.
All tools share the uniform 'opensearch_' prefix, but the action part varies between nouns (e.g., opensearch_terms) and imperative verbs (e.g., opensearch_list_indices). This is minor inconsistency but not confusing.
With 17 tools, the server covers the full scope of OpenSearch read operations: connectivity, health, indices, mapping, search, aggregations, and specialized queries. The count feels right for the domain.
The tool set is comprehensive for read-only queries, including escape hatch for unmapped endpoints. Missing a dedicated get-document-by-ID tool is a minor gap, but search and explain cover it indirectly.
Maintenance
Related MCP Connectors
The Remote MCP server acts as a standardized bridge between LLM applications (like Claude, ChatGPT, and Cursor) and external services, enabling AI agents to access external tools and resources. Its primary capability is providing a centralized search tool to discover other MCP servers and their respective tools. Unlike local implementations, it runs remotely with OAuth authentication and permission controls for security.
The HubSpot MCP Server acts as a bridge that enables AI assistants and Large Language Models to securely interact with HubSpot CRM data through natural conversation, without requiring users to understand complex API structures. It provides read-only access to standard CRM objects (contacts, companies, deals, tickets, products, invoices, and more) and their associations, secured via OAuth 2.0, allowing AI agents to perform tasks like summarizing deals, fetching company updates, and looking up record changes.
MCP server for building and testing AI agents with multi-model experimentation and insights.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Related MCP Servers
- AlicenseAqualityAmaintenanceMCP server for OpenSearch that enables AI assistants to interact with OpenSearch clusters through a standardized interface for search, index management, and cluster operations.977,891 PyPI151Apache 2.0
- AlicenseAqualityDmaintenanceA read-only MCP server that gives AI assistants natural language access to Elasticsearch/Kibana logs for querying and analysis.71MIT
- AlicenseAqualityDmaintenanceRead-only MCP server for exploring and searching OpenSearch clusters, enabling log analysis, index exploration, and query execution.8MIT
- AlicenseBqualityBmaintenanceA read-only MCP server for investigating Amazon OpenSearch Service domains using natural language, with tools for cluster health, index management, search, and diagnostics, secured by allowed profiles and regions.20MIT