Query Splunk in natural language using Claude AI and the Splunk MCP Server.
Works with Splunk Enterprise and Splunk Cloud.
$ python splunk_mcp_client.py --interactive
Connecting to https://your-splunk-host:8089/services/mcp ...
Connected: Splunk_MCP_Server 1.0.3 - 13 tools
Knowledge file loaded: splunk_knowledge.json (generated 0d ago)
splunk> how many bytes did user@company.com send to github.com in the last 24 hours?
>> splunk_run_query({"query": "index=proxy sourcetype=zscaler-web ... | stats sum(bytes) as total_bytes by user"})
user@company.com sent 1.2 MB to github.com in the last 24 hours.
- Python 3.8+ (stdlib only - no pip installs)
- Splunk Enterprise or Splunk Cloud with the MCP Server app (v1.0+) installed
- A valid MCP token created inside the MCP Server app
- An Anthropic API key
| URL | Port | Notes | |
|---|---|---|---|
| Primary | https://<host>:8089/services/mcp |
8089 | Direct REST API access |
| Fallback | https://<host>/en-US/splunkd/__raw/services/mcp |
443 | Through web interface - no special port needed |
Use primary (8089) if: your machine has direct access to the Splunk management port.
Use fallback (443) if: port 8089 is blocked, you're on a corporate network, or you're on Splunk Cloud without IP allowlisting.
Splunk Cloud note: Port 8089 requires your source IP to be allowlisted via a Splunk support ticket. The fallback (443) bypasses this requirement entirely.
# Check which port is reachable
# Linux / macOS
nc -zv your-splunk-host 8089
# Windows PowerShell
Test-NetConnection -ComputerName your-splunk-host -Port 8089git clone https://github.com/mthcht/Splunk-MCP-Client.git
cd splunk-mcp-client# Linux / macOS
cp .env.example .env
chmod 600 .env
nano .env
# Windows (PowerShell)
Copy-Item .env.example .env
notepad .envFill in your credentials:
SPLUNK_MCP_TOKEN=your_splunk_mcp_token_here
ANTHROPIC_API_KEY=sk-ant-your_key_here
# Primary endpoint (port 8089)
SPLUNK_MCP_URL=https://your-host:8089/services/mcp
# Fallback endpoint (port 443) - uncomment if 8089 is blocked
# SPLUNK_MCP_URL=https://your-host/en-US/splunkd/__raw/services/mcpOr run the interactive setup wizard:
python setup.pyWhere to get the Splunk MCP token: Open the Splunk MCP Server app inside Splunk → click Generate Token. Do not use tokens from Settings → Tokens - they will not work.
The knowledge file gives Claude accurate context about your Splunk environment - which indexes exist, what sourcetypes they contain, and what fields are available. Without it, Claude has to guess.
See the Knowledge file section below for full options.
Quick start - if you already have a lookup built by a scheduled search:
spl scheduled search I use:
| rest /services/data/indexes count=0 splunk_server=local
| fields title
| rename title AS index
| where NOT match(index, "^_")
| map maxsearches=150 search="
| metadata type=sourcetypes index=$index$
| eval index=\"$index$\"
| fields index, sourcetype, recentTime
"
| where isnotnull(sourcetype) AND sourcetype!=""
| eval recentTime_str = strftime(recentTime, "%m/%d/%Y:%H:%M:%S")
| eval earliest_str = strftime(recentTime - 120, "%m/%d/%Y:%H:%M:%S")
| eval latest_str = strftime(recentTime + 180, "%m/%d/%Y:%H:%M:%S")
| map maxsearches=500 search="
search index=$index$ sourcetype=\"$sourcetype$\"
earliest=\"$earliest_str$\" latest=\"$latest_str$\"
| head 500
| fieldsummary maxvals=1
| where count > 0 AND NOT match(field, \"^_\")
| eval index=\"$index$\"
| eval sourcetype=\"$sourcetype$\"
| eval recentTime=\"$recentTime_str$\"
| fields index, sourcetype, recentTime, field, count, distinct_count, values
"
| table index, sourcetype, recentTime, field, count, distinct_count, values
| outputlookup splunk_knowledge_for_mcp.csv
get the knowledge:
python generate_knowledge.py --lookup splunk_knowledge_for_mcp.csv# Single query
python splunk_mcp_client.py "what indexes are available?"
# Interactive mode
python splunk_mcp_client.py --interactiveusage: splunk_mcp_client.py [-h] [--interactive] [--debug] [--env ENV]
[--url URL] [--knowledge K] [--no-knowledge] [query]
positional arguments:
query Natural language query
options:
-h, --help show this help message and exit
--interactive, -i Interactive REPL mode
--debug, -d Show MCP/HTTP debug output
--env ENV Path to .env file (default: next to the script)
--url URL Override SPLUNK_MCP_URL from .env
--knowledge K, -k K Path to splunk_knowledge.json (default: next to the script)
--no-knowledge Run without loading the knowledge file
python splunk_mcp_client.py "how many events were indexed today?"
python splunk_mcp_client.py "show top 10 hosts by event count in the last 24h"
python splunk_mcp_client.py "list all Windows failed logins in the last hour"python splunk_mcp_client.py --interactive
splunk> show me all error events from the last hour
splunk> which sourcetypes have the most volume this week?
splunk> how many bytes did user@company.com send to external IPs yesterday?
splunk> exitpython splunk_mcp_client.py --env /path/to/.env "show failed logins"python splunk_mcp_client.py --url "https://your-host/en-US/splunkd/__raw/services/mcp" "show indexes"python splunk_mcp_client.py --debug "what indexes exist?"
# Prints every MCP request/response, SSE event, and Anthropic API callThe knowledge file (splunk_knowledge.json) is a compact inventory of your Splunk environment - indexes, sourcetypes, and key fields with sample values. Claude reads it at startup to write accurate SPL without guessing field names or searching the wrong index.
Run generate_knowledge.py with no arguments. It queries Splunk directly via MCP - no lookup or scheduled search needed:
python generate_knowledge.pyThis runs the following discovery search through MCP:
| rest /services/data/indexes count=0 splunk_server=local
| fields title
| rename title AS index
| where NOT match(index, "^_")
| map maxsearches=150 search="
| metadata type=sourcetypes index=$index$
| eval index=\"$index$\"
| fields index, sourcetype, recentTime
"
| where isnotnull(sourcetype) AND sourcetype!=""
| eval recentTime_str = strftime(recentTime, "%m/%d/%Y:%H:%M:%S")
| eval earliest_str = strftime(recentTime - 120, "%m/%d/%Y:%H:%M:%S")
| eval latest_str = strftime(recentTime + 180, "%m/%d/%Y:%H:%M:%S")
| map maxsearches=500 search="
search index=$index$ sourcetype=\"$sourcetype$\"
earliest=\"$earliest_str$\" latest=\"$latest_str$\"
| head 500
| fieldsummary maxvals=1
| where count > 0 AND NOT match(field, \"^_\")
| eval index=\"$index$\"
| eval sourcetype=\"$sourcetype$\"
| eval recentTime=\"$recentTime_str$\"
| fields index, sourcetype, recentTime, field, count, distinct_count, values
"
| table index, sourcetype, recentTime, field, count, distinct_count, values
Each sourcetype's fieldsummary runs on a 5-minute window anchored on its most recent event - no full scans, no timeouts. For large environments (50+ indexes) this can take a few minutes. Increase the timeout if needed:
python generate_knowledge.py --timeout 1200For faster, repeatable runs, save the SPL above as a scheduled report in Splunk (daily or weekly) with | outputlookup your_lookup_name.csv appended. Then fetch it with:
# Single lookup
python generate_knowledge.py --lookup your_lookup_name.csv
# Multiple lookups merged (e.g. one per team or data domain)
python generate_knowledge.py --lookups soc.csv edr.csv cloud.csvThis fetches the pre-built lookup via MCP and runs in seconds regardless of environment size.
python generate_knowledge.py # auto-discover
python generate_knowledge.py --lookup my_lookup.csv # single lookup
python generate_knowledge.py --lookups a.csv b.csv # merge multiple lookups
python generate_knowledge.py --timeout 1200 # longer timeout for auto-discover
python generate_knowledge.py --output /path/to/out.json # custom output path
python generate_knowledge.py --debug # show raw MCP responses
Your Splunk admin needs to:
- Install the MCP Server app (v1.0+)
- Create a role with
mcp_tool_executecapability:# authorize.conf [role_mcp_user] mcp_tool_execute = enabled
- Assign your Splunk user to that role
- Generate a token inside the MCP Server app (not from Settings → Tokens)
Splunk Cloud only: Port 8089 requires your source IP to be allowlisted. Open a support ticket with Splunk to request this, or use the fallback (port 443) endpoint.
| File | Description |
|---|---|
splunk_mcp_client.py |
Main CLI tool - natural language → SPL → results |
generate_knowledge.py |
Builds splunk_knowledge.json from a Splunk lookup or via auto-discovery |
splunk_knowledge_scheduled_search.spl |
SPL to paste into Splunk as a scheduled search - builds the knowledge lookup |
setup.py |
Interactive .env setup wizard |
.env.example |
Credential template |
splunk_knowledge.json |
Generated knowledge file (gitignored) |
- Never commit
.env- it is in.gitignorealready - Linux: keep
.envatchmod 600(owner read/write only) - Windows: store
.envoutside the repo or restrict access via file properties - Tokens: Splunk MCP tokens use public-key encryption and cannot be reused outside the MCP context
- SSL: Certificate verification is disabled by default to handle self-signed and corporate CA certificates
To enable strict SSL verification, edit make_ssl() in splunk_mcp_client.py:
def make_ssl():
ctx = ssl.create_default_context()
# Remove the two lines below to enable verification:
# ctx.check_hostname = False
# ctx.verify_mode = ssl.CERT_NONE
return ctxTo use a custom CA bundle (corporate PKI or private CA):
def make_ssl():
return ssl.create_default_context(cafile="/path/to/ca-bundle.pem")| Variable | Required | Description |
|---|---|---|
SPLUNK_MCP_TOKEN |
✅ | Encrypted token from the Splunk MCP Server app |
ANTHROPIC_API_KEY |
✅ | API key from console.anthropic.com |
SPLUNK_MCP_URL |
✅ | Full MCP endpoint URL - primary (8089) or fallback (443) |
| Error | Cause | Fix |
|---|---|---|
Connection failed: HTTP 405 |
Wrong HTTP method | Update to the latest version of this script |
Connection failed: HTTP 401 |
Bad or expired token | Regenerate the token from the MCP Server app |
Connection failed: HTTP 403 |
Missing role or IP not allowlisted | Check user role has mcp_tool_execute; on Splunk Cloud use the fallback (443) |
Connection failed: timed out |
Port 8089 blocked | Switch to the fallback endpoint (443) |
SPLUNK_MCP_URL not set |
Missing from .env |
Add SPLUNK_MCP_URL=https://... to your .env |
.env file not found |
Wrong path | Use --env /full/path/to/.env |
SPLUNK_MCP_TOKEN not found |
Key name mismatch | Key must be named exactly SPLUNK_MCP_TOKEN |
Lookup returned empty |
Wrong lookup name or app scope | Verify name in Settings → Lookups; try --debug |
Anthropic 429 rate limit |
System prompt too large | Rebuild knowledge file - generate_knowledge.py auto-limits token usage |
MIT