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
- BridgeMCP https://github.com/Arsie-codes/bridgemcp
Official Plugins
- bridgemcp-logging https://github.com/Arsie-codes/bridgemcp-logging
Official Servers
- bridgemcp-server-weather https://github.com/Arsie-codes/bridgemcp-server-weather
More official plugins and servers are currently under development.
Metadata
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)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| bridgemcp_logging-0.1.2.tar.gz | 14.3 kB | Without provenance | Details for bridgemcp_logging-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| bridgemcp_logging-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for bridgemcp_logging-0.1.2-py3-none-any.whl |
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
|
Security for bridgemcp-logging 0.1.2
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.