Skip to main content

bridgemcp-logging

Structured invocation logging for BridgeMCP.

Every tool call, resource read, and prompt render is recorded with timing, exception details, and a structured log record. Zero configuration required.


Installation

pip install bridgemcp-logging

Requires bridgemcp-py >= 0.2.1 and Python 3.11+.


Quickstart

from bridgemcp import BridgeMCP
from bridgemcp_logging import LoggingPlugin

app = BridgeMCP(name="my-server")
app.register_plugin(LoggingPlugin())

@app.tool
def greet(name: str) -> str:
    return f"Hello, {name}!"

app.run()

Console output for each call:

[2026-06-30 12:00:00Z] INFO  tool:greet           2.1ms  OK

Configuration

from bridgemcp_logging import LoggingPlugin, LoggingConfig, ConsoleHandler

plugin = LoggingPlugin(
    config=LoggingConfig(
        success_level="DEBUG",   # level for successful calls (default: "INFO")
        error_level="ERROR",     # level for failed calls (default: "ERROR")
        log_kwargs=True,         # include call arguments in the record (default: False)
        log_result=False,        # include return values in the record (default: False)
    ),
    handler=ConsoleHandler(stream=sys.stdout),
)
app.register_plugin(plugin)

log_kwargs and log_result are False by default because arguments and return values may contain secrets or large payloads. Enable them explicitly when needed.


Public API

LoggingPlugin

class LoggingPlugin(Plugin):
    name = "bridgemcp-logging"
    version: str          # from installed package metadata
    description: str

    def __init__(
        self,
        config: LoggingConfig = LoggingConfig(),
        handler: ConsoleHandler = ConsoleHandler(),
    ) -> None: ...

    def setup(self, app: BridgeMCP) -> None: ...
    async def on_startup(self, app: BridgeMCP) -> None: ...
    async def on_shutdown(self, app: BridgeMCP) -> None: ...

LoggingConfig

class LoggingConfig(BaseModel, frozen=True):
    success_level: str = "INFO"
    error_level: str = "ERROR"
    log_kwargs: bool = False
    log_result: bool = False

InvocationRecord

@dataclass(frozen=True)
class InvocationRecord:
    invocation_id: str
    app_name: str
    framework_version: str
    plugin_version: str
    primitive: str              # "tool" | "resource" | "prompt"
    name: str
    kwargs: dict[str, Any] | None
    result: Any
    exception: Exception | None
    exception_type: str | None
    exception_chain: list[str]
    succeeded: bool
    duration_ms: float
    started_at: datetime
    finished_at: datetime
    level: str

TextFormatter

class TextFormatter:
    def format(self, record: InvocationRecord) -> str: ...

Produces one-line human-readable output:

[2026-06-30 12:00:00Z] INFO  tool:greet           12.3ms  OK
[2026-06-30 12:00:01Z] ERROR tool:send_email        3.2ms  FAILED  SMTPAuthenticationError: ...

ConsoleHandler

class ConsoleHandler:
    def __init__(
        self,
        stream: TextIO = sys.stderr,
        formatter: TextFormatter = TextFormatter(),
    ) -> None: ...

    def emit(self, record: InvocationRecord) -> None: ...
    def flush(self) -> None: ...

Exception handling

If a tool, resource, or prompt handler raises, the exception is captured in the InvocationRecord, the record is emitted, and the exception is re-raised. The logging plugin is transparent — it never swallows exceptions.

asyncio.CancelledError and KeyboardInterrupt are not captured (they are not Exception subclasses and should propagate without interference).


Middleware ordering

bridgemcp-logging should be the first plugin registered so its timing measurement covers the full middleware chain:

app.register_plugin(LoggingPlugin())   # outermost — measures total wall time
app.register_plugin(AuthPlugin())
app.register_plugin(RateLimitPlugin())

Versioning

bridgemcp-logging is versioned independently from bridgemcp-py. Compatible versions:

bridgemcp-logging bridgemcp-py
0.1.x >= 0.2.1

License

MIT — see LICENSE.


Official BridgeMCP Ecosystem

Framework

Official Plugins

Official Servers

More official plugins and servers are currently under development.

Release files for bridgemcp-logging 0.1.2

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

Source distribution (sdist)

Source distribution for bridgemcp-logging 0.1.2
File Size Uploaded
bridgemcp_logging-0.1.2.tar.gz 14.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bridgemcp-logging 0.1.2
File Interpreter ABI Platform
bridgemcp_logging-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 25.4 kB

Release files / bridgemcp_logging-0.1.2.tar.gz

Download URL bridgemcp_logging-0.1.2.tar.gz
Size 14.3 kB
Tags Source
SHA-256 checksum
How to use checksums
017a0e38371d249ddd2499f73c336e2006643edd38794d43a0351bb2b15e9846
BLAKE2b-256 checksum
How to use checksums
7823201d52b5defb054d3f400fc2facf12e37a00236c2b3706d52a59aaf2271b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release files / bridgemcp_logging-0.1.2-py3-none-any.whl

Download URL bridgemcp_logging-0.1.2-py3-none-any.whl
Size 11.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
142e0fe9a756338d3d8fbf77de95d173d94d23df15914f3d8bd05c4d0ff8fc1d
BLAKE2b-256 checksum
How to use checksums
efcd551bfd73cff737751d82897bb420b165c867c63472556fb40c1d2b87b89f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.6

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

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