MCP Integration (Legacy v2)¶
Legacy (archived)
This page is the older, omnibus MCP guide kept for historical reference.
For the current v3 MCP docs, see:
- MCP Overview
- Node Server · Python Server
- Transports · OAuth/OIDC Setup
Demo
What MCP is - MCP is a protocol. “SSE”, “HTTP”, and “stdio” are transports. Faxbot provides two server implementations (Node and Python), each capable of running on any of the transports. Pick a language (Node or Python) and a transport (stdio/HTTP/SSE) that fits your environment.
Quick Start (Claude/Cursor) - Add Faxbot MCP to your assistant config (stdio). Then call send_fax with a local filePath.
Claude Desktop or Cursor config example:
{
"mcpServers": {
"faxbot": {
"command": "node",
"args": ["src/servers/stdio.js"],
"cwd": "/PATH/TO/faxbot/node_mcp",
"env": { "FAX_API_URL": "http://localhost:8080", "API_KEY": "your_api_key" }
}
}
}
Use these tools
- send_fax: { to, filePath } (stdio) or { to, fileContent, fileName, fileType } (HTTP/SSE)
- get_fax_status: { jobId }
- faxbot_pdf (stdio convenience): { pdf_path, to, header_text? } — for text‑based PDFs only; do not use for scanned/image PDFs.
Important notes
- File types: only PDF and TXT. Convert images (PNG/JPG) to PDF first.
- Stdio: use filePath so the MCP reads the file locally and posts it to Faxbot.
- HTTP/SSE: provide base64 content and keep files small (≤ ~100 KB).
- Backends: works with any Faxbot backend (phaxio, sinch, or sip).
- Scanned/image PDFs: use send_fax with filePath to send the original image PDF; do not call faxbot_pdf.
Examples
- “Call send_fax with { to: "+15551234567", filePath: "/Users/me/Documents/letter.pdf" }”
- “Call get_fax_status with { jobId: "
Docker Quick Start (HTTP MCP) - Start the API and MCP via Docker Compose:
docker compose up -d --build api
docker compose --profile mcp up -d --build faxbot-mcp
http://localhost:3001.
- Use this when integrating web clients or cloud AI that speak MCP over HTTP.
- For Claude Desktop or Cursor (stdio), run the MCP directly on the host instead of Docker.
Turnkey SSE (HIPAA‑oriented) via Docker Compose - Node SSE (port 3002):
export OAUTH_ISSUER=https://YOUR_ISSUER
export OAUTH_AUDIENCE=faxbot-mcp
export OAUTH_JWKS_URL=https://YOUR_ISSUER/.well-known/jwks.json
docker compose --profile mcp up -d --build faxbot-mcp-sse
export OAUTH_ISSUER=https://YOUR_ISSUER
export OAUTH_AUDIENCE=faxbot-mcp
export OAUTH_JWKS_URL=https://YOUR_ISSUER/.well-known/jwks.json
docker compose --profile mcp up -d --build faxbot-mcp-py-sse
MCP Inspector (explore tools/resources/prompts) - Start the Inspector UI via Docker:
docker compose --profile mcp up -d mcp-inspector
open http://localhost:6274
npx @modelcontextprotocol/inspector
node node_mcp/src/servers/stdio.js (or python python_mcp/stdio_server.py) with FAX_API_URL and API_KEY env.
- HTTP: set transport “streamable-http” and point to http://localhost:3001.
- SSE: set transport “sse” and point to http://localhost:3002/sse (Node) or http://localhost:3003/sse (Python). Include Authorization: Bearer <JWT>.
Example mcp.json for MCP Inspector
{
"mcpServers": {
"faxbot-node-stdio": {
"type": "stdio",
"command": "node",
"args": ["src/servers/stdio.js"],
"cwd": "./node_mcp",
"env": {
"FAX_API_URL": "http://localhost:8080",
"API_KEY": "your_api_key"
}
},
"faxbot-node-http": {
"type": "streamable-http",
"url": "http://localhost:3001/mcp"
},
"faxbot-node-sse": {
"type": "sse",
"url": "http://localhost:3002/sse"
},
"faxbot-py-stdio": {
"type": "stdio",
"command": "python",
"args": ["stdio_server.py"],
"cwd": "./python_mcp",
"env": {
"FAX_API_URL": "http://localhost:8080",
"API_KEY": "your_api_key"
}
},
"faxbot-py-sse": {
"type": "sse",
"url": "http://localhost:3003/sse"
}
}
}
Authorization: Bearer <JWT> in the Inspector UI headers before connecting.
- If you keep only one server entry or name one default-server, Inspector selects it automatically.
Details
Transports × servers (language matrix)
2 languages × 3 transports = 6 options. Node MCP: - stdio: `node_mcp/src/servers/stdio.js` - HTTP: `node_mcp/src/servers/http.js` (port 3001) - SSE+OAuth: `node_mcp/src/servers/sse.js` (port 3002) Python MCP: - stdio: `python_mcp/stdio_server.py` - HTTP: `python_mcp/http_server.py` - SSE+OAuth: `python_mcp/server.py` Legacy Node servers also exist under `api/` (`mcp_server.js`, `mcp_http_server.js`, `mcp_sse_server.js`).Node MCP start commands
cd node_mcp && npm install
FAX_API_URL=http://localhost:8080 API_KEY=$API_KEY ./scripts/start-stdio.sh # stdio
FAX_API_URL=http://localhost:8080 API_KEY=$API_KEY MCP_HTTP_PORT=3001 ./scripts/start-http.sh
OAUTH_ISSUER=... OAUTH_AUDIENCE=... FAX_API_URL=http://localhost:8080 API_KEY=$API_KEY \
MCP_SSE_PORT=3002 ./scripts/start-sse.sh
Python MCP start commands
cd python_mcp
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
export FAX_API_URL=http://localhost:8080
export API_KEY=your_api_key
python stdio_server.py # stdio
# or: uvicorn http_server:app --host 0.0.0.0 --port 3004
# or: uvicorn server:app --host 0.0.0.0 --port 3003 (SSE+OAuth)
HTTP and SSE details
- HTTP uses Streamable HTTP with sessions: POST `/mcp`, GET `/mcp` (SSE), DELETE `/mcp`. - SSE+OAuth requires Bearer JWT with `iss`/`aud`; JWKS is fetched from the issuer. - Place HTTP/SSE behind auth/rate limits for production.Legacy /api servers
Scripts and Make targets exist under `api/`. These servers are base64‑only for `send_fax`.Voice examples
❌ “Fax document.pdf to +1234567890” (missing file access/base64) ✅ “Call send_fax with { to: "+1234567890", filePath: "/path/to/file.pdf" }” For HTTP/SSE, read and base64‑encode the file before calling `send_fax`.File conversion hints
- macOS Preview: File → Export As… → PDF - macOS CLI: `sips -s format pdf "in.png" --out "out.pdf"` - Linux: `img2pdf in.png -o out.pdf` or `magick convert in.png out.pdf` - Windows: “Print to PDF”.See also: Images vs Text PDFs guide (docs/IMAGES_AND_PDFS.md).