Skip to main content

Investigation MCP Server

CI License: MIT Python 3.13+ Read-only MCP

A FastMCP server exposing safe, read-only tools for investigating support tickets across PostgreSQL, AWS CloudWatch, and New Relic.

Overview

When a support ticket comes in ("checkout failed for user 4417 around 14:30"), answering it usually means opening a DB client, the AWS Console, and a logging platform, hand-writing a query in each, then manually cross-referencing timestamps and ids across all three. This server turns that into a conversation with an MCP client.

Features include:

  • 🐘 PostgreSQL — schema discovery, validated read-only SELECT execution, PII-masked sample rows, and catalog-driven identifier/store lookup (no hardcoded table list).
  • ☁️ AWS CloudWatch — log group discovery, Logs Insights queries (cost-capped by bytes scanned), pattern-based log filtering, and metric statistics.
  • 🟢 New Relic — event type and log field discovery (keyset()), correlation-id detection, and validated NRQL execution.
  • 🛡️ Guardrails, not trust — every query is AST-parsed (SQL) or pattern-validated (NRQL/CloudWatch) before it touches the network; results are PII-redacted before they're returned.

The server does not generate queries itself. The client model (Claude Desktop, Cursor) writes the query, using schema/field-discovery tools and a curated query cookbook this server exposes as grounding context — the server's job is to make sure the model has enough context to write a correct query, and to validate + execute whatever it writes safely. See docs/design.md (§3.1) for the full rationale.

Cross-source correlation — matching a request_id/order_id across the DB and both log sources — is currently done by the client model itself; there's no composite "investigate this ticket end-to-end" tool yet (see docs/design.md §4.5 for what's not implemented).

Architecture

Architecture: MCP client to Investigation MCP Server, fanning out to PostgreSQL, AWS CloudWatch, and New Relic

Quick Start

Fastest: run the published package with uvx

No clone, no Docker, no port. Install uv, then add this to your MCP client config (Claude Desktop claude_desktop_config.json, Cursor .cursor/mcp.json). The client launches the server itself over stdio, and uvx downloads and caches the package on first run:

{
  "mcpServers": {
    "investigation": {
      "command": "uvx",
      "args": ["opsinsight-mcp"],
      "env": {
        "DB_URL": "postgresql+asyncpg://readonly_user:pass@host:5432/dbname",
        "CLOUDWATCH_REGION": "ap-south-1",
        "CLOUDWATCH_ACCESS_KEY_ID": "...",
        "CLOUDWATCH_SECRET_ACCESS_KEY": "...",
        "CLOUDWATCH_ALLOWED_LOG_GROUP": "/app/prod",
        "NEW_RELIC_API_KEY": "NRAK-...",
        "NEW_RELIC_ACCOUNT_ID": "..."
      }
    }
  }
}

Claude Code: claude mcp add -e DB_URL=... investigation -- uvx opsinsight-mcp.

Only set the variables for the sources you use (see What each source needs). In this mode there is no .env file — the env block is the configuration. To run an unreleased version straight from GitHub, use "args": ["--from", "git+https://github.com/Vignesh-2552/mcp-log-db-investigator", "opsinsight-mcp"].

Prerequisites (running from source)

  • Python 3.11+
  • uv
  • Access credentials for whichever source(s) you want to use — see What each source needs below. You don't need all three; a source you skip just errors at call time instead of blocking startup.

Installation

uv sync
copy .env.example .env
# edit .env — fill in DB_URL and/or the CloudWatch/New Relic blocks you need
uv run investigation-server

The server starts on http://127.0.0.1:8001/mcp by default (streamable HTTP transport; change it with SERVER_PORT). It has no built-in HTTP authentication, so only set SERVER_HOST to a non-loopback address when access is protected by an authenticated proxy or equivalent network control.

Docker

For a long-running HTTP server (shared by a team, or on a server host), run the image published to GHCR on every merge to main:

docker run --rm -p 127.0.0.1:8000:8000 --env-file .env -e SERVER_HOST=0.0.0.0 -e SERVER_PORT=8000 ghcr.io/vignesh-2552/mcp-log-db-investigator:latest

Then point the client at http://localhost:8000/mcp. To build the image yourself instead: docker build -t investigation-mcp . and use investigation-mcp as the image name.

What differs from the local (uv run) path:

  • The image defaults to SERVER_HOST=0.0.0.0 and SERVER_PORT=8000, so it is reachable through -p ...:8000. A --env-file value overrides those defaults, and .env.example sets 127.0.0.1 and 8001; the -e flags above override the .env file again, so keep them (or drop SERVER_HOST and SERVER_PORT from the .env you use with Docker).
  • Use host.docker.internal instead of localhost in DB_URL for a database running on your own machine.
  • AWS_PROFILE won't work (there's no local AWS config file inside the image) — use CLOUDWATCH_ACCESS_KEY_ID/CLOUDWATCH_SECRET_ACCESS_KEY in .env instead if you need CloudWatch tools.

What each source needs

Source Required Notes
PostgreSQL (db_* tools) DB_URL Full connection string, asyncpg driver: postgresql+asyncpg://user:pass@host:5432/dbname. Point this at a read-only role/replica — see Security Model.
AWS CloudWatch (cw_* tools) CLOUDWATCH_REGION + one of (AWS_PROFILE) or (CLOUDWATCH_ACCESS_KEY_ID + CLOUDWATCH_SECRET_ACCESS_KEY) + CLOUDWATCH_ALLOWED_LOG_GROUP CLOUDWATCH_REGION has no AWS_REGION fallback — it must be set explicitly. CLOUDWATCH_ALLOWED_LOG_GROUP is a comma-separated allowlist; leaving it unset means no log group is queryable.
New Relic (nr_* tools) NEW_RELIC_API_KEY + NEW_RELIC_ACCOUNT_ID The API key must be a User API key (NRAK-...), not an ingest/license key. NEW_RELIC_REGION defaults to us; set it to eu for EU-region accounts.

