cursor-mcp-feedback 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +263 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.js +25 -0
- package/dist/main.d.ts +13 -0
- package/dist/main.js +438 -0
- package/dist/mcp-app.html +227 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +241 -0
- package/dist/session-store.d.ts +4 -0
- package/dist/session-store.js +76 -0
- package/hooks/block-cursor-mcp-feedback.js +152 -0
- package/hooks/consume-pending.js +88 -0
- package/hooks/session-utils.js +253 -0
- package/package.json +73 -0
- package/rules/cursor-mcp-feedback.mdc +27 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 yuanmingchen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# MCP Feedback App
|
|
2
|
+
|
|
3
|
+
Interactive feedback UI that renders directly inside MCP hosts (Claude, Cursor, etc.) using the [MCP Apps](https://modelcontextprotocol.io/extensions/apps/overview) extension. Includes a **macOS floating companion app** for bidirectional feedback and pending message management.
|
|
4
|
+
|
|
5
|
+
When an AI agent calls the `interactive_feedback` tool, a feedback panel appears inline in the conversation — and optionally in the floating app. The user can respond from either side.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
### MCP App Panel (in-conversation UI)
|
|
10
|
+
|
|
11
|
+
- **Inline feedback UI** — summary with Markdown rendering + input area, directly in the conversation
|
|
12
|
+
- **Dark mode** — auto-detects host theme (transparent background adapts to light/dark)
|
|
13
|
+
- **Image support** — paste (Cmd+V), drag & drop, file picker with preview
|
|
14
|
+
- **Quick replies** — Continue, LGTM, Fix, Pause one-click buttons
|
|
15
|
+
- **Auto-append** — automatically appends a configurable reminder to every feedback
|
|
16
|
+
- **Keyboard shortcut** — Ctrl/Cmd+Enter to submit feedback
|
|
17
|
+
- **Blocking tool pattern** — `interactive_feedback` blocks until user submits via the UI
|
|
18
|
+
|
|
19
|
+
### Floating Companion App (macOS)
|
|
20
|
+
|
|
21
|
+
- **Bidirectional feedback** — both the MCP App panel and floating app receive AI summaries; respond from either side
|
|
22
|
+
- **Pending messages** — queue messages that redirect the agent mid-task (delivered via `preToolUse` hook)
|
|
23
|
+
- **Per-session tabs** — manage multiple agent sessions with project directory info
|
|
24
|
+
- **Chat history** — full conversation history loaded from `events.jsonl` per session
|
|
25
|
+
- **Image support** — paste images (Cmd+V), file picker, thumbnails in chat, click to preview
|
|
26
|
+
- **Global hotkey** — Cmd+Shift+M to toggle the panel
|
|
27
|
+
- **Floating button** — collapsible/expandable, draggable, always-on-top
|
|
28
|
+
- **State persistence** — window position, size, expanded state, input draft all persist across restarts
|
|
29
|
+
- **Enter to send** — Enter sends, Shift+Enter for newline, IME-safe
|
|
30
|
+
- **Menu bar icon** — quick access via status bar
|
|
31
|
+
|
|
32
|
+
### Cursor Integration
|
|
33
|
+
|
|
34
|
+
- **Auto-install** — MCP server config, Cursor rules, and hooks are all auto-configured on first startup
|
|
35
|
+
- **Subagent protection** — hooks prevent subagents from calling `interactive_feedback`
|
|
36
|
+
- **Session lifecycle** — automatic session tracking via hooks (`sessionStart`, `preToolUse`, etc.)
|
|
37
|
+
- **Event logging** — all interactions logged to `events.jsonl` per session for chat history
|
|
38
|
+
|
|
39
|
+
## Architecture
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
┌─────────────────────────────────────────────────┐
|
|
43
|
+
│ MCP Host (Cursor / Claude) │
|
|
44
|
+
│ ┌──────────┐ ┌────────────────────┐ │
|
|
45
|
+
│ │ AI Agent │ │ MCP App Panel │ │
|
|
46
|
+
│ │ │ │ (sandboxed iframe) │ │
|
|
47
|
+
│ │ calls │ │ sessionId embedded │ │
|
|
48
|
+
│ │ tool ────┼────┼─► renders inline │ │
|
|
49
|
+
│ └──────────┘ └────────┬───────────┘ │
|
|
50
|
+
└────────────────────────────┼────────────────────┘
|
|
51
|
+
│ callServerTool
|
|
52
|
+
▼
|
|
53
|
+
┌───────────────────────────┐
|
|
54
|
+
│ MCP Server │
|
|
55
|
+
│ interactive_feedback │ ← polls session file
|
|
56
|
+
│ submit_feedback │ ← writes resolved file
|
|
57
|
+
│ get_system_info │
|
|
58
|
+
└───────────┬───────────────┘
|
|
59
|
+
│
|
|
60
|
+
┌───────────▼───────────────┐
|
|
61
|
+
│ ~/.cursor-mcp-feedback/ │
|
|
62
|
+
│ sessions/{uuid}.json │ ← bidirectional channel
|
|
63
|
+
│ sessions/{convId}/ │
|
|
64
|
+
│ events.jsonl │ ← chat history
|
|
65
|
+
│ pending.json │ ← queued messages
|
|
66
|
+
│ meta.json │ ← session metadata
|
|
67
|
+
│ active-sessions.json │
|
|
68
|
+
└───────────┬───────────────┘
|
|
69
|
+
│ file watch
|
|
70
|
+
┌───────────▼───────────────┐
|
|
71
|
+
│ Floating App (macOS) │
|
|
72
|
+
│ SwiftUI + AppKit │
|
|
73
|
+
│ - bidirectional feedback │
|
|
74
|
+
│ - pending messages │
|
|
75
|
+
│ - per-session chat UI │
|
|
76
|
+
└───────────────────────────┘
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
### Quick Install (npm)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install -g cursor-mcp-feedback
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
On install, `postinstall` automatically configures Cursor (mcp.json, rules, hooks). Just restart Cursor and the MCP server is ready.
|
|
88
|
+
|
|
89
|
+
### From Source
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
git clone git@repo.advai.net:cash/incubating/cusor-feedback-v2.git cursor-mcp-feedback
|
|
93
|
+
cd cursor-mcp-feedback
|
|
94
|
+
npm install
|
|
95
|
+
npm run build
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Floating Companion App (macOS)
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
cd floating-app
|
|
102
|
+
swift build -c release
|
|
103
|
+
# Binary: .build/release/MCPPending
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
To auto-launch on login, add `.build/release/MCPPending` to System Settings > General > Login Items, or run manually.
|
|
107
|
+
|
|
108
|
+
### CLI: Queue Pending Messages
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# List active sessions
|
|
112
|
+
cursor-mcp-feedback queue sessions
|
|
113
|
+
|
|
114
|
+
# Queue a message to the most recent session
|
|
115
|
+
cursor-mcp-feedback queue "please focus on the API layer"
|
|
116
|
+
|
|
117
|
+
# Queue to a specific session
|
|
118
|
+
cursor-mcp-feedback queue "fix the bug" --session <session-id>
|
|
119
|
+
|
|
120
|
+
# List pending messages
|
|
121
|
+
cursor-mcp-feedback queue list
|
|
122
|
+
|
|
123
|
+
# Clear pending messages
|
|
124
|
+
cursor-mcp-feedback queue clear
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Configure your MCP host
|
|
128
|
+
|
|
129
|
+
#### Cursor (auto-configured)
|
|
130
|
+
|
|
131
|
+
On first startup (or `npm install -g`), the MCP server **automatically configures** itself in `~/.cursor/mcp.json` with the correct absolute paths. It also auto-installs:
|
|
132
|
+
|
|
133
|
+
- **Cursor rule** (`~/.cursor/rules/cursor-mcp-feedback.mdc`) — instructs the agent to call `interactive_feedback`
|
|
134
|
+
- **Cursor hooks** (`~/.cursor/hooks/`) — subagent protection + pending message delivery + event logging
|
|
135
|
+
- **hooks.json entries** — registers `sessionStart`, `subagentStart`, `subagentStop`, `beforeMCPExecution`, `preToolUse`, `afterMCPExecution` hooks
|
|
136
|
+
|
|
137
|
+
All auto-installed files are kept in sync on every startup (hash-based diffing, idempotent).
|
|
138
|
+
|
|
139
|
+
To manually configure instead, add to `~/.cursor/mcp.json`:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"mcpServers": {
|
|
144
|
+
"cursor-mcp-feedback": {
|
|
145
|
+
"command": "node",
|
|
146
|
+
"args": ["/absolute/path/to/cursor-mcp-feedback/dist/main.js"],
|
|
147
|
+
"timeout": 86400,
|
|
148
|
+
"env": {
|
|
149
|
+
"MCP_FEEDBACK_TIMEOUT": "86400"
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### Claude Desktop
|
|
157
|
+
|
|
158
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"mcpServers": {
|
|
163
|
+
"cursor-mcp-feedback": {
|
|
164
|
+
"command": "node",
|
|
165
|
+
"args": ["/absolute/path/to/cursor-mcp-feedback/dist/main.js"],
|
|
166
|
+
"timeout": 86400,
|
|
167
|
+
"env": {
|
|
168
|
+
"MCP_FEEDBACK_TIMEOUT": "86400"
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Cursor Hooks
|
|
176
|
+
|
|
177
|
+
| Hook | Event | Purpose |
|
|
178
|
+
|------|-------|---------|
|
|
179
|
+
| `block-cursor-mcp-feedback.js` | `subagentStart` | Record subagent_id to negative list |
|
|
180
|
+
| `block-cursor-mcp-feedback.js` | `subagentStop` | Remove subagent_id on completion |
|
|
181
|
+
| `block-cursor-mcp-feedback.js` | `beforeMCPExecution` | Deny cursor-mcp-feedback calls from subagents |
|
|
182
|
+
| `block-cursor-mcp-feedback.js` | `afterMCPExecution` | Log feedback_request/response events to events.jsonl |
|
|
183
|
+
| `consume-pending.js` | `preToolUse` | Consume pending messages and inject as agent feedback |
|
|
184
|
+
|
|
185
|
+
## Keyboard Shortcuts
|
|
186
|
+
|
|
187
|
+
| Shortcut | Context | Action |
|
|
188
|
+
|----------|---------|--------|
|
|
189
|
+
| `⌘+Enter` / `Ctrl+Enter` | MCP App Panel | Submit feedback |
|
|
190
|
+
| `Enter` | Floating App | Send message / feedback |
|
|
191
|
+
| `Shift+Enter` | Floating App | Insert newline |
|
|
192
|
+
| `⌘+Shift+M` | Global | Toggle floating panel |
|
|
193
|
+
| `Esc` | Floating App | Collapse to floating button |
|
|
194
|
+
| `⌘+V` | Floating App | Paste image from clipboard |
|
|
195
|
+
|
|
196
|
+
## UI Settings
|
|
197
|
+
|
|
198
|
+
| Setting | Default | Persistence | Description |
|
|
199
|
+
|---------|---------|-------------|-------------|
|
|
200
|
+
| Auto-append reminder | On | `~/.cursor-mcp-feedback-settings.json` | Appends text to every feedback |
|
|
201
|
+
| Auto-append text | `After completing, call interactive_feedback...` | Server-side | The text appended after each feedback |
|
|
202
|
+
|
|
203
|
+
## Server Configuration
|
|
204
|
+
|
|
205
|
+
| Environment Variable | Default | Description |
|
|
206
|
+
|---------------------|---------|-------------|
|
|
207
|
+
| `MCP_FEEDBACK_TIMEOUT` | `86400` (24h) | Server-side timeout in seconds |
|
|
208
|
+
|
|
209
|
+
## Development
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
npm run build:ui # Build the UI (Vite → single-file HTML)
|
|
213
|
+
npm run build:server # Compile TypeScript server
|
|
214
|
+
npm run build # Both
|
|
215
|
+
npm run dev # Run with tsx (dev mode, stdio)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Project Structure
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
src/
|
|
222
|
+
App.tsx # Main React component (MCP App Panel UI)
|
|
223
|
+
mcp-app.tsx # React entry point
|
|
224
|
+
styles/app.css # Styles (light + dark theme)
|
|
225
|
+
server.ts # MCP server (tools + resources)
|
|
226
|
+
main.ts # Entry point (stdio/HTTP + auto-install)
|
|
227
|
+
session-store.ts # File-based session CRUD
|
|
228
|
+
logger.ts # File logging
|
|
229
|
+
hooks/
|
|
230
|
+
block-cursor-mcp-feedback.js # Subagent protection + event logging
|
|
231
|
+
consume-pending.js # Pending message delivery
|
|
232
|
+
session-utils.js # Shared session utilities
|
|
233
|
+
floating-app/
|
|
234
|
+
Sources/
|
|
235
|
+
FloatingApp.swift # App delegate, menu bar, window management
|
|
236
|
+
FloatingPanel.swift # NSPanel subclass (keyboard, IME handling)
|
|
237
|
+
FloatingButtonView.swift # Collapsed floating button
|
|
238
|
+
PendingPanelView.swift # Main panel UI (chat, input, tabs)
|
|
239
|
+
SessionManager.swift # Session data, chat history, file I/O
|
|
240
|
+
FileWatcher.swift # File system event monitoring
|
|
241
|
+
ImagePreviewWindow.swift # Image preview via system Preview.app
|
|
242
|
+
Package.swift # Swift Package Manager config
|
|
243
|
+
rules/
|
|
244
|
+
cursor-mcp-feedback.mdc # Cursor rule (auto-installed)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## MCP Tools
|
|
248
|
+
|
|
249
|
+
| Tool | Visibility | Description |
|
|
250
|
+
|------|-----------|-------------|
|
|
251
|
+
| `interactive_feedback` | model | Presents summary (Markdown), blocks until user responds |
|
|
252
|
+
| `submit_feedback` | app-only | Submits user feedback with optional images (called from UI) |
|
|
253
|
+
| `get_system_info` | model | Returns OS, architecture, Node.js version |
|
|
254
|
+
|
|
255
|
+
## Prerequisites
|
|
256
|
+
|
|
257
|
+
- Node.js >= 18
|
|
258
|
+
- macOS 13+ (for floating companion app)
|
|
259
|
+
- MCP host with [MCP Apps](https://modelcontextprotocol.io/extensions/client-matrix) support
|
|
260
|
+
|
|
261
|
+
## License
|
|
262
|
+
|
|
263
|
+
MIT
|
package/dist/logger.d.ts
ADDED
package/dist/logger.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
const LOG_FILE = path.join(os.homedir(), ".cursor-mcp-feedback.log");
|
|
5
|
+
const PID = process.pid;
|
|
6
|
+
function formatLine(level, msg) {
|
|
7
|
+
const ts = new Date().toISOString();
|
|
8
|
+
return `[${ts}] [pid=${PID}] [${level}] ${msg}\n`;
|
|
9
|
+
}
|
|
10
|
+
export function log(msg) {
|
|
11
|
+
const line = formatLine("INFO", msg);
|
|
12
|
+
fs.appendFileSync(LOG_FILE, line);
|
|
13
|
+
console.error("[mcp-feedback]", msg);
|
|
14
|
+
}
|
|
15
|
+
export function logError(msg) {
|
|
16
|
+
const line = formatLine("ERROR", msg);
|
|
17
|
+
fs.appendFileSync(LOG_FILE, line);
|
|
18
|
+
console.error("[mcp-feedback] ERROR:", msg);
|
|
19
|
+
}
|
|
20
|
+
export function logObj(msg, obj) {
|
|
21
|
+
const extra = Object.entries(obj)
|
|
22
|
+
.map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`)
|
|
23
|
+
.join(" ");
|
|
24
|
+
log(`${msg} (${extra})`);
|
|
25
|
+
}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* MCP Feedback App entry point.
|
|
4
|
+
*
|
|
5
|
+
* Modes:
|
|
6
|
+
* --stdio : stdio transport (default, for Claude Desktop / Cursor)
|
|
7
|
+
* --http : HTTP transport on port 3001 (for Claude Web / remote testing)
|
|
8
|
+
*
|
|
9
|
+
* The blocking feedback pattern (interactive_feedback waits for submit_feedback)
|
|
10
|
+
* requires a persistent connection, so stdio is the primary transport.
|
|
11
|
+
* HTTP mode creates a new server per request for stateless tool calls.
|
|
12
|
+
*/
|
|
13
|
+
export {};
|