Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
*.so
*.dylib

# Binary names (specific files in root only)
/splunk
/splunk-cli

# Test binary, built with `go test -c`
*.test

Expand Down
248 changes: 246 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,246 @@
# splunk-cli
Splunk CLI
# Splunk CLI & MCP Server

A Splunk CLI and MCP server that allows you and your coding agents to interact with Splunk. Inspired by the GitHub CLI and following the same concept as jira-cli, it aims to provide a simple and efficient way for humans and agents to interact with Splunk from the command line.

Being both a CLI and an MCP server means you get the best of both worlds. Agents can be directed to perform specific commands (e.g., `Run a search for errors in the last hour by running splunk search 'error' '-1h' 'now'`), or they can use the MCP server to interact with Splunk directly.

Like `jq`, it is a single tiny binary, without the overhead of installing a Node runtime, and without the need to put your Splunk token in plain text file (it uses the system key-ring).

## Installation

### Supported Platforms

Binaries are available for:
- **Linux**: amd64, arm64
- **macOS**: amd64 (Intel), arm64 (Apple Silicon)
- **Windows**: amd64

### Download and Install

Download the binary for your platform from the [release page](https://github.com/kitproj/splunk-cli/releases).

#### Linux

**For Linux (amd64):**
```bash
sudo curl -fsL -o /usr/local/bin/splunk https://github.com/kitproj/splunk-cli/releases/download/v0.0.1/splunk_v0.0.1_linux_amd64
sudo chmod +x /usr/local/bin/splunk
```

**For Linux (arm64):**
```bash
sudo curl -fsL -o /usr/local/bin/splunk https://github.com/kitproj/splunk-cli/releases/download/v0.0.1/splunk_v0.0.1_linux_arm64
sudo chmod +x /usr/local/bin/splunk
```

#### macOS

**For macOS (Apple Silicon/arm64):**
```bash
sudo curl -fsL -o /usr/local/bin/splunk https://github.com/kitproj/splunk-cli/releases/download/v0.0.1/splunk_v0.0.1_darwin_arm64
sudo chmod +x /usr/local/bin/splunk
```

**For macOS (Intel/amd64):**
```bash
sudo curl -fsL -o /usr/local/bin/splunk https://github.com/kitproj/splunk-cli/releases/download/v0.0.1/splunk_v0.0.1_darwin_amd64
sudo chmod +x /usr/local/bin/splunk
```

#### Verify Installation

After installing, verify the installation works:
```bash
splunk -h
```

## Usage

### Configuration

#### Getting a Splunk API Token

Before configuring, you'll need to create a Splunk authentication token:

1. Log in to your Splunk instance: `https://your-splunk-host:8000`
2. Go to Settings > Tokens
3. Click "New Token" or "Enable Token Authentication" if not already enabled
4. Generate and copy the token (you won't be able to see it again)

#### Configure the CLI

The `splunk` CLI can be configured in two ways:

1. **Using the configure command (recommended, secure)**:
```bash
echo "your-api-token" | splunk configure your-splunk-host
```
This stores the host in `~/.config/splunk-cli/config.json` and the token securely in your system's keyring.

2. **Using environment variables**:
```bash
export SPLUNK_HOST=your-splunk-host
export SPLUNK_TOKEN=your-api-token
```
Note: The SPLUNK_TOKEN environment variable is still supported for backward compatibility, but using the keyring (via `splunk configure`) is more secure on multi-user systems.

## Usage

### Direct CLI Usage

```bash
Usage:
splunk configure <host> - Configure Splunk host and token (reads token from stdin)
splunk search <query> [earliest-time] [latest-time] - Run a Splunk search query
splunk list-saved-searches - List all saved searches
Comment thread
alexec marked this conversation as resolved.
Outdated
splunk create-saved-search <name> <query> [description] - Create a saved search
splunk list-alerts - List scheduled alerts
Comment thread
alexec marked this conversation as resolved.
Outdated
splunk server-info - Get Splunk server information
Comment thread
alexec marked this conversation as resolved.
Outdated
splunk send-event <index> <source> <sourcetype> <json-event> - Send an event to Splunk
splunk mcp-server - Start MCP server (stdio transport)
```

#### Examples

**Run a search:**
```bash
splunk search "error" "-1h" "now"
# Search for "error" in the last hour

splunk search "index=main sourcetype=access_combined | stats count by status"
# Search with SPL query
```

**List saved searches:**
```bash
splunk list-saved-searches
```

**Create a saved search:**
```bash
splunk create-saved-search "Error Monitor" "search index=main error" "Monitor for errors"
```

**List scheduled alerts:**
```bash
splunk list-alerts
```

**Get server information:**
```bash
splunk server-info
```

**Send an event:**
```bash
splunk send-event main app json '{"message": "Test event", "level": "info"}'
```

### MCP Server Mode

The MCP (Model Context Protocol) server allows AI assistants and other tools to interact with Splunk through a standardized JSON-RPC protocol over stdio. This enables seamless integration with AI coding assistants and other automation tools.

Learn more about MCP: https://modelcontextprotocol.io

**Setup:**

1. First, configure your Splunk host and token (stored securely in the system keyring):
```bash
echo "your-api-token" | splunk configure your-splunk-host
```

2. Add the MCP server configuration to your MCP client (e.g., Claude Desktop, Cline):
```json
{
"mcpServers": {
"splunk": {
"command": "splunk",
"args": ["mcp-server"]
}
}
}
```

For **Claude Desktop**, add this to:
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

The server exposes the following tools:
- `search` - Run a Splunk search query and return results
- `list_saved_searches` - List all saved searches in Splunk
- `create_saved_search` - Create a new saved search
- `list_alerts` - List all scheduled alerts
- `server_info` - Get Splunk server information
- `send_event` - Send an event to Splunk via HTTP Event Collector

**Example usage from an AI assistant:**
> "Search Splunk for errors in the main index in the last hour and show me the top 10 results."

## Development

### Built With

This CLI uses the following Go libraries:
- **[github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go)** - Model Context Protocol server library
- **[github.com/zalando/go-keyring](https://github.com/zalando/go-keyring)** - Cross-platform keyring library for secure token storage

The Splunk API client is a custom implementation using the Splunk REST API, as there is no official Go SDK for Splunk Enterprise.

### Building from Source

```bash
# Clone the repository
git clone https://github.com/kitproj/splunk-cli.git
cd splunk-cli

# Build the binary
go build -o splunk

# Run tests
go test ./...
```

### Project Structure

```
splunk-cli/
├── internal/
│ ├── config/ # Configuration management (host, token storage)
│ └── splunk/ # Splunk REST API client
├── main.go # CLI entry point and command handlers
├── mcp.go # MCP server implementation
├── mcp_test.go # MCP server tests
└── README.md # This file
```

## Troubleshooting

### Common Issues

**"Splunk host must be configured" error**
- Make sure you've run `splunk configure <host>` or set the `SPLUNK_HOST` environment variable
- Check that the config file exists: `cat ~/.config/splunk-cli/config.json`

**"Failed to execute request" or authentication errors**
- Verify your API token is still valid (tokens can expire)
- Re-run the configure command to update the token: `echo "new-token" | splunk configure your-splunk-host`
- Make sure your Splunk user has permission to access the requested resources

**Keyring issues on Linux**
- Some Linux systems may not have a keyring service installed
- Install `gnome-keyring` or `kwallet` for your desktop environment
- Alternatively, use environment variables: `export SPLUNK_TOKEN=your-token`

**MCP server not appearing in Claude Desktop**
- Restart Claude Desktop after editing the config file
- Check the config file syntax is valid JSON
- Verify the `splunk` binary is in your PATH: `which splunk`

### Getting Help

- Report issues: https://github.com/kitproj/splunk-cli/issues
- Check existing issues for solutions and workarounds

## License

This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
25 changes: 25 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module github.com/kitproj/splunk-cli

go 1.24.10

require (
github.com/mark3labs/mcp-go v0.43.0
github.com/zalando/go-keyring v0.2.6
golang.org/x/term v0.37.0
)

require (
al.essio.dev/pkg/shellescape v1.5.1 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/danieljoos/wincred v1.2.2 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/invopop/jsonschema v0.13.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
golang.org/x/sys v0.38.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
55 changes: 55 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho=
al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0=
github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mark3labs/mcp-go v0.43.0 h1:lgiKcWMddh4sngbU+hoWOZ9iAe/qp/m851RQpj3Y7jA=
github.com/mark3labs/mcp-go v0.43.0/go.mod h1:YnJfOL382MIWDx1kMY+2zsRHU/q78dBg9aFb8W6Thdw=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s=
github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU=
golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading