Lightweight telemetry SDK for MCP servers. Captures MCP tool invocations, HTTP requests, business events, and UI interactions with built-in payload sanitization.
Project description
listo-mcp-observability
Lightweight telemetry SDK for Python MCP servers. Captures MCP tool invocations, HTTP requests, business events, and UI interactions with built-in payload sanitization.
Python port of @listo-labs-ltd/mcp-observability (TypeScript).
Features
- Easy setup — 3 lines with
create_mcp_observability_easy() - Local dashboard — Real-time metrics at
/telemetry/dashboard - Centralized analytics — Send to Listo Insights in production
- MCP tool tracking — Decorator-based (
@obs.track_tool()) or programmatic wrapping - Payload sanitization — Redacts password, token, apiKey, secret, authorization
- Sampling — Configurable rates with guaranteed error/session capture
- Zero runtime dependencies — Core uses only Python stdlib
Installation
# From PyPI
pip install listo-mcp-observability
# With uv
uv add listo-mcp-observability
# With optional MCP SDK support
pip install "listo-mcp-observability[mcp]"
# With optional Starlette dashboard support
pip install "listo-mcp-observability[starlette]"
Quick Start
from mcp.server.fastmcp import FastMCP
from mcp_observability import create_mcp_observability_easy
mcp = FastMCP("my-server")
obs = create_mcp_observability_easy(service_name="my-server")
@mcp.tool()
@obs.track_tool("search_hotels")
async def search_hotels(query: str) -> str:
return f"Results for {query}"
Environment Variables
| Variable | Description | Default |
|---|---|---|
INSIGHTS_API_URL |
Listo Insights API endpoint | — |
INSIGHTS_API_KEY |
API key for authentication | — |
ENVIRONMENT or PYTHON_ENV |
Controls dev/production defaults | dev |
API
create_mcp_observability_easy()
Recommended entry point with sensible defaults:
obs = create_mcp_observability_easy(
service_name="my-server",
service_version="1.0.0",
environment="dev", # "dev" | "staging" | "production"
sample_rate=1.0, # 0.0 to 1.0 (errors always captured)
)
Dev mode (default): Console logging (errors only), in-memory dashboard, 100% sampling.
Production mode: No console, remote sink only, 10% sampling.
@obs.track_tool(name)
Decorator for tracking MCP tool calls:
@mcp.tool()
@obs.track_tool("my_tool")
async def my_tool(arg: str) -> str:
...
obs.wrap_mcp_handler(request_kind, handler, context)
Programmatic handler wrapping:
wrapped = obs.wrap_mcp_handler(
"CallTool",
original_handler,
context=lambda *args, **kwargs: McpTrackingContext(
tool_name="search",
args=kwargs,
),
)
obs.record_business_event(name, properties, status)
obs.record_business_event("purchase", {"amount": 99.99}, "ok")
obs.record_session(action, session_id)
obs.record_session("open", "session-123")
obs.record_ui_event(name, ...)
obs.record_ui_event(name="click", action="button_press", widget_id="w1")
Dashboard Endpoints (Starlette)
from mcp_observability import create_telemetry_routes
routes = create_telemetry_routes()
# GET /telemetry — JSON metrics
# GET /telemetry/dashboard — HTML dashboard
# POST /telemetry/event — UI event ingestion
Remote Sink
from mcp_observability import RemoteSink, RemoteSinkOptions
sink = RemoteSink(RemoteSinkOptions(
endpoint="https://api.listoai.co/v1/events/batch",
api_key="your-key",
batch_size=50,
flush_interval=5.0,
max_retries=3,
))
Payload Sanitization
The SDK automatically redacts sensitive fields (case-insensitive):
password,token,apiKey,secret,authorization
Redaction is recursive (up to 6 levels deep) and limits arrays to 20 elements.
Custom redaction keys:
obs = McpObservability(ObservabilityOptions(
service_name="my-server",
redact_keys=["password", "token", "credit_card", "ssn"],
))
Development
# Install dependencies
uv sync --all-extras
# Run tests
uv run pytest -v
# Lint
uv run ruff check src/ tests/
# Build
uv build
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file listo_mcp_observability-0.0.2.tar.gz.
File metadata
- Download URL: listo_mcp_observability-0.0.2.tar.gz
- Upload date:
- Size: 19.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
930759dd2a6e48d69a5d6ca06cbb1b36018ff74e579e1f18e2dc2bf8fafaecfc
|
|
| MD5 |
ee6d7c97cee1d9cd3596cda583481897
|
|
| BLAKE2b-256 |
58dedb86f2fc619266522358011691a329b3603c4f958d659c1ec9abe15c66a7
|
Provenance
The following attestation bundles were made for listo_mcp_observability-0.0.2.tar.gz:
Publisher:
publish.yml on Listo-Labs-Ltd/mcp-observability-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
listo_mcp_observability-0.0.2.tar.gz -
Subject digest:
930759dd2a6e48d69a5d6ca06cbb1b36018ff74e579e1f18e2dc2bf8fafaecfc - Sigstore transparency entry: 991834859
- Sigstore integration time:
-
Permalink:
Listo-Labs-Ltd/mcp-observability-python@c5e8282027164e877785b4e43080ff04910fdc96 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Listo-Labs-Ltd
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c5e8282027164e877785b4e43080ff04910fdc96 -
Trigger Event:
push
-
Statement type:
File details
Details for the file listo_mcp_observability-0.0.2-py3-none-any.whl.
File metadata
- Download URL: listo_mcp_observability-0.0.2-py3-none-any.whl
- Upload date:
- Size: 16.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
abb666c0b0c8b3644f7f65b36f187d6406f1d67df2dc9ae56116190b93f0b256
|
|
| MD5 |
5bc8b25c7655ab3aebf342120a3aac8d
|
|
| BLAKE2b-256 |
4a153147ed553b6838874bc005515d5848b0e846b69c575bd0e8a7ab5e1e65b2
|
Provenance
The following attestation bundles were made for listo_mcp_observability-0.0.2-py3-none-any.whl:
Publisher:
publish.yml on Listo-Labs-Ltd/mcp-observability-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
listo_mcp_observability-0.0.2-py3-none-any.whl -
Subject digest:
abb666c0b0c8b3644f7f65b36f187d6406f1d67df2dc9ae56116190b93f0b256 - Sigstore transparency entry: 991834862
- Sigstore integration time:
-
Permalink:
Listo-Labs-Ltd/mcp-observability-python@c5e8282027164e877785b4e43080ff04910fdc96 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/Listo-Labs-Ltd
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c5e8282027164e877785b4e43080ff04910fdc96 -
Trigger Event:
push
-
Statement type: