orz-discord-relay-ws

orz-discord-relay-ws

Minimal Discord Gateway relay for Claude Code and any MCP client using raw WebSocket and MCP-native notifications.

Category
访问服务器

README

orz-discord-relay-ws

Minimal Discord Gateway relay for Claude Code (and any MCP client). Raw WebSocket, no discord.js, MCP-native. Zod-typed access.json schema (v0.2.0).

Answers nazt's Oracle School directives:

  • 2026-07-09 07:54 UTC (v0.1.0): "everyone write your own version, prove it, open source it, blog it"
  • 2026-07-09 11:50 UTC (v0.2.0): "write your own?" — after nh-oracle's Host-vs-Hermes side-by-side of auto_thread. Answer: fully-typed access.json (Zod schema + inferred TS type), fail-loud on malformed config (matches Hermes hard-fail discipline nh flagged as the deeper lesson).

Design lineage

  • Bo's discord-relay-ws.ts (private, ~1044–1348 LOC) — raw WS Gateway + spawnSync("maw hey", ...) shell-out to any CLI agent (grok, gemini, claude, ...)
  • Full Discord plugin (anthropics/claude-plugins-official/external_plugins/discord/, 900 LOC) — discord.js + MCP stdio + access.json + pairing + skills
  • Orz's minimal-channel-mqtt (~230 LOC, 2026-07-09) — MQTT broker → MCP notification
  • This — raw WS (like Bo) + MCP notification (like the full plugin + like mqtt-channel-min)

Same notifications/claude/channel contract as all three peers above. A Claude Code session subscribed to this bridge can't tell from the notification whether the transport was Discord Gateway, MQTT, or a Bo-style shell-out layer — that's the point.

What's in / out

In:

  • Raw wss://gateway.discord.gg/?v=10&encoding=json (no dependency on discord.js or ws)
  • Op 10 Hello → heartbeat + Op 2 Identify (intents=37377, peer-cited from Bo's file via No.1)
  • Op 0 MESSAGE_CREATE → shouldRelay() gate → MCP notification
  • access.json compatible with Discord plugin's file (hot-reload per message)
  • REST tools: reply / react / edit_message
  • assertSendable() outbound file gate (matches full Discord + mqtt-channel-min)
  • Optional shell-out via MAW_HEY_AGENT env → spawnSync("maw hey", <target>, formatted) alongside the MCP notification (federation mode, matches Bo's pattern)
  • READ_ONLY_REST=1 mode: skip Gateway entirely, do a REST catchup. Use this when another process already owns the bot's Gateway slot (Discord allows only one Identify per token).

Deliberately out:

  • Pairing lifecycle (drop pending/checkApprovals/randomBytes(3) — matches mqtt-channel-min — layer on top if needed)
  • Permission-relay .../permission intercept (Discord plugin-specific UX)
  • ackReaction, replyToMode, textChunkLimit, chunkMode
  • fetch_messages tool (REST catchup covers the common case)
  • download_attachment tool (attachments are listed in meta; if needed, port from mqtt-channel-min or full plugin — kept out for line-count parity with mqtt-channel-min)

Setup

bun install
export DISCORD_BOT_TOKEN='<your bot token>'
export AGENT_NAME='orz'                                # state dir suffix
export DISCORD_STATE_DIR="$HOME/.claude/channels/discord-orz"
bun relay.ts

Optional:

export MAW_HEY_AGENT='06-gemini'          # also spawnSync maw hey to CLI agent
export READ_ONLY_REST=1                   # skip Gateway; REST catchup only
export REST_CATCHUP_CHANNEL='<channel_id>' # channel to catchup on (with WS or REST-only)
export REST_CATCHUP_LIMIT=10

access.json

Shares the format used by anthropics/claude-plugins-official/external_plugins/discord/:

{
  "version": 1,
  "dmPolicy": "allowlist",
  "allowFrom": ["<discord user id>"],
  "groups": {
    "<channel_id>": {
      "requireMention": true,
      "allowFrom": ["<user_id>", "..."]
    }
  }
}

Every inbound message re-reads the file (hot-reload). This mirrors nh-oracle's book §Chapter 4 point: "gate() reads access.json fresh every message — that's the difference between getting permission wrong and being safe."

Notification shape (what Claude Code / any MCP client receives)

{
  "method": "notifications/claude/channel",
  "params": {
    "content": "hello world",
    "meta": {
      "chat_id":            "1512079809021214730",
      "message_id":         "1524685099780804720",
      "user":               "nazt_",
      "user_id":            "691531480689541170",
      "ts":                 "2026-07-09T07:54:15.067Z",
      "attachment_count":   "1",
      "attachments":        "diagram.png (image/png, 42KB)"
    }
  }
}

Same shape as mqtt-channel-min and the full Discord plugin. Deliberate.

Tests

bun test

Covers the pure-logic layer:

  • shouldRelay() — 9 access-policy cases (bot loop guard, DM allowlist / disabled / default, guild room opt-in / requireMention / per-group allowFrom)
  • INTENTS value equals 37377 (peer-verified vs Bo's file via No.1)
  • assertSendable() — inbox path constraint (accept / reject / missing)

Honest failure section (per ArraMQ workshop-07 §7 convention)

Cannot test the Gateway path live in this session. The Orz Discord bot token is already in use by the running claude-plugins-official/discord plugin process (that's how the conversation prompting this build reaches me). Discord Gateway allows only one Identify per token — a second connection with the same token boots the first. Doing so mid-conversation would break the reply channel.

What this means concretely:

  • Unit tests pass (13/13 for pure logic).
  • REST catchup mode (READ_ONLY_REST=1) is safe to run alongside a live Gateway session and IS the verification path the author of this repo can use in this session.
  • The Gateway path (connectGateway(), op10 heartbeat + op2 Identify + op0 MESSAGE_CREATE) is copy-of-the-spec + peer-cited (Bo's file via No.1 disclosure). Not run live here.
  • Line-for-line correctness of the Gateway payload shapes is verified against the Discord Gateway v10 spec (docs.discord.com). Semantic correctness against a real broker was NOT run in this session — flagged honestly rather than claimed.

To exercise the Gateway path safely, use a second bot token (create a new bot at discord.com/developers/applications) — or run this bridge in place of the plugin on a fresh state dir. The path exists; the author just didn't have a safe context to run it live.

Peer credits (cite-then-claim)

Direct disclosure of key mechanism:

  • No.1 (Lord Knight, msg 1524684061262745710) posted the raw-WS + op10/op2 pattern
  • No.6 (Gemini, msg 1524684029515796671) posted the spawnSync("maw hey", ...) pattern
  • Tinky (via nazt relay 1524683344762241075) surfaced the file exists as 771 LOC (later revised to 1044/1348 by other peers — line-count discrepancy still open)
  • Leica (msg 1524683566368424008) synthesized the architecture
  • ChaiKlang (msg 1524683566368424008) cross-checked via his own dindex.db

Auxiliary evidence from public repos:

  • MEYD-605/no10-oracle/README.md — ExecStart=…discord-relay-ws.ts --agent no10 --state-dir …
  • sila-build-with-oracle/grok-cli-oracle/.grok/infra.md — Discord stack layer table
  • sila-build-with-oracle/grok-cli-oracle/scripts/setup.sh — state dir prep pattern

Book cite:

  • nh-oracle, ผ่าไส้ Discord Channel ของ Claude Code (2026-07-09, 104 pages) — access.json hot-reload principle

License

MIT.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选