Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 59 additions & 176 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,43 @@
# github-webhook-mcp

GitHub webhook receiver and local MCP extension for GitHub notification workflows.
Real-time GitHub webhook notifications for Claude via Cloudflare Worker + Durable Object.

## Description
## Architecture

`github-webhook-mcp` receives GitHub webhook events, persists them to a local `events.json`, and exposes them to AI agents through MCP tools.
It is designed for notification-style workflows where an AI can poll lightweight summaries, inspect a single event in detail, and mark handled events as processed.

Detailed behavior, event metadata, trigger semantics, and file responsibilities live in [docs/0-requirements.md](docs/0-requirements.md).

## Features
```
GitHub ──POST──▶ Cloudflare Worker ──▶ Durable Object (SQLite)
├── MCP tools (Streamable HTTP)
├── SSE real-time stream
┌────────────────┘
Desktop / Codex: .mcpb local bridge ──▶ polling via MCP tools
Claude Code CLI: .mcpb local bridge ──▶ SSE → channel notifications
```

- Receives GitHub webhook events over HTTPS and persists them locally.
- Exposes pending events to MCP clients through lightweight polling tools.
- Supports real-time `claude/channel` notifications in Claude Code.
- Supports direct trigger mode for immediate Codex reactions per event.
- Ships as a Node-based `.mcpb` desktop extension and as an `npx` MCP server.
- **Cloudflare Worker** receives GitHub webhooks, verifies signatures, stores events in a Durable Object with SQLite.
- **Local MCP bridge** (.mcpb) proxies tool calls to the Worker and optionally listens to SSE for real-time channel notifications.
- No local webhook receiver or tunnel required.

## Prerequisites

