
EventWhisper
STDIOWindows Event Log MCP server for EVTX file analysis and filtering
Windows Event Log MCP server for EVTX file analysis and filtering
EventWhisper exposes fast, scriptable access to Windows .evtx
logs via an MCP (Model Context Protocol) server.
It’s pure Python (uses the evtx
library), instead of a PowerShell wrapper and does not execute commands on the host — safer for incident response, digital forensics, and threat hunting.
The server exposes two primary tools:
Built specifically for IR/DFIR & hunting so you don’t need to look up Event IDs all day. Designed, developed, and tested on Windows with Claude — and usable from any MCP client.
https://github.com/user-attachments/assets/e1878c86-56f6-466b-bbc4-04d1edeeb36b
EventWhisper can be set up with Poetry, whether you run it inside Claude or standalone.
On Windows, make sure Poetry is on your PATH
.
Install Poetry (PowerShell):
(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -
Add Poetry to PATH (user install):
C:\Users\<YourUser>\AppData\Roaming\Python\Scripts
Verify:
poetry --version
Primarily developed for use with Claude, but you can run the MCP server standalone and plug it into other LLMs.
Clone and install:
git clone https://github.com/hexastrike/eventwhisper cd eventwhisper poetry install
Run the MCP server:
poetry run python -m eventwhisper.mcp.server # (or) plain Python if deps are installed globally: python -m eventwhisper.mcp.server
Add this to Claude Desktop’s MCP config (e.g., %AppData%\Claude\claude_desktop_config.json
):
{ "mcpServers": { "EventWhisper": { "type": "stdio", "command": "poetry", "args": [ "-C", "C:\\Path\\To\\eventwhisper", "run", "python", "-m", "eventwhisper.mcp.server" ], "env": { "PYTHONIOENCODING": "utf-8" } } } }
Open Settings → Developer to confirm EventWhisper is registered and “running”.
When prompted, allow the tool:
Try a first prompt:
Use EventWhisper to list
.evtx
files inC:\Windows\System32\winevt\Logs
.
EventWhisper was written to be simple and maintainable. We use pytest for tests and ruff for linting/formatting. Run everything locally (or via pre-commit):
poetry install poetry run ruff format . poetry run ruff check . --fix poetry run pytest --cov=eventwhisper --cov-report=term-missing # pre-commit on all files: poetry run pre-commit run --all-files # pre-push hooks (full tests + coverage): poetry run pre-commit run --hook-stage push --all-files
When making pull requests, ensure all tests pass and coverage thresholds are met.
Every new utility or feature should include clear tests and follow PEP 8. Tests live in the tests/
directory.
Primary logic lives in eventwhisper/evtxio/evtxio.py
— EVTX iteration/filtering/projection.
The core server function is get_events_from_evtx()
(a wrapper around the iterator iter_events_from_evtx()
):
def get_events_from_evtx( provider: str | Path, start: datetime | str | None = None, end: datetime | str | None = None, results_limit: int | str | None = RESULTS_LIMIT, event_ids: int | str | Sequence[int] | Sequence[str] | None = None, contains: str | Sequence[str] | None = None, not_contains: str | Sequence[str] | None = None, fields: str | Sequence[str] | None = None, ) -> list[str]:
Constants live in eventwhisper/utils/config.py
and include both:
RESULTS_LIMIT
— max number of events returned (LLMs have token/char caps).SCAN_LIMIT
— max events scanned to keep responses fast on huge logs.# example.py from __future__ import annotations from datetime import datetime, timezone from eventwhisper.evtxio.evtxio import get_events_from_evtx # 1) First matching event from Security log print(get_events_from_evtx(r"C:\Windows\System32\winevt\Logs\Security.evtx", results_limit=1)) # 2) Filter by keywords and project fields events = get_events_from_evtx( r"C:\Windows\System32\winevt\Logs\Security.evtx", contains=["powershell", "Invoke-"], fields=["Event.System.EventID", "Event.EventData.Image", "Event.EventData.CommandLine"], results_limit=5, ) for e in events: print(e) # 3) Time-bounded query (UTC) start = datetime(2025, 1, 1, tzinfo=timezone.utc) end = datetime(2025, 1, 31, 23, 59, 59, tzinfo=timezone.utc) print(len(get_events_from_evtx(r"C:\Windows\System32\winevt\Logs\Security.evtx", start=start, end=end)))
Run it with poetry run python example.py
.
RESULTS_LIMIT
and scanning is bounded to keep responses fast. If your MCP client doesn’t realize results are capped, run a second, narrower query..evtx
from the Internet, right-click → Properties → Unblock.r"C:\path\file.evtx"
.<video>
; use a thumbnail → MP4 link (see Demo section)..evtx
filesDistributed under the GPLv3. See LICENSE.