Log Intelligence MCP

Log Intelligence MCP

MCP server for semantic log ingestion, hybrid retrieval, and cleanup, enabling natural-language querying of log files with dense+BM25 retrieval and full provenance.

Category
Visit Server

README

Log Intelligence MCP

Semantic log ingestion, hybrid retrieval, and cleanup for the Rapid7 SI Triage Automation POC. This is the "Application Logs MCP" in the architecture diagram: it turns raw log files (downloaded from Jira tickets by the companion Jira/Confluence MCP) into a queryable vector index, and serves the most relevant log chunks back to the triage agent during defect analysis.


What it does

  1. Ingest — reads raw log files for a ticket, parses them into logical entries (a header line plus its stack-trace/continuation lines), groups them into semantic, token-budgeted chunks, embeds each chunk, and stores the vectors in a per-ticket collection.
  2. Query — given a natural-language question, runs hybrid retrieval (dense vector similarity + BM25 keyword matching, fused with Reciprocal Rank Fusion) and returns the top-k chunks with full provenance (source file, line range, time span, log levels, trace ids).
  3. Stats — cheap aggregate view of a ticket's logs (level histogram, error count, time span, distinct trace ids).
  4. Delete — after the defect pipeline finishes, removes the ticket's vectors and the raw local log files, freeing disk and clearing stale data.

Tools

Tool Purpose
ingest_ticket_logs(ticket_id, paths?) Parse → chunk → embed → store all logs for a ticket. Reads from the shared logs/<ticket_id>/ dir by default, or an explicit paths list.
query_logs(ticket_id, query, top_k=5) Hybrid semantic + keyword retrieval of the most relevant chunks.
get_log_stats(ticket_id) Ingestion manifest + stored-chunk count + entry summary.
delete_ticket_logs(ticket_id, delete_raw=true) Remove vectors and (optionally) raw files. Cleanup step.

The chunking strategy (why it's built this way)

Chunk quality decides retrieval quality, so the chunker is the heart of this MCP.

  • Entry-aware. Logs are first assembled into entries: a timestamped header plus every continuation line (\tat …, Caused by:, … N more, wrapped messages). An entry is atomic — it is never split across chunks, which is what guarantees a stack trace always travels with the ERROR line that produced it.
  • Token-budgeted for Claude. Chunks target ~1000 tokens and are capped at 1600 (CHUNK_*_TOKENS). Large enough to hold a full error + stack trace + surrounding context; small enough that top-k results stay focused and the agent's Phase-1 prompt stays bounded.
  • Semantically grouped. Packing prefers to break at natural boundaries — a new trace/correlation id, or a fresh ERROR — so related lines for one request land in the same chunk.
  • Overlap without cutting. Each chunk is seeded with the trailing whole entries of the previous chunk (~150 tokens) so context isn't lost at boundaries, but entries are never sliced mid-way.
  • Oversized entries. A single entry larger than the hard max (e.g. a giant stack trace) is emitted whole and flagged oversized rather than truncated.

Token counting uses a fast, conservative character-based estimate (logs are punctuation-heavy, so this slightly over-estimates and keeps chunks safely under budget). Set USE_ANTHROPIC_TOKENIZER=1 to use exact Claude token counts when network is available.

Hybrid retrieval

Dense and sparse retrieval catch different things: embeddings capture semantic similarity ("payment failed" ≈ "authorization error"), while BM25 nails exact identifiers (TokenVaultException, a trace id, a filename). We run both and fuse their rankings with Reciprocal Rank Fusion:

rrf_score(d) = Σ_retriever  weight / (RRF_K + rank_retriever(d))

RRF fuses ranks rather than raw scores, so the two different score scales don't need fragile normalisation. Tunables: RRF_K (default 60), DENSE_WEIGHT, SPARSE_WEIGHT, CANDIDATE_POOL, DEFAULT_TOP_K.


Backends (production vs. offline)

Every heavy dependency sits behind an adapter with a real pure-Python fallback, so the whole pipeline runs and is testable with no network, and flips to the production backend by changing one env var.

Concern Production (default when installed) Offline fallback (real, not mock)
Embeddings sentence-transformers all-mpnet-base-v2 (768-dim) Deterministic hashed n-gram TF-IDF on numpy
Vector store Chroma (persistent) Per-ticket numpy .npz + JSON, real cosine search
Sparse Pure-Python BM25 (always) same
Token count Anthropic exact counter (optional) character estimate

EMBED_BACKEND=auto uses sentence-transformers if importable, else the hashing embedder. VECTOR_BACKEND=auto uses Chroma if importable, else the numpy store. Force a backend with EMBED_BACKEND=sentence-transformers|bedrock|hashing and VECTOR_BACKEND=chroma|numpy.

The offline fallbacks are genuine implementations (real vectors, real persistence, real similarity search) — they exist so the POC runs anywhere, not to fake results.


Install & run

cd log-intelligence-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e .            # installs mcp, chromadb, sentence-transformers, numpy, uvicorn
cp .env.example .env        # adjust if needed

# stdio (for a local MCP client / Claude Desktop):
python -m log_intelligence_mcp --transport stdio

# HTTP (streamable-http, served at http://127.0.0.1:8081/mcp):
python -m log_intelligence_mcp --transport http

The first sentence-transformers run downloads the model (needs network once). With no network / no heavy deps installed, it automatically uses the offline fallbacks — the server still starts and every tool works.

Register with an MCP client (stdio example)

{
  "mcpServers": {
    "log-intelligence": {
      "command": "python",
      "args": ["-m", "log_intelligence_mcp", "--transport", "stdio"],
      "env": { "SI_DATA_DIR": "/absolute/path/to/si_data" }
    }
  }
}

How it coordinates with the Jira/Confluence MCP

Both servers share one directory tree, SI_DATA_DIR (default ./si_data) — set it to the same absolute path for both.

si_data/
  logs/<ticket_id>/…      # written by the Jira MCP, read by this MCP
  vector_store/           # owned by this MCP
  meta/<ticket_id>.json   # ingestion manifest written by this MCP

Typical flow: Jira MCP get_ticket downloads log attachments into logs/<ticket_id>/ → this MCP ingest_ticket_logs(ticket_id) indexes them → agent calls query_logs(...) during analysis → delete_ticket_logs(ticket_id) cleans up at the end.


Tests

pytest                      # in the POC environment (needs `pip install pytest`)
python tests/_runner.py     # offline harness used when pytest isn't installed

The suite covers entry assembly, the chunker invariants (no split entry, token budget respected, stack trace kept whole, overlap present, every line covered, oversized handling), BM25, hashed embeddings, the numpy store round-trip, hybrid fusion, and a full ingest → query → stats → delete end-to-end. 20 tests, all offline.

Configuration reference

See .env.example for every variable. Key ones: SI_DATA_DIR, CHUNK_TARGET_TOKENS/CHUNK_MAX_TOKENS/CHUNK_MIN_TOKENS/CHUNK_OVERLAP_TOKENS, EMBED_BACKEND/EMBED_MODEL, VECTOR_BACKEND, RRF_K/DENSE_WEIGHT/SPARSE_WEIGHT, DEFAULT_TOP_K, MCP_HTTP_HOST/MCP_HTTP_PORT (default 8081), LOG_LEVEL/LOG_JSON.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured