circuit-mcp 1.0.14 → 1.0.15
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/README.md +47 -32
- package/package.json +20 -5
- package/src/server.js +92 -3
package/README.md
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Connect [Circuit](https://withcircuit.com) to Cursor and Claude Code via MCP (Model Context Protocol).
|
|
4
4
|
|
|
5
|
+
**Circuit** transforms customer feedback into engineering specs. The MCP brings your priorities and briefs directly into your AI coding assistant.
|
|
6
|
+
|
|
5
7
|
## Quick Start
|
|
6
8
|
|
|
7
9
|
### Cursor
|
|
8
10
|
|
|
9
|
-
Add to
|
|
11
|
+
Add to `~/.cursor/mcp.json`:
|
|
10
12
|
|
|
11
13
|
```json
|
|
12
14
|
{
|
|
@@ -21,62 +23,75 @@ Add to your Cursor settings (`Cmd+Shift+P` → "Cursor Settings: Open User Setti
|
|
|
21
23
|
|
|
22
24
|
### Claude Code
|
|
23
25
|
|
|
24
|
-
Run this command:
|
|
25
|
-
|
|
26
26
|
```bash
|
|
27
27
|
claude mcp add circuit -- npx circuit-mcp
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
## First Run
|
|
31
31
|
|
|
32
|
-
On first use, Circuit
|
|
32
|
+
On first use, Circuit opens your browser to authenticate. Your token is cached at `~/.circuit/token.json`.
|
|
33
33
|
|
|
34
34
|
```
|
|
35
|
-
|
|
36
|
-
│ ⚡ Circuit MCP │
|
|
37
|
-
╰──────────────────────────────────╯
|
|
35
|
+
Circuit MCP
|
|
38
36
|
|
|
39
37
|
First time setup - let's connect your account.
|
|
40
|
-
|
|
41
38
|
Opening browser to authenticate...
|
|
42
39
|
|
|
43
|
-
|
|
40
|
+
Connected!
|
|
44
41
|
```
|
|
45
42
|
|
|
46
|
-
##
|
|
43
|
+
## Available Tools
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
| Tool | Description |
|
|
46
|
+
|------|-------------|
|
|
47
|
+
| `get_priorities` | Get top customer priorities ranked by volume, urgency, or sentiment |
|
|
48
|
+
| `get_brief` | Get the engineering spec for a priority (what to build, why, done criteria) |
|
|
49
|
+
| `search_feedback` | Search raw customer feedback by keyword |
|
|
50
|
+
| `start_building` | Mark a brief as "building" - you're working on it |
|
|
51
|
+
| `mark_done` | Mark a brief as "done" - it shipped! |
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
npx circuit-mcp setup
|
|
53
|
+
## Example Usage
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
npx circuit-mcp auth
|
|
55
|
+
Ask your AI assistant:
|
|
57
56
|
|
|
58
|
-
|
|
59
|
-
npx circuit-mcp logout
|
|
60
|
-
```
|
|
57
|
+
> "What are my top 5 priorities?"
|
|
61
58
|
|
|
62
|
-
|
|
59
|
+
> "Get the brief for priority #1"
|
|
63
60
|
|
|
64
|
-
|
|
61
|
+
> "Search feedback about login issues"
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|------|-------------|
|
|
68
|
-
| `get_priorities` | Get top customer feedback priorities |
|
|
69
|
-
| `get_brief` | Get the engineering brief for a priority |
|
|
70
|
-
| `get_feedback` | Get raw customer feedback items |
|
|
63
|
+
> "Mark that brief as done"
|
|
71
64
|
|
|
72
|
-
|
|
65
|
+
## Commands
|
|
73
66
|
|
|
74
|
-
|
|
67
|
+
```bash
|
|
68
|
+
npx circuit-mcp # Start MCP server (used by Cursor/Claude)
|
|
69
|
+
npx circuit-mcp setup # Show setup instructions
|
|
70
|
+
npx circuit-mcp auth # Re-authenticate
|
|
71
|
+
npx circuit-mcp logout # Clear stored token
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## How It Works
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
Circuit (app.withcircuit.com)
|
|
78
|
+
│
|
|
79
|
+
│ Feedback → Priorities → Briefs
|
|
80
|
+
│
|
|
81
|
+
▼
|
|
82
|
+
Circuit MCP ◄─── Cursor / Claude Code
|
|
83
|
+
│
|
|
84
|
+
│ get_priorities, get_brief, etc.
|
|
85
|
+
│
|
|
86
|
+
▼
|
|
87
|
+
Your AI assistant has context
|
|
88
|
+
```
|
|
75
89
|
|
|
76
|
-
|
|
90
|
+
## Links
|
|
77
91
|
|
|
78
|
-
|
|
92
|
+
- [Circuit](https://withcircuit.com) - Customer feedback intelligence
|
|
93
|
+
- [MCP Protocol](https://modelcontextprotocol.io) - Model Context Protocol spec
|
|
79
94
|
|
|
80
95
|
## License
|
|
81
96
|
|
|
82
|
-
|
|
97
|
+
Proprietary - © Circuit (withcircuit.com)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "circuit-mcp",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Circuit
|
|
3
|
+
"version": "1.0.15",
|
|
4
|
+
"description": "Connect Circuit to Cursor and Claude Code - bring customer priorities and engineering briefs into your AI coding assistant",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"circuit-mcp": "./bin/circuit-mcp.js"
|
|
@@ -13,13 +13,28 @@
|
|
|
13
13
|
"keywords": [
|
|
14
14
|
"circuit",
|
|
15
15
|
"mcp",
|
|
16
|
+
"model-context-protocol",
|
|
16
17
|
"cursor",
|
|
17
18
|
"claude",
|
|
19
|
+
"claude-code",
|
|
18
20
|
"ai",
|
|
19
|
-
"feedback"
|
|
21
|
+
"feedback",
|
|
22
|
+
"priorities",
|
|
23
|
+
"engineering",
|
|
24
|
+
"specs",
|
|
25
|
+
"customer-feedback"
|
|
20
26
|
],
|
|
21
|
-
"author": "Circuit",
|
|
22
|
-
"license": "
|
|
27
|
+
"author": "Circuit <hello@withcircuit.com>",
|
|
28
|
+
"license": "UNLICENSED",
|
|
29
|
+
"homepage": "https://withcircuit.com",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/CatherineWilliamsTreloar/Circuit.git",
|
|
33
|
+
"directory": "circuit-mcp"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/CatherineWilliamsTreloar/Circuit/issues"
|
|
37
|
+
},
|
|
23
38
|
"dependencies": {
|
|
24
39
|
"chalk": "^5.3.0",
|
|
25
40
|
"open": "^10.1.0"
|
package/src/server.js
CHANGED
|
@@ -173,6 +173,19 @@ async function handleMessage(message, token) {
|
|
|
173
173
|
},
|
|
174
174
|
required: ['query']
|
|
175
175
|
}
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'get_insights',
|
|
179
|
+
description: 'Get high-level insights and patterns across your priorities. Identifies themes, trends, and strategic recommendations.',
|
|
180
|
+
inputSchema: {
|
|
181
|
+
type: 'object',
|
|
182
|
+
properties: {
|
|
183
|
+
limit: {
|
|
184
|
+
type: 'number',
|
|
185
|
+
description: 'Number of priorities to analyze (default: 10)'
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
176
189
|
}
|
|
177
190
|
]
|
|
178
191
|
}
|
|
@@ -230,11 +243,15 @@ function formatPriorities(data) {
|
|
|
230
243
|
// Format: #Rank. Title
|
|
231
244
|
lines.push(`**#${p.rank}. ${p.theme}**`);
|
|
232
245
|
|
|
233
|
-
// Badges row: Category | X users | Trend
|
|
246
|
+
// Badges row: Category | X users | Trend | Status
|
|
234
247
|
const badges = [];
|
|
235
248
|
badges.push(p.category || 'Other');
|
|
236
249
|
badges.push(`${p.volume} users`);
|
|
237
250
|
if (trendText) badges.push(trendText.trim());
|
|
251
|
+
if (p.brief_status && p.brief_status !== 'no_brief') {
|
|
252
|
+
const statusLabel = { ready: 'Ready', building: 'Building', done: 'Done' }[p.brief_status];
|
|
253
|
+
if (statusLabel) badges.push(statusLabel);
|
|
254
|
+
}
|
|
238
255
|
|
|
239
256
|
lines.push(badges.join(' · '));
|
|
240
257
|
|
|
@@ -272,8 +289,14 @@ function formatBrief(data) {
|
|
|
272
289
|
output += `> "${p.key_quote}"\n\n`;
|
|
273
290
|
}
|
|
274
291
|
|
|
275
|
-
output += `---\n`;
|
|
276
|
-
|
|
292
|
+
output += `---\n\n`;
|
|
293
|
+
|
|
294
|
+
// Include deep link to Circuit
|
|
295
|
+
if (data.circuit_url) {
|
|
296
|
+
output += `**Generate brief:** ${data.circuit_url}\n\n`;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
output += `Or I can help you draft implementation notes based on the customer feedback above.`;
|
|
277
300
|
return output;
|
|
278
301
|
}
|
|
279
302
|
return `Error: ${data.message || data.error}`;
|
|
@@ -358,6 +381,69 @@ function formatStatusChange(data) {
|
|
|
358
381
|
return JSON.stringify(data, null, 2);
|
|
359
382
|
}
|
|
360
383
|
|
|
384
|
+
/**
|
|
385
|
+
* Format insights for display
|
|
386
|
+
*/
|
|
387
|
+
function formatInsights(data) {
|
|
388
|
+
if (data.message) {
|
|
389
|
+
return data.message;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const lines = [];
|
|
393
|
+
|
|
394
|
+
lines.push(`## Insights from ${data.analyzed} priorities\n`);
|
|
395
|
+
lines.push(`**Total feedback volume:** ${data.total_feedback_volume} mentions\n`);
|
|
396
|
+
|
|
397
|
+
// Category breakdown
|
|
398
|
+
if (data.category_breakdown) {
|
|
399
|
+
lines.push('**Category breakdown:**');
|
|
400
|
+
for (const [cat, count] of Object.entries(data.category_breakdown)) {
|
|
401
|
+
lines.push(`- ${cat}: ${count}`);
|
|
402
|
+
}
|
|
403
|
+
lines.push('');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Top 3 by volume
|
|
407
|
+
if (data.top_3_by_volume && data.top_3_by_volume.length > 0) {
|
|
408
|
+
lines.push('**Top priorities by volume:**');
|
|
409
|
+
for (const p of data.top_3_by_volume) {
|
|
410
|
+
lines.push(`- ${p.theme} (${p.volume} users, ${p.category})`);
|
|
411
|
+
}
|
|
412
|
+
lines.push('');
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Trends
|
|
416
|
+
if (data.trending_up && data.trending_up.length > 0) {
|
|
417
|
+
lines.push(`**Trending up:** ${data.trending_up.join(', ')}`);
|
|
418
|
+
}
|
|
419
|
+
if (data.trending_down && data.trending_down.length > 0) {
|
|
420
|
+
lines.push(`**Trending down:** ${data.trending_down.join(', ')}`);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// High urgency
|
|
424
|
+
if (data.high_urgency && data.high_urgency.length > 0) {
|
|
425
|
+
lines.push('\n**High urgency items:**');
|
|
426
|
+
for (const h of data.high_urgency) {
|
|
427
|
+
lines.push(`- ${h.theme} (urgency: ${h.urgency})`);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// Recommendations
|
|
432
|
+
if (data.recommendations && data.recommendations.length > 0) {
|
|
433
|
+
lines.push('\n**Recommendations:**');
|
|
434
|
+
for (const r of data.recommendations) {
|
|
435
|
+
lines.push(`- ${r}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
lines.push('\n---');
|
|
440
|
+
if (data.circuit_url) {
|
|
441
|
+
lines.push(`View full details: ${data.circuit_url}`);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return lines.join('\n');
|
|
445
|
+
}
|
|
446
|
+
|
|
361
447
|
/**
|
|
362
448
|
* Handle tool calls
|
|
363
449
|
*/
|
|
@@ -385,6 +471,9 @@ async function handleToolCall(id, params, token) {
|
|
|
385
471
|
case 'mark_done':
|
|
386
472
|
formattedText = formatStatusChange(result);
|
|
387
473
|
break;
|
|
474
|
+
case 'get_insights':
|
|
475
|
+
formattedText = formatInsights(result);
|
|
476
|
+
break;
|
|
388
477
|
default:
|
|
389
478
|
formattedText = JSON.stringify(result, null, 2);
|
|
390
479
|
}
|