signalsleuth
README.md
# SignalSleuth
**Agentic RAG + MCP copilot for cellular (4G/5G) modem log triage.**
SignalSleuth reads modem logs, detects known fault signatures (radio link failure, handover failure,
attach reject, RRC setup timeout, auth failure, modem crash), retrieves matching troubleshooting
knowledge with hybrid search, and produces an evidence-backed report with log line citations.
Everything is exposed as tools through an **MCP server** so Claude Desktop, Claude Code or any MCP
client can investigate logs interactively.
## Highlights
- **C++17 parser** (`logparse`) for fast log ingestion, with a byte-for-byte equivalent Python fallback and a parity test.
- **Deterministic signatures + LLM agent**: rules give reproducible findings; the LLM agent explains and prioritises via tool calling.
- **Hybrid RAG**: BM25 + vector similarity fused with Reciprocal Rank Fusion, pluggable `Embedder`.
- **MCP server** with 5 tools and a prompt template.
- **Responsible data handling**: IMSI/IMEI/ICCID/IP/phone redaction at every boundary, path allowlist, the LLM cannot choose file paths, logs treated as untrusted input.
- **Observability**: JSONL span tracing for every tool call and agent step.
- **Evaluation gate**: precision/recall, retrieval hit@k, redaction leaks, parser parity, enforced in CI.
## Quickstart
```bash
git clone https://github.com/<you>/signalsleuth && cd signalsleuth
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]" # add ,llm for the LLM agent
make build # builds and tests the C++ parser (needs cmake + a C++17 compiler)
signalsleuth triage data/sample_logs/mixed_incident.log
signalsleuth search "T310 expired"
signalsleuth eval
pytest -q
```
The Python fallback parser is used automatically if the C++ binary is not built.
## Use it from an MCP client
```bash
signalsleuth serve
```
Add to Claude Desktop config (see `mcp_config.example.json`):
```json
{ "mcpServers": { "signalsleuth": { "command": "signalsleuth", "args": ["serve"],
"env": { "SIGNALSLEUTH_LOG_DIRS": "/absolute/path/to/your/logs" } } } }
```
Then ask: *"Triage data/sample_logs/handover_failure.log and tell me the likely root cause."*
| Tool | Purpose |
|---|---|
| `summarize_log` | Counts by level/layer, time span, first error |
| `find_anomalies` | Fault signatures with line-numbered evidence |
| `get_log_window` | Context around a line |
| `search_knowledge` | Hybrid retrieval over troubleshooting notes |
| `triage_log` | One-shot Markdown report |
## LLM agent (optional)
```bash
export ANTHROPIC_API_KEY=...
signalsleuth triage data/sample_logs/mixed_incident.log --llm
```
The agent runs a tool-use loop (max 8 steps), and every tool result is redacted before the model sees it.
## Project layout
```
signalsleuth/
├── cpp/ C++17 log parser (library, CLI, unit tests, CMake)
├── src/signalsleuth/
│ ├── parser.py C++ binary wrapper + Python fallback
│ ├── signatures.py fault detectors
│ ├── retrieval.py BM25 + vector + RRF
│ ├── redact.py PII redaction
│ ├── tracing.py JSONL spans
│ ├── tools.py shared tool layer (allowlist, redaction, tracing)
│ ├── agent.py deterministic agent
│ ├── llm_agent.py Anthropic tool-use agent
│ ├── mcp_server.py MCP server
│ ├── evaluation.py eval harness
│ └── cli.py
├── data/sample_logs/ synthetic logs
├── data/knowledge/ troubleshooting notes (original, cites 3GPP specs for normative text)
├── evals/ labelled cases
├── tests/ 30 tests
├── docs/ architecture + resume material
└── .github/workflows/ci.yml
```
## Limitations
- Logs and knowledge notes are synthetic/hand-written; the log format is a simple text format, not a vendor binary format.
- The eval set is small, so use it as a regression gate rather than a benchmark.
- The default "embeddings" are hashed character trigrams. Swap in a neural embedder via the `Embedder` protocol.
## License
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues