platform-adapter-mcp
README.md
# platform-adapter-mcp
A reference implementation of the **adapter pattern for the Model Context
Protocol (MCP)** — the same architecture Claude Code uses internally to
expose tools to its agent loop.
The reference wraps seven real-world REST/GraphQL APIs (HackerOne,
Intigriti, Bugcrowd, Code4rena, Immunefi, YesWeHack, HackenProof) behind
a single, uniform tool surface. Swap the adapters for CRMs, ATSs,
finance APIs, internal services — the MCP layer doesn't change.
```
+---------------------------------+
| Claude Code / LLM agent | ← makes tool calls
+---------------------------------+
| MCP (JSON-RPC)
+---------------------------------+
| FastMCP server (server.py) | ← uniform tool surface
+---------------------------------+
|
+---------------------------------+
| Adapter registry (lazy) | ← one class per upstream API
+---------------------------------+
|
+------+------+------+------+-----+
| H1 | Bug | C4 | ... | CRM | ← platform-specific auth, rate limit,
+------+------+------+------+-----+ schema normalization
```
## What this demonstrates
- **Adapter pattern in Python.** One abstract base class
(`adapters/base.py`) with `authenticate`, `list_programs`, `get_program`,
`get_scope`. Every platform implements the same four methods against a
different upstream schema.
- **Lazy initialization.** Adapters only spin up when first called and
only if credentials are configured — same pattern you'd use for an
MCP server that conditionally exposes Salesforce vs. HubSpot based on
which credentials exist in the environment.
- **Schema normalization.** Each platform returns data in a different
shape (HackerOne: REST + GraphQL; Bugcrowd: GraphQL microservice;
Code4rena: undocumented JSON; Immunefi: REST with quirky auth). They
all map to the same `Program` / `ScopeAsset` / `Brief` dataclasses
consumed by the MCP tools.
- **Prompt-driven tool design.** Each `@mcp.tool()` exposes a single
high-level intent (`cross_platform_scope("shopify.com")`) rather than
raw CRUD primitives — this is how you keep tool descriptions short and
agent-friendly.
## Why this matters for prompt-driven development
MCP is the standard tool protocol for Claude Code and most modern agent
runtimes. Writing a thin MCP wrapper around any existing API turns that
API into a callable tool the agent can use on its own. The same pattern
works for:
- **CRMs** (Salesforce, HubSpot, Pipedrive)
- **ATSs** (Greenhouse, Lever, Workable)
- **Internal services** (any authenticated REST API in your stack)
- **Finance/payment tools** (Stripe, Mercury, Plaid)
The agent never needs to know the upstream API exists. It calls
`find_account(domain="acme.com")` and the adapter handles auth, retry,
and schema mapping.
## Quick start
```bash
git clone https://github.com/kigansolutions/platform-adapter-mcp
cd platform-adapter-mcp
pip install -r requirements.txt
cp config.example.yaml config.yaml
# edit config.yaml with your platform credentials
python server.py
```
Then add to your MCP client (Claude Desktop, etc.):
```json
{
"mcpServers": {
"platforms": {
"command": "python",
"args": ["/path/to/platform-adapter-mcp/server.py"],
"env": {"BB_CONFIG": "/path/to/platform-adapter-mcp/config.yaml"}
}
}
}
```
The six `@mcp.tool()` functions become available immediately.
## Layout
```
platform-adapter-mcp/
├── server.py # FastMCP server, 6 tools, lazy adapter registry
├── config.example.yaml # Platform credentials (copy to config.yaml)
├── adapters/
│ ├── base.py # Abstract adapter + Program/ScopeAsset/Brief models
│ ├── hackerone.py # H1 REST + GraphQL adapter (full)
│ ├── intigriti.py # Intigriti REST adapter (full)
│ ├── bugcrowd.py # Bugcrowd GraphQL adapter (full)
│ ├── code4rena.py # Code4rena REST adapter (full)
│ ├── immunefi.py # Immunefi REST adapter (full)
│ ├── yeswehack.py # YesWeHack REST adapter (stub)
│ └── stubs.py # Sherlock + HackenProof placeholder adapters
└── requirements.txt
```
## Adding a new platform
1. Create `adapters/newplatform.py` extending `BaseAdapter`.
2. Implement `authenticate()`, `list_programs()`, `get_program()`,
`get_scope()`.
3. Register the class in `ADAPTER_CLASSES` in `server.py`.
4. Add a config block in `config.yaml`.
5. Done — the agent can now call the platform through the same six tools.
The same five steps add a new CRM, a new ATS, a new payment provider, or
a new internal microservice.
## Notes
- No credentials ship in this repo. `config.example.yaml` shows the
structure; users copy it to `config.yaml` and fill in their own keys.
- Adapters only activate when `enabled: true` AND valid credentials are
present. The server logs which adapters come online at startup.
- The `raw` field on every returned model preserves the original API
response, so agents can reach past the normalized model when needed
without changing the adapter.
## About
Built by [Cameron Weyers](https://github.com/kigansolutions), Kigan Agentic AI Solutions.This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues