mcp-events
Lightweight out-of-band event channel for MCP servers.
A tool call can accumulate warnings and errors that don't belong in the main
return value but also can't be silently swallowed. mcp-events gives those
signals a coherent path to the calling LLM.
Quick start
from mcp_events import with_events, soft_failure, emit_event
@with_events()
@mcp.tool()
def my_tool(args):
try:
result = risky_thing()
except Exception as e:
soft_failure("risky_thing_failed", str(e), {"context": "..."})
result = fallback_result()
return {"status": "ok", "data": result}
When warnings or errors are emitted, the decorator appends them to the response:
{
"status": "ok",
"data": "...",
"events": [
{
"level": "warn",
"code": "risky_thing_failed",
"message": "connection reset by peer",
"context": {"context": "..."}
}
]
}
The events field is omitted entirely when nothing notable happened.
API
Emitting events
from mcp_events import soft_failure, emit_event
# soft_failure is an alias for warn — use at previously-silent except blocks
soft_failure("code", "message", {"optional": "context"})
# emit at any severity
emit_event("info" | "warn" | "error", "code", "message", {...})
Both functions route to the active EventAccumulator when inside an
event_context, or fall back to stderr when called outside one.
Context management
from mcp_events import event_context, get_current
with event_context() as events:
events.warn("code", "message")
response = {"status": "ok"}
if events.has_any("warn"):
response["events"] = events.to_envelope()
return response
Nested event_context blocks share the outer accumulator — events from
deeply-nested helpers accumulate into the top-level context rather than
being discarded.
Decorator
from mcp_events import with_events
@with_events() # default: surface warn+error events
@with_events("info") # surface all events including info
Works on both sync and async functions. The events key is omitted when no
events meet the threshold.
Persistence
acc.events # list[Event] snapshot — iterate for local persistence
Each Event has severity, code, message, context (dict, defaults to {}).
Response envelope
{
"status": "ok",
"events": [
{
"level": "warn",
"code": "stale_cache_fallback",
"message": "Using cached snapshot from 5 days ago",
"context": {"snapshot_age_days": 5}
}
]
}
eventsis omitted when empty — never"events": []contextis omitted when empty — never"context": {}- Emission order is chronological
Distribution
In development, install from the local path in each consuming project:
# pyproject.toml
[project]
dependencies = ["mcp-events>=0.1.0"]
[tool.uv.sources]
mcp-events = { path = "/path/to/mcp-events", editable = true }
Downstream users (installing from PyPI) ignore the [tool.uv.sources] block
and get the published package.
Running tests
uv run pytest
Metadata
Release files for mcp-events 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mcp_events-0.1.0.tar.gz | 33.5 kB | Without provenance | Details for mcp_events-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mcp_events-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for mcp_events-0.1.0-py3-none-any.whl |
Total release size: 38.4 kB
Release files / mcp_events-0.1.0.tar.gz
| Download URL | mcp_events-0.1.0.tar.gz |
|---|---|
| Size | 33.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d9c26adde5fa1f7c511d8207a2361b89e78c8dca0ba712340168e7f5729a0fb8
|
|
BLAKE2b-256 checksum How to use checksums |
22cf90b4af882a55e7d95ea0c9177914095c8132e4652fda296739769be9eb11
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / mcp_events-0.1.0-py3-none-any.whl
| Download URL | mcp_events-0.1.0-py3-none-any.whl |
|---|---|
| Size | 4.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
21a5c44b241e8d2b89289f4bdf88e8ab9f636a488a6552031c96c7e4092997ef
|
|
BLAKE2b-256 checksum How to use checksums |
5492a112182f36b255075bf0dca99f35465a92835cf4d7e1b9766a052d19d2a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for mcp-events 0.1.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
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.