MCP Integration Bridge

MCP Integration Bridge

An MCP server that connects any two systems so an agent can explore both, map between them, and run real data transfers — then shows its working in a run folder you can audit afterwards.

Category
Visit Server

README

MCP Integration Bridge

An MCP server that connects any two systems so an agent can explore both, map between them, and run real data transfers — then shows its working in a run folder you can audit afterwards.

Nothing in the codebase names a product. Which systems the bridge talks to is decided by a .env file (addresses and credentials) and a profile (the shape of each system: its endpoints, entities, queries, and documentation tree). Pointing the bridge at a different pair of systems is a configuration change.

flowchart LR
  MCP["MCP client<br/>(Cursor, Claude Desktop)"] -- stdio --> B
  UI["Browser UI"] -- HTTP --> B
  B["Integration bridge"] <--> SRC["SOURCE system<br/>records read from"]
  B <--> TGT["TARGET system<br/>records written to"]
  B <--> HUB["HUB (optional)<br/>orchestration API"]
  ENV[".env"] --> B
  PROF["profiles/&lt;id&gt;/"] --> B

See docs/ARCHITECTURE.md for the full design.


What it gives an agent

Capability How
Explore live APIs Authenticated tools for each system: REST/OData reads, GraphQL queries, introspection
Explore the docs Offline keyword search across each system's source or specification tree
Read named entities source_query_data / target_query_data over operations the profile declares
Transfer records execute_workflow runs forward, reverse, or a full round trip
Self-bootstrap A missing workflow is built from a template, a codegen pipeline, or generated modules
Audit everything Every tool call, payload, and skipped field lands in a timestamped run folder

Quickstart

python -m venv .venv
.venv/Scripts/pip install -r requirements.txt   # Linux/macOS: .venv/bin/pip

cp .env.example .env      # then fill in the SOURCE_* and TARGET_* values
python scripts/selfcheck.py

selfcheck.py validates the profile, catalog, workflow and ingest wiring without contacting either system, so it works before you have credentials.

As an MCP server (stdio) — copy mcp.json.example into your MCP client config and adjust the paths:

.venv/Scripts/python server.py

As an HTTP API for a browser UI:

.venv/Scripts/python http_server.py     # http://127.0.0.1:8765

Start with bridge_info — it reports the active profile, both roles, and exactly which environment variables are still missing.


Configuration

Every connected system is a role, and all roles are configured the same way: <ROLE>_<OPTION>, where the role is SOURCE, TARGET, or HUB. Environment variables override the profile's defaults, so a profile ships the shape of a system and .env supplies the instance.

Minimum viable .env

ACTIVE_PROFILE=erp-to-tms

SOURCE_BASE_URL=https://your-tenant.example.com
SOURCE_TOKEN_URL=https://your-tenant.example.com/auth/realms/main/protocol/openid-connect/token
SOURCE_CLIENT_ID=your-client-id
SOURCE_CLIENT_SECRET=your-client-secret
SOURCE_DOCS_PATH=c:/Repositories/your-erp/workspace

TARGET_BASE_URL=https://your-platform.example.com
TARGET_USERNAME=you@example.com
TARGET_PASSWORD=your-password
TARGET_DOCS_PATH=c:/Repositories/your-platform

.env.example documents the full surface, including connector selection, path prefixes, login form field names, bootstrap behaviour, and the HTTP bridge.

Connectors

A role picks its protocol with <ROLE>_CONNECTOR:

Value Authentication Suits
oauth2_rest OAuth2 client credentials → bearer REST / OData service catalogues
session_graphql CSRF-protected form login → cookie GraphQL web applications
token_api Credentials → JWT bearer JSON APIs that issue a token from a login

Searching documentation

Each role's offline search is described entirely by settings, so it works against a source checkout, a specification bundle, or a folder of docs:

SOURCE_DOCS_PATH=c:/Repositories/your-erp/workspace
SOURCE_DOCS_GLOBS=*/model/**/*.projection,*/model/**/*.entity
SOURCE_DOCS_INDEX_GLOB=*/model/**/*.projection

TARGET_DOCS_PATH=c:/Repositories/your-platform
TARGET_DOCS_GLOBS=**/graphql/*.py,**/schema.py
TARGET_DOCS_INDEX_FILE=your_app/schema.py
TARGET_DOCS_INDEX_REGEX=(\w+Query)

DOCS_GLOBS selects what is searchable; the index settings produce the list of named API surfaces that *_search_docs returns alongside raw matches.


MCP tools

Bridge and runs

Tool Purpose
bridge_info Active profile, both roles, paths, and what is still unconfigured
run_new Start a new run folder
run_info Active run id, folder, and counters

Workflows

Tool Purpose
list_workflows Registered workflows and whether each is ready
workflow_bootstrap_hints Search hints and a starter manifest for a missing workflow
register_workflow Register a manifest plus forward.py and optional reverse.py
bootstrap_workflow Build a workflow automatically
execute_workflow Run forward, reverse, or round_trip

