{"id":50553421,"url":"https://github.com/reaatech/webhook-relay-mcp","last_synced_at":"2026-06-04T05:00:52.323Z","repository":{"id":354487483,"uuid":"1223061723","full_name":"reaatech/webhook-relay-mcp","owner":"reaatech","description":"MCP server that receives webhooks from external services and translates them into agent-consumable events. Signature validation, payload normalization, and tools for subscribe/poll/history.","archived":false,"fork":false,"pushed_at":"2026-05-24T00:55:30.000Z","size":418,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-24T01:21:01.233Z","etag":null,"topics":["agentic-ai","ai","ai-agents","mcp","mcp-relay","mcp-server","mcp-tools","model-context-protocol","typescript","webhooks"],"latest_commit_sha":null,"homepage":"https://reaatech.com/products/mcp-infrastructure/webhook-relay-mcp","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/reaatech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-28T01:16:13.000Z","updated_at":"2026-05-24T00:55:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/reaatech/webhook-relay-mcp","commit_stats":null,"previous_names":["reaatech/webhook-relay-mcp"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/reaatech/webhook-relay-mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reaatech%2Fwebhook-relay-mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reaatech%2Fwebhook-relay-mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reaatech%2Fwebhook-relay-mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reaatech%2Fwebhook-relay-mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reaatech","download_url":"https://codeload.github.com/reaatech/webhook-relay-mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reaatech%2Fwebhook-relay-mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33888295,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-04T02:00:06.755Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-ai","ai","ai-agents","mcp","mcp-relay","mcp-server","mcp-tools","model-context-protocol","typescript","webhooks"],"created_at":"2026-06-04T05:00:51.664Z","updated_at":"2026-06-04T05:00:52.307Z","avatar_url":"https://github.com/reaatech.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# webhook-relay-mcp\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](package.json)\n[![MCP SDK](https://img.shields.io/badge/MCP_SDK-^1.29.0-blue)](https://github.com/modelcontextprotocol/sdk)\n\nAn [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that bridges third-party webhooks into agent workflows. Receives webhooks from Stripe, GitHub, Replicate, Twilio, SendGrid, Slack, Vercel, and generic sources, normalizes them into a consistent event format, and exposes them to MCP clients via subscription-based polling.\n\n## Features\n\n- **Multi-source ingestion** — Stripe, GitHub, Replicate, Twilio, SendGrid, Slack, Vercel, and Generic\n- **Signature validation** — HMAC-SHA256/SHA1 verification with constant-time comparison\n- **Advanced filtering** — DSL with 13 operators ($eq, $gt, $in, $regex, $and, $or, $not, etc.) and dot-notation\n- **Event normalization** — Source-specific payloads normalized into a unified schema\n- **Deduplication** — Ingress-level deduplication by webhookId\n- **MCP tools** — 15 tools: subscribe, unsubscribe, list, poll, history, register, stats, replay, update-source, delete-source, rotate-secret, list-sources, audit-log, source-health, event-types\n- **Dual transport** — stdio for local agents, HTTP/SSE for remote agents\n- **Outbound delivery** — Forward events to external URLs with retry and dead-letter queue\n- **Prometheus metrics** — 7 counters/gauges at /metrics endpoint\n- **Admin dashboard** — Built-in web UI at /\n- **MCP authentication** — Optional API key auth for HTTP/SSE connections\n- **Audit logging** — Persistent audit trail of all operations\n- **Source health monitoring** — Heartbeat tracking per webhook source\n- **SQLite storage** — WAL mode, schema migrations, foreign keys\n- **Rate limiting** — In-memory per-IP rate limiting\n- **Event retention** — Configurable automatic cleanup\n- **Docker support** — Multi-stage build with health checks\n\n## Quick Start\n\nRequires **Node.js \u003e= 20**. Building from source additionally requires **pnpm \u003e= 10**.\n\n### Install from npm\n\nThe runnable entry point is **[`@reaatech/webhook-relay-mcp`](https://www.npmjs.com/package/@reaatech/webhook-relay-mcp)**,\nwhich bundles the HTTP ingestion server, MCP transport, and dashboard:\n\n```bash\n# Run directly with npx (no install)\nENCRYPTION_KEY=$(openssl rand -hex 32) npx @reaatech/webhook-relay-mcp\n\n# Or install globally — exposes a `webhook-relay-mcp` binary\nnpm install -g @reaatech/webhook-relay-mcp\nENCRYPTION_KEY=$(openssl rand -hex 32) webhook-relay-mcp\n```\n\nIt starts in MCP **stdio** mode by default (for local agents). Set `MCP_TRANSPORT=sse`\nfor HTTP/SSE. `ENCRYPTION_KEY` is required — see [Configuration](#configuration).\n\n\u003e **Native dependency:** the server transitively depends on\n\u003e [`better-sqlite3`](https://github.com/WiseLibs/better-sqlite3), a native addon.\n\u003e Installation downloads a prebuilt binary when one exists for your platform and Node\n\u003e version; otherwise it compiles from source, which requires a C++ toolchain (e.g.\n\u003e `build-essential` + `python3` on Linux, Xcode Command Line Tools on macOS).\n\n### Published packages\n\n| Package | Role |\n|---------|------|\n| [`@reaatech/webhook-relay-mcp`](https://www.npmjs.com/package/@reaatech/webhook-relay-mcp) | **Runnable server + CLI** (start here) |\n| [`@reaatech/webhook-relay-tools`](https://www.npmjs.com/package/@reaatech/webhook-relay-tools) | MCP server + 15 tools (library) |\n| [`@reaatech/webhook-relay-webhooks`](https://www.npmjs.com/package/@reaatech/webhook-relay-webhooks) | Sources, validators, ingestion (library) |\n| [`@reaatech/webhook-relay-storage`](https://www.npmjs.com/package/@reaatech/webhook-relay-storage) | SQLite storage + services (library) |\n| [`@reaatech/webhook-relay-core`](https://www.npmjs.com/package/@reaatech/webhook-relay-core) | Types, config, crypto, filters (library) |\n\n### From source (development)\n\n```bash\npnpm install\npnpm run build\n```\n\n### Configuration\n\nCopy `.env.example` to `.env` and adjust as needed:\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `NODE_ENV` | `development` | `development`, `production`, or `test` |\n| `PORT` | `3000` | HTTP server port |\n| `HOST` | `0.0.0.0` | HTTP server bind address |\n| `DATABASE_PATH` | `./data/webhook-relay.db` | SQLite database file path |\n| `ENCRYPTION_KEY` | *(required)* | Master key for encrypting webhook secrets at rest |\n| `MCP_TRANSPORT` | `stdio` | `stdio` for local agents, `sse` for HTTP/SSE remote access |\n| `LOG_LEVEL` | `info` | `trace`, `debug`, `info`, `warn`, `error`, or `fatal` |\n| `LOG_FORMAT` | `json` | `json` for structured output, `pretty` for development |\n| `WEBHOOK_BASE_URL` | `http://localhost:3000` | Public-facing base URL for generating webhook endpoint URLs |\n| `EVENT_RETENTION_DAYS` | `30` | Days to retain events before automatic cleanup |\n| `ADMIN_API_KEY` | *(optional)* | API key for securing the `/admin/cleanup` endpoint |\n| `MCP_API_KEY` | *(optional)* | API key for MCP client authentication |\n| `METRICS_ENABLED` | `true` | Enable Prometheus metrics endpoint |\n| `DELIVERY_RETRY_MAX` | `5` | Max retry attempts for outbound delivery |\n| `DELIVERY_RETRY_BACKOFF_MS` | `1000` | Base backoff time for retries (ms) |\n| `SOURCE_HEARTBEAT_MINUTES` | `60` | Expected heartbeat interval for source health |\n| `RATE_LIMIT_WINDOW_MS` | `60000` | Rate limit sliding window in milliseconds |\n| `RATE_LIMIT_MAX_REQUESTS` | `100` | Max requests per window per IP |\n\n### Run\n\n**MCP stdio mode** (default, for local agent use):\n```bash\npnpm start\n```\n\n**HTTP/SSE mode** (for remote agents or multi-client setups):\n```bash\nMCP_TRANSPORT=sse pnpm start\n```\n\n### Docker\n\n```bash\ndocker compose up --build\n```\n\n## MCP Tools\n\n### `webhooks.subscribe`\n\nCreate a subscription for event types with optional TTL and filters.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `eventTypes` | `string[]` | Yes | Event type patterns (supports `*` wildcard, e.g. `\"payment.*\"`) |\n| `filters` | `object` | No | Filter DSL expression (supports operators: $eq, $gt, $in, $regex, $and, $or, $not, etc.) |\n| `ttl` | `number` | No | Subscription TTL in seconds (default: 3600) |\n\n### `webhooks.unsubscribe`\n\nCancel an active subscription by ID.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `subscriptionId` | `string` | Yes | The subscription ID to cancel |\n\n### `webhooks.list`\n\nList subscriptions with optional filtering.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `activeOnly` | `boolean` | No | Return only active subscriptions (default: `true`) |\n| `eventTypes` | `string[]` | No | Filter by matching event type patterns |\n| `limit` | `number` | No | Max results (default: 50, max: 100) |\n\n### `webhooks.poll`\n\nPoll for events matching a subscription. Supports blocking mode for long-polling.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `subscriptionId` | `string` | No | Poll from a specific subscription |\n| `eventTypes` | `string[]` | No | Event type patterns to match |\n| `timeout` | `number` | No | Max wait in seconds (default: 30) |\n| `limit` | `number` | No | Max events to return (default: 10) |\n\n### `webhooks.history`\n\nQuery historical events with cursor-based pagination.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `eventTypes` | `string[]` | No | Filter by event types |\n| `sources` | `string[]` | No | Filter by source (e.g. `\"stripe\"`, `\"github\"`) |\n| `startTime` | `string` | No | ISO 8601 start timestamp |\n| `endTime` | `string` | No | ISO 8601 end timestamp |\n| `correlationId` | `string` | No | Filter by correlation ID |\n| `limit` | `number` | No | Page size (default: 50, max: 100) |\n| `cursor` | `string` | No | Pagination cursor for next page |\n\n### `webhooks.register`\n\nRegister a new webhook source configuration.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `name` | `string` | Yes | Unique name for this source (e.g. `\"stripe-production\"`) |\n| `sourceType` | `string` | Yes | One of: `stripe`, `github`, `replicate`, `twilio`, `sendgrid`, `slack`, `vercel`, `generic` |\n| `signingSecret` | `string` | Yes | Webhook signing secret (encrypted at rest) |\n| `webhookUrl` | `string` | No | Custom endpoint URL (auto-generated from `WEBHOOK_BASE_URL` if omitted) |\n\n### `webhooks.stats`\n\nGet aggregate statistics for webhook events.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `eventTypes` | `string[]` | No | Filter by event types |\n| `sources` | `string[]` | No | Filter by source |\n| `startTime` | `string` | No | ISO 8601 start |\n| `endTime` | `string` | No | ISO 8601 end |\n| `groupBy` | `string` | No | Group by: `type`, `source`, `hour`, `day` |\n\n### `webhooks.replay`\n\nReplay webhook events to trigger downstream processing.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `eventId` | `string` | No | Specific event ID to replay |\n| `startTime` | `string` | No | ISO 8601 start range |\n| `endTime` | `string` | No | ISO 8601 end range |\n| `limit` | `number` | No | Max events (default 10, max 50) |\n\n### `webhooks.update-source`\n\nUpdate an existing webhook source configuration.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `name` | `string` | Yes | Source name to update |\n| `updates` | `object` | Yes | Fields: `newName`, `signingSecret`, `isActive`, `webhookUrl` |\n\n### `webhooks.delete-source`\n\nDelete a webhook source configuration.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `name` | `string` | Yes | Source name to delete |\n\n### `webhooks.rotate-secret`\n\nRotate a webhook signing secret.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `name` | `string` | Yes | Source name |\n| `newSecret` | `string` | Yes | New signing secret (min 8 chars) |\n\n### `webhooks.list-sources`\n\nList registered webhook sources.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `activeOnly` | `boolean` | No | Only active sources (default: `false`) |\n| `sourceType` | `string` | No | Filter by type |\n\n### `webhooks.audit-log`\n\nQuery the persistent audit trail of all operations.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `actor` | `string` | No | Filter by actor |\n| `action` | `string` | No | Filter by action |\n| `resourceType` | `string` | No | Filter by resource type |\n| `startTime` | `string` | No | ISO 8601 start |\n| `endTime` | `string` | No | ISO 8601 end |\n| `limit` | `number` | No | Max results (default 50, max 100) |\n\n### `webhooks.source-health`\n\nCheck heartbeat status for webhook sources.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `name` | `string` | No | Specific source name (all if omitted) |\n\n### `webhooks.event-types`\n\nList available event types across registered sources.\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `source` | `string` | No | Filter by source |\n\n## HTTP Endpoints\n\n| Method | Path | Description |\n|--------|------|-------------|\n| `GET` | `/` | Admin dashboard web UI |\n| `GET` | `/health` | Basic health check with version |\n| `GET` | `/health/ready` | Readiness probe |\n| `GET` | `/metrics` | Prometheus metrics endpoint |\n| `POST` | `/admin/cleanup` | Trigger event retention cleanup (requires `ADMIN_API_KEY` in production) |\n| `POST` | `/webhooks/:name` | Ingest webhook for a registered source (`:name` = registered source name) |\n| `GET` | `/webhooks/:name/verify` | Webhook verification handshake (hub challenge) |\n| `POST` | `/mcp` | MCP HTTP/SSE transport endpoint (initialize sessions) |\n| `GET` | `/mcp` | MCP HTTP/SSE transport (streaming GET) |\n| `DELETE` | `/mcp` | MCP HTTP/SSE transport (session termination) |\n\n\u003e **Note:** The webhook ingestion path uses the registered source *name* (e.g. `stripe-production`), not the source type. This allows multiple configurations per source type (e.g. `stripe-test` and `stripe-production`).\n\n## Supported Webhook Sources\n\n### Stripe\n\n- Validates `Stripe-Signature` header (v1 scheme with timestamp tolerance of 5 minutes)\n- Event type mapping: `invoice.payment_succeeded` → `payment.completed`, `customer.subscription.created` → `subscription.created`, etc.\n\n### GitHub\n\n- Validates `X-Hub-Signature-256` header (HMAC-SHA256)\n- Combines `X-GitHub-Event` header with payload `action` field for event type\n\n### Replicate\n\n- Optional signature validation via `webhook-secret` header\n- Derives event type from payload `status` field\n\n### Twilio\n\n- HMAC-SHA1 validation of the full request URL with sorted form params\n- Separate event type mapping for SMS and Voice status callbacks\n\n### SendGrid\n\n- Validates `X-SendGrid-Signature` header (HMAC-SHA256), batch event payloads\n- 11 email event type mappings\n\n### Slack\n\n- Custom v0 signature format (HMAC-SHA256 of `v0:timestamp:body`)\n- Events API payload structure, interactive message support\n\n### Vercel\n\n- Validates `x-vercel-signature` header (HMAC-SHA1)\n- 9 deployment/project/domain event type mappings\n\n### Generic\n\n- Configurable HMAC algorithm via `x-signature-algorithm` header\n- Pass-through normalization (preserves original payload structure)\n\n## Architecture\n\n```\n                   ┌──────────────────────────────────────────────────────────────┐\n                   │                     webhook-relay-mcp                          │\n                   │                                                               │\nExternal Services  │  ┌──────────┐  ┌───────────┐  ┌──────────┐  ┌─────────────┐ │  ┌───────────┐\n┌───────────────┐  │  │ Express  │  │ Signature │  │ SQLite   │  │   Outbound  │ │  │    MCP    │\n│ Stripe        │──┼─▶│ HTTP     │─▶│ Validator │─▶│ (WAL)    │─▶│   Delivery  │─┼─▶│  Clients  │\n│ GitHub        │──┼─▶│ Server   │  │           │  │          │  │   Engine    │ │  │ (Agents)  │\n│ Replicate     │──┼─▶│          │  │ Normalize │  │ Events   │  │  + Retry    │ │  │           │\n│ Twilio        │──┼─▶│ /webhooks│  └───────────┘  │ Subscrip │  │  + DLQ      │ │  │ stdio or  │\n│ SendGrid      │──┼─▶│ /:name   │                 │ tions    │  └─────────────┘ │  │ HTTP/SSE  │\n│ Slack         │──┼─▶│          │  ┌───────────┐  │ Audit    │                  │  │           │\n│ Vercel        │──┼─▶│          │  │ Advanced  │  │ Log      │  ┌───────────┐  │  │ 15 tools  │\n│ Generic       │──┼─▶│          │  │ Filter    │  │ Sources  │  │ Prometheus│  │  │           │\n└───────────────┘  │  └──────────┘  │ DSL ($gt, │  │ Health   │  │ /metrics  │  │  └───────────┘\n                   │               │ $in, ...)  │  │          │  └───────────┘  │\n                   │               └───────────┘  │          │                 │\n                   │                              └──────────┘                 │\n                   │                                    │                      │\n                   │                    ┌───────────────┘                      │\n                   │                    ▼                                      │\n                   │              ┌───────────┐  ┌───────────┐               │\n                   │              │   Admin   │  │    MCP    │               │\n                   │              │ Dashboard │  │   Auth    │               │\n                   │              │    (/)    │  │ (API Key) │               │\n                   │              └───────────┘  └───────────┘               │\n                   └──────────────────────────────────────────────────────────────┘\n```\n\n**Data flow**: External webhook → signature validation → payload normalization → deduplication check → SQLite storage → notify matching poll waiters → MCP clients receive events. Outbound delivery forwards events to external URLs with retry and dead-letter queue.\n\n## Development\n\n```bash\n# Start dev server with hot reload\npnpm run dev\n\n# Run all tests\npnpm run test\n\n# Run tests in watch mode\npnpm run test:watch\n\n# Run tests with coverage report\npnpm run test:coverage\n\n# Run all quality checks\npnpm run typecheck \u0026\u0026 pnpm run lint \u0026\u0026 pnpm run test \u0026\u0026 pnpm run build\n\n# Format code\npnpm run format\n\n# Check formatting (CI)\npnpm run format:check\n```\n\n### Project Structure\n\n```\npackages/\n├── core/                      # Shared types, config, crypto, validation, filters, metrics\n├── storage/                   # SQLite, repositories, migrations, services\n│   ├── repositories/          # Events, Subscriptions, Sources, Audit\n│   └── services/              # Cleanup, Delivery, Audit, SourceHealth, PollWaiter\n├── webhooks/                  # Ingest, validators, source handlers\n│   ├── sources/               # stripe, github, replicate, twilio, sendgrid, slack, vercel, generic\n│   └── validators/            # HMAC, Stripe, GitHub, Slack, Twilio\n├── mcp/                       # MCP server, tool implementations (15 tools)\n│   └── tools/\n└── server/                    # Express HTTP server, middleware, dashboard\n    └── middleware/             # RateLimit, RawBody, MCPAuth\n```\n\n## Security\n\n- **Signature validation**: All webhooks validated with `crypto.timingSafeEqual` for constant-time comparison\n- **Secrets at rest**: Signing secrets encrypted with AES-256-GCM\n- **MCP authentication**: Optional API key auth for HTTP/SSE connections via `X-API-Key` or `Authorization: Bearer`\n- **Audit logging**: Persistent audit trail of all MCP tool operations in the audit_log table\n- **Rate limiting**: In-memory per-IP sliding window rate limiting on all webhook ingestion endpoints\n- **Input validation**: All inputs validated with Zod schemas; SQL injection prevented via parameterized queries\n- **Deduplication**: Webhook-level deduplication by `webhookId` prevents replay attacks\n- **Admin auth**: `ADMIN_API_KEY` secures the `/admin/cleanup` endpoint in production\n\n## Limitations\n\n- **Single-instance polling**: `webhooks.poll` blocking mode uses in-memory waiters per process. In a horizontally-scaled deployment, a webhook arriving on one instance will not wake a poller on another instance. Use non-blocking polling (`timeout: 0`) for multi-instance deployments, or deploy as a single instance.\n- **In-memory rate limiting**: Rate limits are not shared across instances behind a load balancer. For multi-instance deployments, use an external rate limiting solution.\n- **SQLite scalability**: SQLite with WAL mode supports moderate concurrency but is not designed for high-throughput distributed workloads. Consider migrating to PostgreSQL for large-scale production deployments.\n\n## License\n\nMIT — see [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freaatech%2Fwebhook-relay-mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freaatech%2Fwebhook-relay-mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freaatech%2Fwebhook-relay-mcp/lists"}