Skip to main content

BridgeMCP

CI PyPI Python License: MIT

A production-ready Python framework for building MCP servers.

BridgeMCP makes it simple to expose your application's data and actions to AI clients like Claude Desktop, Cursor, and VS Code through the Model Context Protocol.

Write your business logic. BridgeMCP handles the protocol.


Why BridgeMCP

The MCP Python SDK is powerful but low-level. Building a real server means wiring up transport layers, hand-crafting JSON schemas, managing tool dispatch, and handling protocol errors — before you write a single line of business logic.

BridgeMCP wraps all of that behind a clean, decorator-based API:

Without BridgeMCP With BridgeMCP
Manually define JSON schemas Inferred from type annotations
Write protocol handlers @app.tool decorator
Manage error codes Typed exception hierarchy
Choose and wire a transport app.run() or app.run_http()

Installation

# With MCP transport support
pip install 'bridgemcp-py[mcp]'

# Core only (no transport — useful if you only need app.call() in tests)
pip install bridgemcp-py

Python 3.11+ required.


Quick Start

1. Write your server (server.py):

from bridgemcp import BridgeMCP

app = BridgeMCP(name="my-app", version="1.0.0", description="My first MCP server.")

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

@app.tool
def add(x: int, y: int) -> int:
    """Add two integers."""
    return x + y

if __name__ == "__main__":
    app.run()

2. Connect to Claude Desktop

Edit your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "my-app": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

Restart Claude Desktop. Your tools will appear in the tool picker.


Core Concepts

Creating an application

from bridgemcp import BridgeMCP
from bridgemcp.config import BridgeConfig

app = BridgeMCP(
    name="my-app",          # shown to AI clients during the MCP handshake
    version="1.0.0",        # defaults to the installed package version
    description="...",      # optional — shown as server instructions
    config=BridgeConfig(),
)

Registering tools

Use @app.tool as a bare decorator or with keyword arguments:

# Bare — uses function name and docstring automatically
@app.tool
def get_order(order_id: str) -> dict:
    """Fetch an order by ID."""
    return orders.get(order_id)

# With overrides
@app.tool(name="list_orders", description="List all open orders.")
def fetch_open_orders(limit: int = 20) -> list:
    return orders.list(status="open", limit=limit)

Type annotations become the JSON schema that AI clients use to call your tools. Default values become optional parameters. Docstrings become tool descriptions.

Calling tools directly

The decorated function is returned unchanged, so you can call it in tests without touching the framework:

# Direct call — no framework involved
assert get_order("ORD-123") == {"id": "ORD-123", ...}

# Through the framework — registry lookup + error wrapping
result = app.call("get_order", order_id="ORD-123")

Running the server

# stdio — subprocess transport (Claude Desktop, Cursor, VS Code)
app.run()

# HTTP/SSE — network transport
app.run_http(host="0.0.0.0", port=8000)

Exception Hierarchy

All BridgeMCP exceptions inherit from BridgeMCPError:

from bridgemcp.exceptions import (
    BridgeMCPError,              # base — catch this to handle any framework error

    # Tools
    ToolNotFoundError,           # raised by app.call() when the tool name is unknown
    ToolRegistrationError,       # raised by @app.tool when a name is already taken
    ToolExecutionError,          # raised when the tool function itself raises

    # Resources
    ResourceNotFoundError,       # raised by app.read_resource() when URI is unknown
    ResourceRegistrationError,   # raised by @app.resource when URI is already taken
    ResourceExecutionError,      # raised when the resource handler raises

    # Prompts
    PromptNotFoundError,         # raised by app.render_prompt() when name is unknown
    PromptRegistrationError,     # raised by @app.prompt when name is already taken
    PromptExecutionError,        # raised when the prompt handler raises
)
# The original exception is always available via __cause__ on execution errors.

Architecture

bridgemcp/
├── application.py      # BridgeMCP — the single public entry point
├── config/             # BridgeConfig (Pydantic, frozen)
├── exceptions.py       # Typed exception hierarchy
├── execution.py        # Handler execution pipeline (shared by all primitives)
├── middleware.py       # InvocationContext, MiddlewareFn, build_chain()
├── plugin.py           # Plugin base class and duck-typing contract
├── tools/              # Tool dataclass + ToolRegistry
├── resources/          # Resource dataclass + ResourceRegistry
├── prompts/            # Prompt, PromptMessage, PromptRegistry
└── adapters/           # Protocol adapters (MCP SDK is only imported here)
    └── mcp.py          # build_mcp_server() → FastMCP

The framework is layered deliberately:

  1. BridgeMCP owns the entire public API — decorators, invocation methods, run().
  2. Registry modules store primitive metadata independently of any protocol.
  3. execution.py handles invocation, exception chaining, and output normalization.
  4. middleware.py defines the composition layer — no framework imports.
  5. adapters/mcp.py is the only place the MCP SDK is imported.

Because the MCP SDK is an optional dependency, BridgeMCP and all invocation methods work without it. Your unit tests run without any MCP imports, keeping them fast and your business logic decoupled from the transport.


Examples

Example Description
examples/hello_world/ Minimal server — greet, add, server_info tools

Development

# Clone and install in editable mode with all dev dependencies
git clone https://github.com/Arsie-codes/bridgemcp.git
cd bridgemcp
pip install -e '.[mcp,dev]'

# Run the test suite
pytest

# Run a specific test file
pytest tests/test_tool_registry.py -v

# Lint and format
ruff check bridgemcp tests
black bridgemcp tests

The test suite requires no network access and no MCP client — it runs entirely against the in-process framework.


What's in the core

Feature API
Tools @app.tool, app.call(), await app.acall(), app.list_tools()
Resources @app.resource(uri=...), app.read_resource(), await app.aread_resource(), app.list_resources()
Prompts @app.prompt, app.render_prompt(), await app.arender_prompt(), app.list_prompts()
Middleware app.add_middleware(), @app.middleware
Plugins app.register_plugin(), Plugin base class (optional)
Transport app.run() (stdio), app.run_http() (HTTP/SSE)


Official BridgeMCP Ecosystem

Framework

Official Plugins

Official Servers

More official plugins and servers are currently under development.

License

MIT — Copyright (c) 2026 Muhammad Arslan

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bridgemcp_py-0.2.4.tar.gz (71.1 kB view details)

Uploaded Source

Built Distribution

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

bridgemcp_py-0.2.4-py3-none-any.whl (33.9 kB view details)

Uploaded Python 3

File details

Details for the file bridgemcp_py-0.2.4.tar.gz.

File metadata

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

File hashes

Hashes for bridgemcp_py-0.2.4.tar.gz
Algorithm Hash digest
SHA256 babcfb455bc973dc066f4271a62c8c3dc36f4e389f83904b5edb70ad9ede1196
MD5 81c2d3c271a5d747bbda4a6fa7aaaa4e
BLAKE2b-256 e2a6422619f1de08c8680e78980680100cd8806817d388ba37620d510acdd8a7

See more details on using hashes here.

File details

Details for the file bridgemcp_py-0.2.4-py3-none-any.whl.

File metadata

  • Download URL: bridgemcp_py-0.2.4-py3-none-any.whl
  • Upload date:
  • Size: 33.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for bridgemcp_py-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 7aac3244acf56ab961595b75c6d08157f1c2dbeb3c321a8f920249b787e6b253
MD5 eb720e2625df594c2421d120c0c7bb00
BLAKE2b-256 6178ae76ef2b78b16b603d79e1add14e57f03a46d0a6e9fb7d7051e9ebc25ec8

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 Sentry Error logging StatusPage Status page