See .env.example for every available variable, including tuning knobs (row limits, time-window caps, timeouts) that all ship with working defaults.

Configure Your AI Assistant

Cursor — .cursor/mcp.json:

{
  "mcpServers": {
    "investigation": {
      "type": "http",
      "url": "http://localhost:8001/mcp"
    }
  }
}

Claude Desktop — same shape in claude_desktop_config.json.

Usage Examples

Investigate a failed order

Ask:

Why did checkout fail for order 88213 around 14:30 IST yesterday?

Find a user's records across the database

Ask:

Find every row across the schema that references user_id 4417.

Trace a request through the logs

Ask:

Pull the log lines for order_id 88213 from /aws/ecs/checkout-svc for the last hour.

Cross-check against New Relic

Ask:

What event types have data in New Relic in the last hour, and what fields does the Log event type have?

MCP Server API

For a junior-friendly reference with inputs, output structures, examples, and tool update guidance, see docs/tool-reference.md.

Tool Name Description
db_list_tables Tables + row estimates + comments (cached ~10 min).
db_describe_table Columns, types, nullability, PK/FK, indexes.
db_sample_rows Sample rows, PII-masked.
db_explain_query EXPLAIN (FORMAT JSON) on a validated query.
db_run_query Validated, read-only SELECT execution.
db_search_by_identifier Find rows across catalog-discovered tables by order/user/payment/request id.
db_resolve_store Resolve a store name/domain to a store_id, or return candidates if ambiguous.
cw_list_log_groups Log groups + retention + stored bytes.
cw_describe_log_fields Sample recent events, discover JSON fields + frequency.
cw_run_insights_query StartQuery → poll → GetQueryResults, cost-capped.
cw_get_trace_events Convenience wrapper: matching log lines for a field/value, sorted chronologically.
cw_filter_events Simple pattern grep over recent events.
cw_get_metric_stats CloudWatch metric datapoints.
nr_list_event_types SHOW EVENT TYPES — enumerates event types with data (Log, Transaction, Span, Metric, custom types); run before nr_describe_log_fields if the event type is unknown.
nr_describe_log_fields keyset() of a New Relic event type (default Log), flags likely trace/correlation id attributes; run before writing NRQL.
nr_run_nrql_query Validated, read-only NRQL execution against New Relic (Log/Metric/event data).

Resources: schema://db/tables, schema://db/table/{name}, logs://groups, docs://query-cookbook.

Security Model

Every db_*/cw_*/nr_* call goes through a guardrail layer before any network I/O: SQL is parsed with sqlglot and rejected unless it's a single SELECT/WITH...SELECT with no dangerous functions; CloudWatch calls are checked against a log-group allowlist, a time-window cap, and a bytes-scanned cost ceiling; NRQL is restricted to a single SELECT with no write-ish keywords and a clamped LIMIT. Results and any log messages are redacted before returning. See docs/design.md §6 for the full model.

Development

uv run ruff check .                              # lint
uv run pytest tests/unit -q                      # guardrail/redaction tests, no external deps
uv run pytest tests/integration -m integration   # requires a reachable Postgres; auto-skips otherwise
  • tests/unit/ — pure logic, no network/DB dependency (the guardrail tests are the security-boundary tests and the highest priority in this suite).
  • tests/integration/test_db_tools.py — runs against your configured Postgres; skipped automatically if it isn't reachable.

CI (.github/workflows/ci.yml) runs lint + both test suites on every push/PR to main/dev.

See CLAUDE.md for the architecture/layering conventions this codebase follows, and docs/tool-reference.md for how to add a new tool. Contributing a change? See CONTRIBUTING.md.

License

MIT

Metadata

Release files for opsinsight-mcp 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for opsinsight-mcp 0.1.1
File Size Uploaded Provenance Actions
opsinsight_mcp-0.1.1.tar.gz 1.3 MB With provenance Details for opsinsight_mcp-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for opsinsight-mcp 0.1.1
File Interpreter ABI Platform Actions
opsinsight_mcp-0.1.1-py3-none-any.whl Python 3 none any Details for opsinsight_mcp-0.1.1-py3-none-any.whl

Total release size: 1.4 MB

Release files / opsinsight_mcp-0.1.1.tar.gz

Download URL opsinsight_mcp-0.1.1.tar.gz
Size 1.3 MB
Tags Source
SHA-256 checksum
How to use checksums
a7f2f5f1e6e7da26b79ddb2953dabf3c47ef3ed64ba0a5e601a2bb5cd2e5646f
BLAKE2b-256 checksum
How to use checksums
92d5ea8866d7ed8a375c435229763b69c224e20384a76051053f7f352421d8bf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / opsinsight_mcp-0.1.1-py3-none-any.whl

Download URL opsinsight_mcp-0.1.1-py3-none-any.whl
Size 63.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
411ce362dd6caa99970f3bfc8f3c471bd310508c0e4fad0f8c3df5fa4d949ad2
BLAKE2b-256 checksum
How to use checksums
c6cec70c288a9d48e8642038eb23d25c9091980530d077e07ee01d65686bc039
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Security for opsinsight-mcp 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for opsinsight_mcp-0.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page