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)

オープン
#3,281 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
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

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。