| Component | Required for | Install |
|-----------|-------------|---------|
| **Python 3.12+** | Webhook receiver | [python.org](https://www.python.org/downloads/) — check "Add python to PATH" during install |
| **Node.js 18+** | MCP server (`npx`) | [nodejs.org](https://nodejs.org/) |
| **NSSM** *(optional)* | Running receiver as a Windows service | [nssm.cc](https://nssm.cc/) — extract and add to PATH |

> Only install what you need. If you only use the `.mcpb` desktop extension, Python alone is sufficient for the receiver.
| Component | Required |
|-----------|----------|
| **Node.js 18+** | MCP server |
| **Cloudflare account** | Worker deployment (self-hosting) |

## Installation

### Claude Desktop — Desktop Extension (.mcpb)

Download `mcp-server.mcpb` from [Releases](https://github.com/Liplus-Project/github-webhook-mcp/releases), then:

1. Open Claude Desktop → **Settings** → **Extensions** → **Advanced settings** → **Install Extension...**
1. Open Claude Desktop → **Settings** → **Extensions** → **Install Extension...**
2. Select the `.mcpb` file
3. Enter the path to your `events.json` when prompted

### Claude Desktop / Claude Code — npx
3. Enter your Worker URL when prompted (e.g. `https://github-webhook-mcp.example.workers.dev`)

Add to your Claude MCP config (`claude_desktop_config.json` or project settings):
### Claude Code CLI — npx

```json
{
Expand All @@ -48,13 +46,16 @@ Add to your Claude MCP config (`claude_desktop_config.json` or project settings)
"command": "npx",
"args": ["github-webhook-mcp"],
"env": {
"EVENTS_JSON_PATH": "/path/to/events.json"
"WEBHOOK_WORKER_URL": "https://github-webhook-mcp.example.workers.dev",
"WEBHOOK_CHANNEL": "1"
}
}
}
}
```

Set `WEBHOOK_CHANNEL=1` to enable real-time channel notifications (Claude Code CLI only).

### Codex — config.toml

```toml
Expand All @@ -63,189 +64,71 @@ command = "npx"
args = ["github-webhook-mcp"]

[mcp.github-webhook-mcp.env]
EVENTS_JSON_PATH = "/path/to/events.json"
WEBHOOK_WORKER_URL = "https://github-webhook-mcp.example.workers.dev"
WEBHOOK_CHANNEL = "0"
```

### Python (legacy)
## Self-Hosting the Worker

```json
{
"mcpServers": {
"github-webhook-mcp": {
"command": "python",
"args": ["/path/to/github-webhook-mcp/main.py", "mcp"]
}
}
}
```

## Configuration

### 1. Install receiver dependencies
### 1. Deploy to Cloudflare

```bash
pip install -r requirements.txt
cd worker
npm install
npx wrangler deploy
```

### 2. Start the webhook receiver
### 2. Set the webhook secret

```bash
WEBHOOK_SECRET=your_secret python main.py webhook --port 8080 --event-profile notifications
npx wrangler secret put GITHUB_WEBHOOK_SECRET
```

### 3. Set up Cloudflare Tunnel
### 3. Configure the GitHub webhook

```bash
cloudflared tunnel login
cloudflared tunnel create github-webhook-mcp
cp cloudflared/config.yml.example ~/.cloudflared/config.yml
# Edit config.yml with your tunnel ID and domain
cloudflared tunnel run
```

### 4. Configure the GitHub webhook

- Payload URL: `https://webhook.yourdomain.com/webhook`
- Payload URL: `https://your-worker.workers.dev/webhooks/github`
- Content type: `application/json`
- Secret: same value as `WEBHOOK_SECRET`
- Recommended event profile:
- Issues
- Issue comments
- Pull requests
- Pull request reviews
- Pull request review comments
- Check runs
- Workflow runs
- Discussions
- Discussion comments

If your webhook is temporarily set to `Send me everything`, start the receiver with `--event-profile notifications` and it will ignore noisy events such as `workflow_job` or `check_suite`.
- Secret: same value as the Cloudflare secret
- Events: select the events you want to receive

### 5. Optional direct trigger mode
### 4. Optional: Channel notifications

Use the bundled Codex wrapper if you want the webhook to launch `codex exec` immediately.
The local MCP bridge supports Claude Code's `claude/channel` capability. When enabled, new webhook events are pushed into your session via SSE in real-time.

```bash
python main.py webhook \
--port 8080 \
--event-profile notifications \
--trigger-command "python codex_reaction.py --workspace /path/to/workspace --output-dir /path/to/github-webhook-mcp/codex-runs"
```

If you want Codex to resume an existing app thread instead of writing markdown output:

```text
python codex_reaction.py --workspace /path/to/workspace --resume-session <thread-or-session-id>
```

If you want webhook delivery to stay notification-only for a workspace, create a `.codex-webhook-notify-only`
file in that workspace. The bundled wrapper will skip direct Codex execution and leave the event pending.

### 6. Optional: Run the receiver as a Windows service (NSSM)

[NSSM (Non-Sucking Service Manager)](https://nssm.cc/) wraps any executable as a Windows service, so the webhook receiver starts automatically on boot without a console window.

```powershell
# Install the service (opens a GUI)
nssm install github-webhook-mcp

# Set the following in the GUI:
# Path: C:\Users\<you>\AppData\Local\Programs\Python\Python312\python.exe
# Startup dir: C:\Users\<you>\github-webhook-mcp
# Arguments: main.py webhook --port 8080 --event-profile notifications
claude --dangerously-load-development-channels server:github-webhook-mcp
```

Or configure non-interactively from an **elevated** PowerShell:
## MCP Tools

```powershell
nssm install github-webhook-mcp "C:\Users\<you>\AppData\Local\Programs\Python\Python312\python.exe"
nssm set github-webhook-mcp AppDirectory "C:\Users\<you>\github-webhook-mcp"
nssm set github-webhook-mcp AppParameters "main.py webhook --port 8080 --event-profile notifications"
nssm set github-webhook-mcp AppEnvironmentExtra "WEBHOOK_SECRET=your_secret"
nssm start github-webhook-mcp
```
| Tool | Description |
|------|-------------|
| `get_pending_status` | Lightweight snapshot of pending event counts by type |
| `list_pending_events` | Summaries of pending events (no full payloads) |
| `get_event` | Full payload for a single event by ID |
| `get_webhook_events` | Full payloads for all pending events |
| `mark_processed` | Mark an event as processed |

Common management commands:
## Monorepo Structure

```powershell
nssm status github-webhook-mcp # check status
nssm restart github-webhook-mcp # restart
nssm edit github-webhook-mcp # re-open the GUI
nssm remove github-webhook-mcp confirm # uninstall
```

> **Alternatives:** `sc create` with a `pywin32` service wrapper, or [WinSW](https://github.com/winsw/winsw) with an XML config, also work. NSSM requires no code changes.

### 7. Optional channel push notifications

The Node.js MCP server supports Claude Code's `claude/channel` capability (research preview, v2.1.80+). When enabled, new webhook events are pushed into your session automatically.

```bash
claude --dangerously-load-development-channels server:github-webhook-mcp
worker/ — Cloudflare Worker + Durable Objects
local-mcp/ — Local stdio MCP bridge (TypeScript, dev)
mcp-server/ — .mcpb package for Claude Desktop
shared/ — Shared types and utilities
```

Channel notifications are enabled by default. To disable, set `WEBHOOK_CHANNEL=0` in the MCP server environment.

## Examples

### Example 1: Check whether any GitHub notifications are pending

**User prompt:** "Do I have any pending GitHub webhook notifications right now?"

**Expected behavior:**

- Calls `get_pending_status`
- Returns pending count, latest event time, and event types
- Uses that summary to decide whether more detail is needed

### Example 2: Review the latest pending PR-related event

**User prompt:** "Show me the latest pending pull request event and explain what changed."

**Expected behavior:**

- Calls `list_pending_events` to find the newest relevant event
- Calls `get_event` only for the selected event
- Summarizes the PR metadata and payload without dumping every event

### Example 3: Mark an event as handled after triage

**User prompt:** "I already handled event `EVENT_ID`. Mark it processed so it stops appearing."

**Expected behavior:**

- Calls `mark_processed` with the event ID
- Marks the event as processed in the local event store
- Confirms success and, if applicable, reports how many processed events were purged

## Privacy Policy

This extension works with GitHub webhook event payloads that you choose to persist locally in `events.json`.
It may include issue titles, pull request metadata, discussion text, sender identities, and repository URLs inside that local event store.

### Data Collection

- Reads the local `events.json` file configured by the user
- Surfaces webhook metadata and payloads to the connected MCP client
- Can mark events as processed in the same local event store
- Does not send event contents to third-party services by itself beyond the webhook receiver and infrastructure you configure

### Submission Note

The extension-specific privacy policy is published at:

- https://smgjp.com/privacy-policy-github-webhook-mcp/
Events are stored in a Cloudflare Durable Object (edge storage). The local MCP bridge proxies tool calls to the Worker and does not store event data locally.

Keep the policy URL in `mcp-server/manifest.json` aligned with that public page before directory submission.
- Extension privacy policy: https://smgjp.com/privacy-policy-github-webhook-mcp/

## Support

- GitHub Issues: https://github.com/Liplus-Project/github-webhook-mcp/issues
- Requirements/specification: [docs/0-requirements.md](docs/0-requirements.md)
- Environment variable examples: [.env.example](.env.example)
- Requirements: [docs/0-requirements.md](docs/0-requirements.md)

## Related

- [docs/0-requirements.md](docs/0-requirements.md) — source-of-truth requirements and behavior contracts
- [Liplus-Project/liplus-language](https://github.com/Liplus-Project/liplus-language) — Li+ language specification
- liplus-language #610
Loading