Skip to content

Getting started

Conduit provides one local MCP endpoint that federates configured downstream Streamable HTTP MCP servers. It requires Python 3.11 or newer.

Install

Install the published package with pipx install conduit-gateway, or build from source:

git clone https://github.com/Rakshita-0023/conduit.git
cd conduit
python -m venv .venv
. .venv/bin/activate
python -m pip install -e .

Configure and start

Create the bundled template, set each downstream URL and its policy, then start Conduit:

conduit --init --config conduit.yaml
conduit --config conduit.yaml

--init creates a private file and refuses to overwrite one. It is available from the published wheel as well as a source checkout.

Run a local demo downstream

For a complete first run, install the official SDK and save this as demo_server.py in a separate working directory:

python -m pip install mcp
import asyncio

from mcp.server.mcpserver import MCPServer

server = MCPServer("demo")


@server.tool()
def hello(name: str) -> dict[str, str]:
    return {"message": f"hello, {name}"}


if __name__ == "__main__":
    asyncio.run(server.run_streamable_http_async(port=9000, json_response=True, stateless_http=True))

Start it in one terminal:

python demo_server.py

Wait until it prints the local URL before starting Conduit in another terminal.

In conduit.yaml, replace the generated downstream entry with:

downstreams:
  - id: demo
    url: http://127.0.0.1:9000/mcp
    headers: {}
policy:
  allow: ["demo.*"]
  deny: []

Then start Conduit in a second terminal:

conduit --config conduit.yaml

The listener must be loopback-only. On first start Conduit refreshes every downstream catalog. It is ready only when every downstream has attempted its first refresh, at least one is healthy, the aggregate is usable, and audit storage is healthy.

curl -sS http://127.0.0.1:8080/healthz
curl -sS http://127.0.0.1:8080/status

Discover tools

Use a Streamable HTTP MCP client with protocol version 2026-07-28. Requests must include matching MCP-Protocol-Version, Mcp-Method, JSON-RPC method, and _meta protocol metadata.

Conduit publishes tools as <downstream-id>.<tool-name>, such as github.search_code; those public names are policy-filtered and do not need to be parsed by a client.

With the official SDK installed, run this in a third terminal to verify the complete path:

import asyncio
from mcp.client.client import Client


async def main() -> None:
    async with Client("http://127.0.0.1:8080/mcp") as client:
        tools = await client.list_tools()
        print([tool.name for tool in tools.tools])  # ['demo.hello']
        result = await client.call_tool("demo.hello", {"name": "Conduit"})
        print(result.content[0].text)


asyncio.run(main())