Skip to main content

Structured invocation logging for BridgeMCP

Project description

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.

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

bridgemcp_logging-0.1.1.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

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

bridgemcp_logging-0.1.1-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file bridgemcp_logging-0.1.1.tar.gz.

File metadata

  • Download URL: bridgemcp_logging-0.1.1.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for bridgemcp_logging-0.1.1.tar.gz
Algorithm Hash digest
SHA256 7f60967676fc676e35b143cb0391e73f71e8f3f82ce6419bba6d425eff5193e8
MD5 bdcf973f4a02960e1b50a1dc59d9cc5e
BLAKE2b-256 612da9f0ef1eeea0928419ccaf27d5f9f0f17af1fe2ab2e289166d752f72879d

See more details on using hashes here.

File details

Details for the file bridgemcp_logging-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for bridgemcp_logging-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1da67a824b719e50bed414fc4d3bf6515eeff9f84efc7de005edb8346738fc47
MD5 99061da828d7213a145ef6021d6bbb44
BLAKE2b-256 da9d5da0bbcec3763b237505445f0297a812b29894f932914446311695b78c62

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