Skip to content

mthcht/Splunk-MCP-Client

Repository files navigation

splunk-mcp-client

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.

Requirements

  • 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

Which endpoint should I use?

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 8089

Setup

1. Clone the repo

git clone https://github.com/mthcht/Splunk-MCP-Client.git
cd splunk-mcp-client

2. Create your .env file

# Linux / macOS
cp .env.example .env
chmod 600 .env
nano .env

# Windows (PowerShell)
Copy-Item .env.example .env
notepad .env

Fill 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/mcp

Or run the interactive setup wizard:

python setup.py

Where 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.

3. (Recommended) Build the knowledge file

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

4. Run

# Single query
python splunk_mcp_client.py "what indexes are available?"

# Interactive mode
python splunk_mcp_client.py --interactive

Usage

usage: 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

Single query

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"

Interactive mode

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> exit

Custom .env path

python splunk_mcp_client.py --env /path/to/.env "show failed logins"

Override the URL on the fly

python splunk_mcp_client.py --url "https://your-host/en-US/splunkd/__raw/services/mcp" "show indexes"

Debug mode

python splunk_mcp_client.py --debug "what indexes exist?"
# Prints every MCP request/response, SSE event, and Anthropic API call

Knowledge file

The 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.

Option A - Auto-discover (no setup required)

Run generate_knowledge.py with no arguments. It queries Splunk directly via MCP - no lookup or scheduled search needed:

python generate_knowledge.py

This 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 1200

Option B - Pre-built lookup (recommended for large or shared environments)

For 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.csv

This fetches the pre-built lookup via MCP and runs in seconds regardless of environment size.

All options

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

Splunk prerequisites

Your Splunk admin needs to:

  1. Install the MCP Server app (v1.0+)
  2. Create a role with mcp_tool_execute capability:
    # authorize.conf
    [role_mcp_user]
    mcp_tool_execute = enabled
  3. Assign your Splunk user to that role
  4. 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.


Files

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)

Security

  • Never commit .env - it is in .gitignore already
  • Linux: keep .env at chmod 600 (owner read/write only)
  • Windows: store .env outside 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

SSL notes

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 ctx

To use a custom CA bundle (corporate PKI or private CA):

def make_ssl():
    return ssl.create_default_context(cafile="/path/to/ca-bundle.pem")

.env reference

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)

Troubleshooting

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

License

MIT

About

Query Splunk in natural language using Claude AI and the Splunk MCP Server.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

 
 
 

Contributors

Languages