anthropics / anthropics/claude-plugins-official
[discord] "See more" on permission prompts shows "Details no longer available." even for unresolved requests (multi-instance / in-memory state)
- 主要言語
- Python
- スター
- 36.3k
- フォーク
- 4.1k
- 平均マージ
- 2日 14時間
- マージ済み PR(30日)
- 539
説明
## Summary
The Discord plugin's permission prompt ships a **See more** button that is supposed to expand the full tool input. In practice it very often replies **"Details no longer available."** — *even for a fresh permission request that has not been allowed/denied yet*.
Root cause: the expansion details are kept only in **per-process in-memory state** (`pendingPermissions` Map), but the plugin runs as a **stdio MCP server spawned per Claude Code session**, and every instance logs in with the **same bot token**. A button click is delivered by Discord's gateway to *one* of the connected instances, which is frequently **not** the instance that created the message and stored the details. That instance's Map has no entry for the `request_id`, so it returns "Details no longer available."
## Environment
- Plugin: `discord` (`external_plugins/discord`), version **0.0.4**
- OS: Windows 11
- Runtime: `bun`
- Multiple Claude Code windows/sessions open concurrently (observed **8 `bun.exe` processes** running)
## Steps to reproduce
1. Have **more than one** Claude Code session/window open (each spawns its own plugin server process via the stdio MCP config).
2. Trigger any tool call that produces a permission prompt, so a `🔐 Permission: ` message is delivered to Discord.
3. On the phone/desktop, tap **See more** on that message — *before* pressing Allow/Deny.
4. **Expected:** the message expands to show `tool_name`, `description`, and the pretty-printed `input_preview`.
5. **Actual:** an ephemeral reply **"Details no longer available."** appears, even though the request is still pending.
This is intermittent and depends on which instance Discord routes the interaction to. With a single, never-restarted instance it can work; with multiple instances (or after the sending session closes/restarts) it almost always fails.
## Root cause (code references, v0.0.4 `server.ts`)
- `.mcp.json` registers the plugin as a **stdio** server (`command: "bun" … "start"`), so it is **spawned per CC session** rather than running as one shared daemon.
- `server.ts:470` — details are stored in process-local memory only:
```ts
const pendingPermissions = new Map()
```
- `server.ts:488` — populated when the `permission_request` notification arrives (in the *receiving* process).
- `server.ts:897` — every instance calls `client.login(TOKEN)` with the **same** token, so multiple gateway connections exist for one bot.
- `server.ts:759-761` — the `more` button handler looks up the Map and, on a miss, replies:
```ts
const details = pendingPermissions.get(request_id)
if (!details) {
await interaction.reply({ content: 'Details no longer available.', ephemeral: true })
return
}
```
Because the interaction can be handled by a different process than the one that ran `set()`, the lookup misses for still-pending requests.
(Related, separate symptom: after Allow/Deny, `server.ts:796` deletes the entry, so re-tapping See more correctly shows "Details no longer available." That part is expected; the bug is the **pre-resolution** failure.)
## Impact
- The **See more** feature is effectively unreliable for anyone running more than one Claude Code session (a common setup).
- Allow/Deny and the `🔐 Permission: ` header still work, and full details remain visible in the terminal, so it is not blocking — but the button is misleading.
## Suggested fixes (any one)
1. **Persist the pending details** out of process memory, keyed by `request_id` (e.g. a small JSON/file/SQLite store under the plugin data dir), and read it in the `more` handler. This makes lookups work regardless of which instance handles the interaction.
2. **Single shared daemon** for the Discord gateway: have per-session MCP servers forward `permission_request`/resolution over IPC to one long-lived process that owns the single bot connection and the state. Avoids multiple logins with the same token entirely.
3. **Embed the details in the message itself** (e.g. as a spoiler block or a follow-up) so no server-side lookup is needed on expansion — at the cost of showing more up front.
Option 1 is the smallest change and directly removes the in-memory coupling.
## Notes
Multiple concurrent `client.login()` calls with the same token also create competing gateway connections, which is fragile independent of this bug; option 2 would address that as well.
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
調査の方向性
Start with external_plugins/discord/server.ts and .mcp.json, especially the pendingPermissions Map around lines 470-488 and the See more handler around 759-761. Reproduce with multiple stdio instances, then verify that a pending request's details remain available regardless of which instance receives the interaction, while resolved requests still report that details are unavailable.
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- bun, typescript
- 領域
- backend
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 静か
- 明瞭さ
- 明確に書かれている
- 初心者へのやさしさ
- 58/100