{
  "markdown": "# Agent Broker  -  SMB Transaction & Communication MCP Server\n\n> **An agent-callable MCP server** that lets autonomous AI agents find, verify, message, schedule with, and transact with small and mid-sized businesses (SMBs) through a single compliance-enforced tool surface.\n\n[![smithery badge](https://smithery.ai/badge/lordbasil147/agent-broker)](https://smithery.ai/servers/lordbasil147/agent-broker)\n[![MCP](https://img.shields.io/badge/MCP-streamable--http-blue)](https://hatchloop.dev/mcp/agent-broker)\n[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)\n[![Python](https://img.shields.io/badge/python-3.11%2B-blue)](https://www.python.org/)\n[![Edge](https://img.shields.io/badge/edge-cloudflare%20workers-orange)](./edge)\n[![Registry](https://img.shields.io/badge/MCP%20Registry-listed-green)](https://github.com/modelcontextprotocol/servers)\n<!-- NO STATIC TEST BADGE. A shields.io badge is a literal in a\n     URL: it rendered \"103/103 passing\" in green whether or not\n     the suite passed, and the real count is over a thousand. A\n     badge that cannot fail is decoration pretending to be\n     evidence. The CI run on the commit is the evidence. -->\n[![CI](https://github.com/basilalshukaili/agentbroker/actions/workflows/ci.yml/badge.svg)](https://github.com/basilalshukaili/agentbroker/actions/workflows/ci.yml)\n\n**Live endpoint:** `https://hatchloop.dev/mcp/agent-broker` (streamable-http, always-on Cloudflare edge)\n\n---\n\n## Why this exists\n\nThere are tens of millions of long-tail small businesses in the US  -  barbers, plumbers, accountants, home cleaners  -  and they have **no API surface**. AI agents that need to schedule a haircut, get a quote, or send a confirmation today must either drive a browser, cold-call by voice, or give up.\n\nThis server is the missing middle layer. Agents call us; we route to the right SMB through whichever channel reaches them fastest  -  Cal.com -> WhatsApp -> SMS -> voice AI -> email  -  with full TCPA / GDPR / CASL / 10DLC compliance enforced as a non-bypassable gate.\n\n---\n\n## Current status (honest)\n\n| Capability | Status |\n|---|---|\n| MCP endpoint (streamable-http) | **Live**  -  `https://hatchloop.dev/mcp/agent-broker` |\n| 23 MCP tools | **Live** (callable today) |\n| Compliance gate (TCPA/GDPR/CASL) | **Live** |\n| REST + A2A + OpenAI/Anthropic tool surfaces | **Live** |\n| SMB supply network | **Demo**  -  20+ seed SMBs; demo bookings return `demo_smb_no_live_booking` |\n| Billing | **Live**  -  12 utility tools free (no key, unmetered). Premium data tools (company verification, sanctions, trade screening): free up to a daily limit (500/day with a free key, 100/day anonymous), then $0.02/call via credits. Write tools: free email-verified key (100 ops/day) at hatchloop.dev/agent-broker; credit packages from $9/1,000 credits at hatchloop.dev/pricing;. |\n| x402 payment rail | **Offered, opt-in.** Enabled on the service since the founder lifted the crypto restriction on 2026-08-29. A caller attaches a payment in `params._meta[\"x402/payment\"]` and the call is served without a key (USDC on Base, proven once on mainnet, tx 0x38a0d9ec). Callers who do not attach one fall through to credits and the free quota, so nothing is gated behind it. `/.well-known/x402` is still a 404 - discovery is via `/.well-known/mcp.json`, which lists the rail. |\n| Production SMB onboarding | **Planned**  -  real businesses not yet enrolled |\n\n> The MCP server is live and callable right now. Bookings hit demo data. 12 utility tools are free (no key, unmetered). Premium data tools (verify_company_record, screen_sanctions, map_trade_restriction) are free up to a daily limit; beyond that, $0.02/call via credits. Write tools require a free email-verified key (100 ops/day)  -  get one at https://hatchloop.dev/agent-broker. Credit packages from $9/1,000 credits at https://hatchloop.dev/pricing.\n\n---\n\n## 23 MCP Tools\n\nAll tools are callable via MCP, REST, OpenAI function calling, Anthropic tool_use, or A2A protocol.\n\n| # | Tool | What it does | Auth |\n|---|---|---|---|\n| 1 | `find_business` | Search SMBs by vertical, location, and capability | **free** |\n| 2 | `verify_business` | Confirm an SMB is real, operating, and capable of the requested service | **free** |\n| 3 | `get_status` | Poll the current state of an async operation | **free** |\n| 4 | `get_outcome` | Retrieve the final `OutcomeReceipt` (with cost and reason codes) | **free** |\n| 5 | `preview_cost` | Estimate cost, latency, and success probability before committing | **free** |\n| 6 | `self_test` | Verify service health and all claimed capabilities are responding | **free** |\n| 7 | `check_quota` | Inspect your remaining daily quota and tier without consuming any ops  -  call at session start or after a rate_limited error | **free** |\n| 8 | `check_booking_link` | Classify a URL and confirm import_booking_url will accept it  -  sub-100ms pre-flight | **free** |\n| 9 | `check_compliance` | Preview TCPA/GDPR/CASL/10DLC gate result before spending a paid send | **free** |\n| 10 | `verify_company_record` | Live GLEIF LEI registry + SEC EDGAR lookup  -  official legal name, status, jurisdiction, address | **free up to daily limit** |\n| 11 | `screen_sanctions` | Check a name or entity against OFAC SDN, the EU Consolidated list and the UK Sanctions List | **free up to daily limit** |\n| 12 | `map_trade_restriction` | OFAC country embargoes + export-control Entity List + sanctioned-party screening for a proposed shipment | **free up to daily limit** |\n| 13 | `get_conversation` | Read a two-way thread you started: state, full transcript, reply count | **free** |\n| 14 | `lookup_us_contracts` | Search US federal contract awards by company name via USASpending.gov  -  awardee, agency, amount, NAICS, period | **free** |\n| 15 | `send_message` | Send WhatsApp, SMS, email, or voice with compliance pre-check enforced | key |\n| 16 | `capture_lead` | Structured intake of a prospect into the SMB's AgentBroker lead store (not the business's own CRM), deduplicated | key |\n| 17 | `schedule_appointment` | Book, reschedule, or cancel via the direct booking API (Cal.com); SMBs reachable only through async channels fail honestly until a background worker is deployed | key |\n| 18 | `send_transactional_confirmation` | TCPA-exempt OTPs, booking confirmations, receipts | key |\n| 19 | `handle_inbound` | Classify inbound messages: booking / cancel / opt-out / question / complaint | key |\n| 20 | `escalate_to_human` | Hand off a stuck or ambiguous task to a human operator with full context | key |\n| 21 | `import_booking_url` | Turn any Cal.com, Calendly, Doctolib, Booksy, OpenTable, Square, Acuity, or Fresha URL into a bookable SMB record | key |\n| 22 | `call_business` | Place a conversational voice-AI phone call to a business on behalf of a consumer | key |\n| 23 | `mint_key` | Issue a free-tier agent identity key via HMAC proof - no email required, no human in the loop | **free** |\n\nFree key (100 write ops/day + 500 premium data calls/day): https://hatchloop.dev/agent-broker  -  Credits from $9/1,000 ops: https://hatchloop.dev/pricing  -  Premium data beyond quota: $0.02/call\n\n---\n\n## Verifiable compliance receipts\n\n`screen_sanctions` and `check_compliance` attach a **compliance receipt**: a\nhash-bound record of which list copies were screened (and how fresh they were),\nwhich ruleset decided, what inputs it was given, and what it returned. It is\nsigned with **Ed25519** and verifiable **offline**  -  months later, with no call\nback to us. It asserts facts about *our system's actions only*; it never claims\n\"this party is clean.\"\n\nVerify one in ~12 lines (pin the public key from\n[hatchloop.dev/agents.md](https://hatchloop.dev/agents.md)):\n\n```python\nimport json, hashlib\nfrom cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey\n\nPINNED_KEY_HEX = \"<hex public key from hatchloop.dev/agents.md>\"\n\nreceipt = json.load(open(\"receipt.json\"))          # the compliance_receipt object\npayload, integrity = receipt[\"payload\"], receipt[\"integrity\"]\n\ncanonical = json.dumps(payload, sort_keys=True, separators=(\",\", \":\"),\n                       ensure_ascii=True, allow_nan=False).encode()\nassert integrity[\"payload_sha256\"] == \"sha256:\" + hashlib.sha256(canonical).hexdigest()\n\nEd25519PublicKey.from_public_bytes(bytes.fromhex(PINNED_KEY_HEX)).verify(\n    bytes.fromhex(integrity[\"signature\"]), canonical)   # raises if tampered\n```\n\nIf no signing key is configured on the server, the receipt says\n`signature_status: \"unsigned\"` with the reason  -  it never claims a signature it\ndoes not have.\n\n---\n\n## Quick start\n\n### Connect via MCP (Claude Desktop, Cursor, Cline, Continue, etc.)\n\n```json\n{\n  \"mcpServers\": {\n    \"agent-broker\": {\n      \"url\": \"https://hatchloop.dev/mcp/agent-broker\"\n    }\n  }\n}\n```\n\n**15 tools require no key.** 12 are always free (find_business, verify_business, check_booking_link, check_compliance, get_conversation, get_status, get_outcome, preview_cost, self_test, check_quota, mint_key, lookup_us_contracts) and 3 more are free within a daily quota (verify_company_record, screen_sanctions, map_trade_restriction).\n\n**Write tools** require an `X-Agent-Identity` bearer token:\n- Free email-verified key (100 ops/day): https://hatchloop.dev/agent-broker\n- **Machine-mintable key (no email, agent self-serve):** `POST https://api.hatchloop.dev/keys/mint` - see [Machine-mintable keys](#machine-mintable-keys) below.\n- Credits from $9/1,000 ops: https://hatchloop.dev/pricing\n\nAdd your key to the config once you have one:\n\n```json\n{\n  \"mcpServers\": {\n    \"agent-broker\": {\n      \"url\": \"https://hatchloop.dev/mcp/agent-broker\",\n      \"headers\": {\n        \"X-Agent-Identity\": \"Bearer YOUR_KEY_HERE\"\n      }\n    }\n  }\n}\n```\n\n### Or via npx (stdio transport)\n\n```bash\nnpx agentbroker-mcp\n```\n\nWith a key:\n\n```bash\nAGENT_BROKER_KEY=your_key npx agentbroker-mcp\n```\n\n### Discover tools (JSON-RPC)\n\n```bash\ncurl -X POST https://hatchloop.dev/mcp/agent-broker \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}}'\n```\n\n### Call a tool (JSON-RPC)\n\n```bash\ncurl -X POST https://hatchloop.dev/mcp/agent-broker \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"jsonrpc\": \"2.0\",\n    \"id\": 2,\n    \"method\": \"tools/call\",\n    \"params\": {\n      \"name\": \"find_business\",\n      \"arguments\": {\n        \"vertical\": \"personal_services\",\n        \"location\": {\"zip_or_city\": \"30309\"},\n        \"capability\": \"haircut\"\n      }\n    }\n  }'\n```\n\n### OpenAI function calling\n\n```python\nimport httpx, openai\ntools = httpx.get(\n    \"https://hatchloop.dev/.well-known/openai-tools.json\"\n).json()[\"tools\"]\nclient = openai.OpenAI()\nresp = client.chat.completions.create(\n    model=\"gpt-4o\",\n    messages=[{\"role\": \"user\", \"content\": \"Book a haircut in Atlanta Saturday under $50\"}],\n    tools=tools,\n)\n```\n\n### Anthropic tool use\n\n```python\nimport httpx, anthropic\ntools = httpx.get(\n    \"https://hatchloop.dev/.well-known/anthropic-tools.json\"\n).json()[\"tools\"]\nclient = anthropic.Anthropic()\nmsg = client.messages.create(\n    model=\"claude-opus-4-5\",\n    max_tokens=1024,\n    tools=tools,\n    messages=[{\"role\": \"user\", \"content\": \"Book a haircut in Atlanta Saturday under $50\"}],\n)\n```\n\n### Plain REST\n\n```bash\ncurl -X POST https://hatchloop.dev/ops/find_business \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"vertical\":\"personal_services\",\"location\":{\"zip_or_city\":\"30309\"},\"capability\":\"haircut\"}'\n```\n\n---\n\n## Machine-mintable keys\n\nAI agents that cannot receive email can self-provision a free-tier API key (100 gated ops/day) by proving identity via HMAC-SHA256.\n\n### How it works\n\n1. Obtain the `MACHINE_MINT_SECRET` from [hatchloop.dev/docs/#machine-mint](https://hatchloop.dev/docs/#machine-mint).\n2. Compute the signature:\n   ```\n   signature = HMAC-SHA256(agent_id + str(timestamp) + nonce, MACHINE_MINT_SECRET)\n   ```\n   The HMAC input is the **raw concatenation** of the three fields (no separators). Digest must be lowercase hex.\n3. POST to `https://api.hatchloop.dev/keys/mint`:\n\n```json\n{\n  \"agent_id\": \"my-agent-abc123\",\n  \"timestamp\": 1725100000,\n  \"nonce\": \"4f8a2c1d9e2b7c6a\",\n  \"signature\": \"<lowercase-hex-hmac>\"\n}\n```\n\n### Response\n\n```json\n{\n  \"ok\": true,\n  \"key\": \"<JWT - use as X-Agent-Identity header>\",\n  \"key_id\": \"free_machine_<hash>\",\n  \"expires_at\": \"2026-11-28\",\n  \"tier\": \"free\",\n  \"daily_limit\": 100,\n  \"usage\": \"Send as the X-Agent-Identity header on every call to https://hatchloop.dev/mcp/agent-broker\"\n}\n```\n\n### Constraints\n- `timestamp` must be within **60 seconds** of server time (prevents replay attacks).\n- Use a fresh `nonce` on every call (UUID or random hex).\n- `agent_id` is a stable identifier for your agent; the issued key is tied to its SHA-256 hash.\n- Returns `401 {error: \"invalid_request\"}` on bad signature or stale timestamp.\n- Returns `503 {error: \"not_configured\"}` if the server secret has not been set (contact hello@hatchloop.dev).\n\n---\n\n## Discovery surfaces\n\n| Surface | URL |\n|---|---|\n| **MCP (streamable-http)** | `https://hatchloop.dev/mcp/agent-broker` |\n| MCP descriptor | `https://hatchloop.dev/.well-known/mcp.json` |\n| OpenAI function tools | `https://hatchloop.dev/.well-known/openai-tools.json` |\n| Anthropic tool_use | `https://hatchloop.dev/.well-known/anthropic-tools.json` |\n| A2A (Agent-to-Agent) | `https://hatchloop.dev/.well-known/agents.json` |\n| OpenAI ChatGPT plugin | `https://hatchloop.dev/.well-known/ai-plugin.json` |\n| llms.txt | `https://hatchloop.dev/llms.txt` |\n| OpenAPI 3.1 | `https://hatchloop.dev/openapi.yaml` |\n| npm shim (stdio) | `npx agentbroker-mcp` |\n| Glama MCP Registry | Listed via [`glama.json`](./glama.json) |\n| MCP Registry | Listed via [`server.json`](./server.json) |\n\n---\n\n## Architecture\n\n```\nAI agent\n   |\n   v  MCP / REST / A2A\nCloudflare Worker edge  (hatchloop.dev)\n   |  300+ PoPs globally -- discovery served from edge bundle in 40-70 ms\n   |\n   +-- GET /.well-known/* /manifest /llms.txt  --> embedded snapshot (40-70 ms)\n   +-- POST /mcp  initialize / tools/list      --> embedded snapshot (40-65 ms)\n   +-- POST /mcp  tools/call  /ops/*           --> proxy to origin  (170-190 ms)\n                |\n                v\n        Python FastAPI  (api.hatchloop.dev)\n                |  Cron keep-alive every 2 min (eliminates Render cold starts)\n                |\n                +-- 23 operation handlers  (core/)\n                +-- Compliance gate        (compliance/pre_check)\n                +-- Channel adapters       (channels/ -- Twilio, Cal.com, Vapi, SendGrid)\n                +-- Billing + outcome store\n                +-- All .well-known / MCP endpoints (also served from edge bundle)\n```\n\nThe edge worker can outlive the origin: discovery still works even if the origin is down. Idempotency is keyed by `(agent_id, operation, idempotency_key)` with 24h TTL. Async operations return `pending_async`; poll with `get_status` / `get_outcome`.\n\n---\n\n## Compliance\n\nEvery outbound communication passes through `compliance/pre_check()`:\n\n1. **Content classification**  -  blocks restricted categories (gambling, adult, cannabis, spam)\n2. **Opt-out check**  -  TCPA STOP keyword, GDPR right-to-be-forgotten, CASL\n3. **Consent check**  -  TCPA written consent, GDPR opt-in, CASL implied/express\n4. **10DLC registry check**  -  US SMS campaign compliance\n5. **Two-party recording consent**  -  CA, FL, IL, MD, MA, MT, NV, NH, PA, WA\n6. **Audit log**  -  PII stored as SHA-256 hash, never plaintext\n\nViolations surface as `ComplianceViolationError` and are never silently bypassed.\n\n---\n\n## Repo layout\n\n```\nagentbroker/\n+-- core/                  # 23 operation handlers + shared Pydantic models\n+-- channels/              # Twilio, SendGrid, Vapi, Bland, Cal.com, Playwright\n+-- compliance/            # pre_check, jurisdiction_rules, consent_store, audit_log\n+-- reliability/           # retry, circuit_breaker, channel_fallback, async_runner\n+-- billing/               # meter, budget_guard, receipt_signer, pricing_tiers\n+-- telemetry/             # tracer, log_redactor, metrics_emitter\n+-- storage/               # outcome_store, idempotency_store\n+-- supply/                # smb_directory (20+ seed/demo SMBs)\n+-- onboarding/            # self_serve, verification_flow, channel_capture\n+-- feedback/              # failure_classifier, attribution_engine, outcome_evaluator\n+-- optimizer/             # ab_router, selection_analytics, weekly_report\n+-- agent_interface/       # manifest_server, mcp_server, well_known, identity, webhooks\n+-- manifest/              # manifest.json, mcp_tools.json, openapi.yaml\n+-- api/                   # errors.md, identity.md, async.md\n+-- docs/                  # mission, architecture, compliance, ADRs\n+-- edge/                  # Cloudflare Worker (TypeScript/Hono)\n+-- deploy/                # Dockerfile, docker-compose.yml\n+-- tests/                 # unit, contract, compliance, fault_injection, agent_sim\n+-- main.py                # FastAPI entry point\n+-- config.py              # Centralized config from env\n+-- requirements.txt\n```\n\n---\n\n## Local development\n\n```bash\n# Install dependencies\npip install -r requirements.txt\n\n# Run tests (1173 passing at the time of writing)\npython -m pytest tests/ -q\n\n# Start the API\npython main.py\n# --> http://localhost:8000/docs      (Swagger UI)\n# --> http://localhost:8000/mcp       (MCP endpoint)\n# --> http://localhost:8000/manifest  (capability manifest)\n\n# Run the agent simulation harness\npython -m tests.agent_sim.harness\n\n# Self-test\npython -c \"import asyncio; from agent_interface.self_test import run_self_test; print(asyncio.run(run_self_test()).all_passed)\"\n```\n\nOr with Docker:\n\n```bash\ndocker compose -f deploy/docker-compose.yml up\n```\n\n---\n\n## Documentation\n\n- [Architecture](./docs/architecture.md)  -  module map, data flow, fallback chains\n- [Compliance](./docs/compliance.md)  -  full jurisdiction matrix, pre-check sequence\n- [Agent integration guide](./docs/AGENT_INTEGRATION_GUIDE.md)  -  copy-paste examples for every protocol\n- [API errors](./api/errors.md)  -  16 error codes with retry semantics\n- [API identity](./api/identity.md)  -  Agent-Identity JWT spec\n- [API async](./api/async.md)  -  execution profiles, polling rules, webhook contract\n- [Benchmarks](./docs/BENCHMARKS.md)  -  measured WinRate, latency, cost vs alternatives\n- [Mission](./docs/mission.md)  -  north-star metric and scope\n\n---\n\n## Contributing\n\nLicensed under MIT. Issues and discussion are welcome  -  open a GitHub issue to report bugs or suggest features. For substantial changes, please open an issue first to discuss direction. Note: this repo is the open-source server; the hosted service at hatchloop.dev (supply index, billing rails) is operated by Hatchloop.\n\n---\n\n## License\n\nMIT  -  see [LICENSE](LICENSE). The hosted service and its supply/billing data are operated separately by Hatchloop.\n\n---\n\n*Built by [Basil Al-Shukaili](https://github.com/basilalshukaili). Listed on the [MCP Registry](https://github.com/modelcontextprotocol/servers) and [Glama](https://glama.ai/mcp/servers).*\n",
  "bytes": 19062,
  "sha": "f143e3085d95fe450de27b8c9d79b64cd84c4255785c932e4e631764e1fea8a0",
  "repo_slug": "basilalshukaili/agentbroker",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_dev_hatchloop_agent_broker_8e916b98/readme"
}