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.
Project details
Release history Release notifications | RSS feed
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 bridgemcp_logging-0.1.0.tar.gz.
File metadata
- Download URL: bridgemcp_logging-0.1.0.tar.gz
- Upload date:
- Size: 11.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1916d6d126516d459c834a2c6203b61c8bb87e97c29dc81f44b2a8051870992
|
|
| MD5 |
81a57cbe15ec57148bbd7b384b2c7158
|
|
| BLAKE2b-256 |
b711a713ee55f5529baffccea317ab4598f8204ce9259f421e6bc89ea48bf750
|
File details
Details for the file bridgemcp_logging-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bridgemcp_logging-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7fa24ae7745eab714ca7df413dc11f12943839593e0f163409ab049aa5c7f436
|
|
| MD5 |
f476ddbcd8277a1aa01bd72d08e50ef3
|
|
| BLAKE2b-256 |
0195e7d67be3538211f2f77a2d6868b13406656377e939044a1026bf2eecf525
|