Skip to main content

Lightweight out-of-band event channel for MCP servers

Project description

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}
    }
  ]
}
  • events is omitted when empty — never "events": []
  • context is 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

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

mcp_events-0.1.0.tar.gz (33.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_events-0.1.0-py3-none-any.whl (4.9 kB view details)

Uploaded Python 3

File details

Details for the file mcp_events-0.1.0.tar.gz.

File metadata

  • Download URL: mcp_events-0.1.0.tar.gz
  • Upload date:
  • Size: 33.5 kB
  • Tags: Source
  • Uploaded using 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}

File hashes

Hashes for mcp_events-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d9c26adde5fa1f7c511d8207a2361b89e78c8dca0ba712340168e7f5729a0fb8
MD5 ce13aeb8945ad309b618fa03df28b776
BLAKE2b-256 22cf90b4af882a55e7d95ea0c9177914095c8132e4652fda296739769be9eb11

See more details on using hashes here.

File details

Details for the file mcp_events-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: mcp_events-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 4.9 kB
  • Tags: Python 3
  • Uploaded using 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}

File hashes

Hashes for mcp_events-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 21a5c44b241e8d2b89289f4bdf88e8ab9f636a488a6552031c96c7e4092997ef
MD5 7522778f178800f5e7783d919d99f5b3
BLAKE2b-256 5492a112182f36b255075bf0dca99f35465a92835cf4d7e1b9766a052d19d2a8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page