From 92d335deba58d56d1a18513d6e5a45900e3ab263 Mon Sep 17 00:00:00 2001 From: liplus-lin-lay <259586417+liplus-lin-lay@users.noreply.github.com> Date: Mon, 23 Mar 2026 13:24:32 +0900 Subject: [PATCH 1/5] docs(mcpb): prepare local directory submission metadata MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README と manifest を Anthropic local MCP directory submission 向けに整理し、Node MCP ツールへ readOnlyHint/destructiveHint を追加しました。\n\n公式一覧提出で不足していた privacy policy 導線、working examples、公開メタデータを先に揃えるための中間整理です。\n\nRefs #38 --- README.md | 206 +++++++++++++++++++++++-------------- mcp-server/manifest.json | 30 +++++- mcp-server/server/index.js | 25 +++++ 3 files changed, 182 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index e71ee31..4ee9c2b 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,89 @@ # github-webhook-mcp -GitHub webhook receiver as an MCP server. +GitHub webhook receiver and local MCP extension for GitHub notification workflows. -Receives GitHub webhook events and enables Lin and Lay to autonomously handle PR reviews and issue management. -It supports two operating styles: +## Description -- MCP polling: store webhook events and let an AI poll lightweight summaries. -- Channel push: push new events into a Claude Code session in real-time via `claude/channel`. -- Direct trigger: run a command immediately for each stored event. +`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). -## Quick Start +## Features -### 1. Install dependencies +- 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. -```bash -pip install -r requirements.txt +## 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...** +2. Select the `.mcpb` file +3. Enter the path to your `events.json` when prompted + +### Claude Desktop / Claude Code — npx + +Add to your Claude MCP config (`claude_desktop_config.json` or project settings): + +```json +{ + "mcpServers": { + "github-webhook-mcp": { + "command": "npx", + "args": ["github-webhook-mcp"], + "env": { + "EVENTS_JSON_PATH": "/path/to/events.json" + } + } + } +} ``` -### 2. Start webhook receiver for MCP polling +### Codex — config.toml -```bash -WEBHOOK_SECRET=your_secret python main.py webhook --port 8080 --event-profile notifications +```toml +[mcp.github-webhook-mcp] +command = "npx" +args = ["github-webhook-mcp"] + +[mcp.github-webhook-mcp.env] +EVENTS_JSON_PATH = "/path/to/events.json" ``` -### 3. Optional: start webhook receiver with direct Codex reactions +### Python (legacy) -Use the bundled Codex wrapper if you want the webhook to launch `codex exec` immediately. -Put `--trigger-command` last when a service manager splits the remaining tokens for you. +```json +{ + "mcpServers": { + "github-webhook-mcp": { + "command": "python", + "args": ["/path/to/github-webhook-mcp/main.py", "mcp"] + } + } +} +``` + +## Configuration + +### 1. Install receiver dependencies ```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" +pip install -r requirements.txt ``` -If you want Codex to resume an existing app thread instead of writing markdown output: +### 2. Start the webhook receiver -```text -python codex_reaction.py --workspace /path/to/workspace --resume-session +```bash +WEBHOOK_SECRET=your_secret python main.py webhook --port 8080 --event-profile notifications ``` -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. - -### 4. Set up Cloudflare Tunnel +### 3. Set up Cloudflare Tunnel ```bash cloudflared tunnel login @@ -56,12 +93,12 @@ cp cloudflared/config.yml.example ~/.cloudflared/config.yml cloudflared tunnel run ``` -### 5. Configure GitHub webhook +### 4. Configure the GitHub webhook - Payload URL: `https://webhook.yourdomain.com/webhook` - Content type: `application/json` - Secret: same value as `WEBHOOK_SECRET` -- Recommended event profile: choose these events to stay close to GitHub Notifications +- Recommended event profile: - Issues - Issue comments - Pull requests @@ -74,73 +111,90 @@ cloudflared tunnel run 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`. -### 6. Enable channel push notifications (optional) +### 5. Optional direct trigger mode -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 — no polling needed. +Use the bundled Codex wrapper if you want the webhook to launch `codex exec` immediately. + +```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 +``` + +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 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 ``` -Channel notifications are enabled by default. To disable, set `WEBHOOK_CHANNEL=0` in the MCP server env. +Channel notifications are enabled by default. To disable, set `WEBHOOK_CHANNEL=0` in the MCP server environment. -### 7. Configure MCP server +## Examples -#### Option A: Claude Desktop — Desktop Extension (.mcpb) +### Example 1: Check whether any GitHub notifications are pending -Download `mcp-server.mcpb` from [Releases](https://github.com/Liplus-Project/github-webhook-mcp/releases), then: +**User prompt:** "Do I have any pending GitHub webhook notifications right now?" -1. Open Claude Desktop → **Settings** → **Extensions** → **Advanced settings** → **Install Extension...** -2. Select the `.mcpb` file -3. Enter the path to your `events.json` when prompted +**Expected behavior:** -#### Option B: Claude Desktop / Claude Code — npx +- Calls `get_pending_status` +- Returns pending count, latest event time, and event types +- Uses that summary to decide whether more detail is needed -Add to your Claude MCP config (`claude_desktop_config.json` or project settings): +### Example 2: Review the latest pending PR-related event -```json -{ - "mcpServers": { - "github-webhook-mcp": { - "command": "npx", - "args": ["github-webhook-mcp"], - "env": { - "EVENTS_JSON_PATH": "/path/to/events.json" - } - } - } -} -``` +**User prompt:** "Show me the latest pending pull request event and explain what changed." -#### Option C: Codex — config.toml +**Expected behavior:** -```toml -[mcp.github-webhook-mcp] -command = "npx" -args = ["github-webhook-mcp"] +- 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 -[mcp.github-webhook-mcp.env] -EVENTS_JSON_PATH = "/path/to/events.json" -``` +### Example 3: Mark an event as handled after triage -#### Option D: Python (legacy) +**User prompt:** "I already handled event `EVENT_ID`. Mark it processed so it stops appearing." -```json -{ - "mcpServers": { - "github-webhook-mcp": { - "command": "python", - "args": ["/path/to/github-webhook-mcp/main.py", "mcp"] - } - } -} -``` +**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 current policy text is mirrored in this README so the packaged extension can point to a public HTTPS URL immediately. +If Anthropic review requires an extension-specific policy on your own domain, publish the same policy text there and update `mcp-server/manifest.json` before final submission. -## Operator Notes +## Support -- For the recommended polling flow, MCP tool contracts, event profiles, and trigger metadata, see [docs/0-requirements.md](docs/0-requirements.md). -- For environment variable examples, see [.env.example](.env.example). -- For direct trigger usage, `codex_reaction.py` is the bundled helper. +- 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) ## Related diff --git a/mcp-server/manifest.json b/mcp-server/manifest.json index daa2ab3..65430cb 100644 --- a/mcp-server/manifest.json +++ b/mcp-server/manifest.json @@ -1,11 +1,21 @@ { "manifest_version": "0.3", "name": "github-webhook-mcp", + "display_name": "GitHub Webhook MCP", "version": "0.3.0", "description": "Browse pending GitHub webhook events. Pairs with a webhook receiver that writes events.json.", + "long_description": "GitHub Webhook MCP helps Claude review and react to GitHub notifications from a local event store. It surfaces lightweight pending-event summaries, exposes full webhook payloads on demand, and lets users mark handled events as processed without exposing the event file directly.", "author": { - "name": "Liplus Project" + "name": "Liplus Project", + "url": "https://github.com/Liplus-Project" }, + "repository": { + "type": "git", + "url": "https://github.com/Liplus-Project/github-webhook-mcp.git" + }, + "homepage": "https://github.com/Liplus-Project/github-webhook-mcp", + "documentation": "https://github.com/Liplus-Project/github-webhook-mcp#readme", + "support": "https://github.com/Liplus-Project/github-webhook-mcp/issues", "license": "MIT", "server": { "type": "node", @@ -51,10 +61,24 @@ } ], "compatibility": { + "claude_desktop": ">=0.11.0", "platforms": [ "win32", "darwin", "linux" - ] - } + ], + "runtimes": { + "node": ">=18.0.0" + } + }, + "keywords": [ + "github", + "webhook", + "notifications", + "mcp", + "claude" + ], + "privacy_policies": [ + "https://github.com/Liplus-Project/github-webhook-mcp?tab=readme-ov-file#privacy-policy" + ] } diff --git a/mcp-server/server/index.js b/mcp-server/server/index.js index c74c0dd..3c0f40f 100644 --- a/mcp-server/server/index.js +++ b/mcp-server/server/index.js @@ -40,12 +40,18 @@ const server = new Server( const TOOLS = [ { name: "get_pending_status", + title: "Get Pending Status", description: "Get a lightweight snapshot of pending GitHub webhook events. Use this for periodic polling before requesting details.", inputSchema: { type: "object", properties: {} }, + annotations: { + title: "Get Pending Status", + readOnlyHint: true, + }, }, { name: "list_pending_events", + title: "List Pending Events", description: "List lightweight summaries for pending GitHub webhook events. Returns metadata only, without full payloads.", inputSchema: { @@ -57,9 +63,14 @@ const TOOLS = [ }, }, }, + annotations: { + title: "List Pending Events", + readOnlyHint: true, + }, }, { name: "get_event", + title: "Get Event Payload", description: "Get the full payload for a single webhook event by ID.", inputSchema: { type: "object", @@ -68,15 +79,25 @@ const TOOLS = [ }, required: ["event_id"], }, + annotations: { + title: "Get Event Payload", + readOnlyHint: true, + }, }, { name: "get_webhook_events", + title: "Get Webhook Events", description: "Get pending (unprocessed) GitHub webhook events with full payloads. Prefer get_pending_status or list_pending_events for polling.", inputSchema: { type: "object", properties: {} }, + annotations: { + title: "Get Webhook Events", + readOnlyHint: true, + }, }, { name: "mark_processed", + title: "Mark Event Processed", description: "Mark a webhook event as processed so it won't appear again.", inputSchema: { type: "object", @@ -88,6 +109,10 @@ const TOOLS = [ }, required: ["event_id"], }, + annotations: { + title: "Mark Event Processed", + destructiveHint: true, + }, }, ]; From 80eadceb2ccb0fa25b6b27e12982fbf288d02549 Mon Sep 17 00:00:00 2001 From: liplus-lin-lay <259586417+liplus-lin-lay@users.noreply.github.com> Date: Mon, 23 Mar 2026 13:38:21 +0900 Subject: [PATCH 2/5] build(mcpb): align lockfile with submission-ready package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anthropic local MCP directory submission 向けの README、manifest、tool annotation 更新に合わせて、mcp-server の lockfile を 0.3.0 構成へ同期しました。\n\nMCPB 本体は現時点では CD の release asset として扱い、repo には含めません。\n\nRefs #38 --- mcp-server/package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mcp-server/package-lock.json b/mcp-server/package-lock.json index 8761232..61636ba 100644 --- a/mcp-server/package-lock.json +++ b/mcp-server/package-lock.json @@ -1,12 +1,12 @@ { "name": "github-webhook-mcp", - "version": "0.2.1", + "version": "0.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "github-webhook-mcp", - "version": "0.2.1", + "version": "0.3.0", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.0.0", From b72831df2ad13062e473dda5410ead0fb1a301ab Mon Sep 17 00:00:00 2001 From: liplus-lin-lay <259586417+liplus-lin-lay@users.noreply.github.com> Date: Mon, 23 Mar 2026 13:44:12 +0900 Subject: [PATCH 3/5] build(mcpb): ignore generated release bundle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 生成される MCPB は現時点では CD の release asset として扱うため、作業 tree に残っても差分ノイズにならないよう .gitignore へ追加しました。\n\nRefs #38 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d0426f9..b906d95 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ codex-runs/ __pycache__/ *.pyc mcp-server/node_modules/ +mcp-server/*.mcpb From 2b31ca279df84fe4a89d36e860244b64c5fd509d Mon Sep 17 00:00:00 2001 From: liplus-lin-lay <259586417+liplus-lin-lay@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:11:45 +0900 Subject: [PATCH 4/5] docs(mcpb): point privacy policy to public domain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README と manifest の privacy policy URL を smgjp.com 上の公開ページへ切り替えました。\n\nAnthropic local MCP directory submission 向けに、拡張専用の公開 URL を source of truth として固定するための更新です。\n\nRefs #38 --- README.md | 7 +++++-- mcp-server/manifest.json | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4ee9c2b..1478065 100644 --- a/README.md +++ b/README.md @@ -187,8 +187,11 @@ It may include issue titles, pull request metadata, discussion text, sender iden ### Submission Note -The current policy text is mirrored in this README so the packaged extension can point to a public HTTPS URL immediately. -If Anthropic review requires an extension-specific policy on your own domain, publish the same policy text there and update `mcp-server/manifest.json` before final submission. +The extension-specific privacy policy is published at: + +- https://smgjp.com/privacy-policy-github-webhook-mcp/ + +Keep the policy URL in `mcp-server/manifest.json` aligned with that public page before directory submission. ## Support diff --git a/mcp-server/manifest.json b/mcp-server/manifest.json index 65430cb..14005ba 100644 --- a/mcp-server/manifest.json +++ b/mcp-server/manifest.json @@ -79,6 +79,6 @@ "claude" ], "privacy_policies": [ - "https://github.com/Liplus-Project/github-webhook-mcp?tab=readme-ov-file#privacy-policy" + "https://smgjp.com/privacy-policy-github-webhook-mcp/" ] } From 6cc31349fa0eb35d7acd97bb9d3dc4765524d860 Mon Sep 17 00:00:00 2001 From: liplus-lin-lay <259586417+liplus-lin-lay@users.noreply.github.com> Date: Mon, 23 Mar 2026 14:33:40 +0900 Subject: [PATCH 5/5] build(release): bump package version to 0.3.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Anthropic local directory submission 向けの整備を patch release に載せるため、mcp-server の version を 0.3.1 に更新し、manifest と lockfile を揃えた。\n\nRefs #38 --- mcp-server/manifest.json | 2 +- mcp-server/package-lock.json | 4 ++-- mcp-server/package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mcp-server/manifest.json b/mcp-server/manifest.json index 14005ba..70bb1be 100644 --- a/mcp-server/manifest.json +++ b/mcp-server/manifest.json @@ -2,7 +2,7 @@ "manifest_version": "0.3", "name": "github-webhook-mcp", "display_name": "GitHub Webhook MCP", - "version": "0.3.0", + "version": "0.3.1", "description": "Browse pending GitHub webhook events. Pairs with a webhook receiver that writes events.json.", "long_description": "GitHub Webhook MCP helps Claude review and react to GitHub notifications from a local event store. It surfaces lightweight pending-event summaries, exposes full webhook payloads on demand, and lets users mark handled events as processed without exposing the event file directly.", "author": { diff --git a/mcp-server/package-lock.json b/mcp-server/package-lock.json index 61636ba..eb58fb7 100644 --- a/mcp-server/package-lock.json +++ b/mcp-server/package-lock.json @@ -1,12 +1,12 @@ { "name": "github-webhook-mcp", - "version": "0.3.0", + "version": "0.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "github-webhook-mcp", - "version": "0.3.0", + "version": "0.3.1", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.0.0", diff --git a/mcp-server/package.json b/mcp-server/package.json index 9c64cd9..3b1fb2f 100644 --- a/mcp-server/package.json +++ b/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "github-webhook-mcp", - "version": "0.3.0", + "version": "0.3.1", "description": "MCP server for browsing GitHub webhook events", "type": "module", "bin": {