Source rolesource_connection_info, source_search_docs, source_http, source_service_query, source_service_metadata, source_query_data

Target roletarget_connection_info, target_search_docs, target_graphql, target_introspect, target_query_data

Hub rolehub_connection_info, hub_login, hub_trigger_run, hub_poll_run, hub_answer_run, hub_graphql, hub_http

Example agent flow

bridge_info                                        → confirm both roles are configured
source_search_docs("Shipment")                     → find the source API surface
target_introspect()                                → see what the target accepts
source_query_data("shipments", limit=5)            → sample real records
execute_workflow(workflow_id="booking", source_id="12345")
run_info                                           → the folder holding the evidence

Profiles

A profile describes one concrete pair of systems. profiles/erp-to-tms/ ships as a worked reference — copy it, edit it, and set ACTIVE_PROFILE.

profiles/<id>/
  profile.json     role defaults (connector, path prefixes, docs globs) + workflow manifests
  catalog.json     named read operations behind source_query_data / target_query_data
  ingest.json      write operations that generated mappings call
  reconcile.json   entities to compare across both systems
  smoke.json       the end-to-end pipeline and its pass criteria
  discovery.json   discovery step labels and the outcome catalogue
  templates/       bundled forward.py / reverse.py for bootstrap

Only profile.json is required.

Adding a readable entity

"source": { "operations": {
  "purchase_orders": {
    "description": "Purchase order headers.",
    "service": "PurchaseOrderHandling",
    "entity_set": "PurchaseOrderSet",
    "filter_template": "OrderNo eq '{identifier}'",
    "search_field": "Description"
  }
}}

source_query_data("purchase_orders", identifier="PO-1") works immediately, with no code change.

Adding a write operation

Generated mappings call methods that no Python file defines — the adapter resolves the name against ingest.json at call time:

"operations": {
  "create_order": {
    "document": "mutation CreateOrder($input: OrderInput!) { createOrder(input: $input) { order { id state } } }",
    "wrap_positional": "input",
    "variables": { "input": "{input}" },
    "root": "createOrder.order",
    "required": true,
    "flatten": { "id": "id", "state": "state" }
  }
}

Mapping logic too complex to express declaratively belongs in the workflow's forward.py / reverse.py, which is ordinary Python. That is the intended boundary: profiles describe what the systems offer; workflows describe how this business mapping works.


Workflows and runs

A workflow is a manifest (how to fetch from the source, what the target entity is called, whether a reverse callback exists) plus a forward.py and optional reverse.py. Asking for one that does not exist is not an error — the bridge tries a bundled template, then a codegen pipeline, then modules already generated under CODEGEN_ROOT, and only then returns needs_bootstrap with search hints and a starter manifest.

Every tool call runs inside a run folder:

runs/2026-08-11/143022-booking-12345/
  run.json  tool_calls.jsonl  transfer_log.jsonl  skips.jsonl
  inputs/   outputs/   mappings/

HTTP bridge

For browser UIs that cannot speak MCP stdio. Routes are role-shaped:

Method Path Purpose
GET /api/health, /api/info Liveness and active configuration
GET /api/workflows, /api/runs Registry and run history
POST /api/sessions Create a session
POST /api/sessions/{id}/configure Supply credentials
POST /api/sessions/{id}/configure-env Use the server's .env
GET /api/sessions/{id}/source/test, /target/test Prove each connection
GET /api/sessions/{id}/source/services, /target/types Discovered API surfaces
POST /api/sessions/{id}/discovery/start Walk both systems
POST /api/sessions/{id}/reconcile/run, /reconcile/lookup Master-data comparison
POST /api/sessions/{id}/smoke/run End-to-end proof
POST /api/sessions/{id}/agent/* Agent-planned discovery and builds

Repository layout

server.py                MCP entry point (stdio)
http_server.py           HTTP bridge entry point
integration_mcp/
  config/                .env loading, profiles, per-role settings
  connectors/            oauth2_rest, session_graphql, token_api, graphql_ingest
  catalog.py             profile-declared read operations
  search/                offline documentation and source-tree search
  transfer/              workflow execution
  workflows/             registry, manifests, bootstrap strategies
  runs/                  run folders, tool-call logging, spec snapshots
  http/                  sessions, discovery, reconcile, smoke, agent
profiles/                per-integration configuration
workflows/               registered forward/reverse modules (gitignored)
runs/                    run artefacts (gitignored)
scripts/                 selfcheck.py
docs/ARCHITECTURE.md     design, diagrams, extension points

Security notes

  • Each connector may only reach the hosts it was configured with. Add more with <ROLE>_ALLOWED_HOSTS, which keeps an authenticated connector from becoming an SSRF primitive.
  • Credentials are read from the environment only; .env and .env.* are gitignored. Cached cookies and tokens live under STATE_DIR.
  • *_connection_info tools report whether a credential is present, never its value.
  • Writing back to the source system is off by default; it requires post_callback=true or TRANSFER_POST_CALLBACK=1.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured