@loupekit/mcp 0.10.7-next.52 → 0.10.8-next.53
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 +2 -2
- package/dist/index.js +16 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,10 +51,10 @@ element, its state, and the page.
|
|
|
51
51
|
|
|
52
52
|
| Tool | Description |
|
|
53
53
|
| --- | --- |
|
|
54
|
-
| `list_comments(status?, url?)` | List comments, optionally filtered by
|
|
54
|
+
| `list_comments(status?, url?)` | List comments, optionally filtered by stage (`queue` / `todo` / `in_progress` / `in_review` / `resolved`) or page URL. The legacy names `open` / `done` are accepted too. |
|
|
55
55
|
| `get_comment(id)` | The full Claude-ready package for one comment: request + element HTML + computed styles + the **screenshot as an image** + any screen-recording URL. |
|
|
56
56
|
| `propose_change(id, html, css?, notes?)` | Write your **modified HTML/CSS** back onto the comment. The dashboard renders it as code plus a live before/after preview for the dev team. |
|
|
57
|
-
| `update_status(id, status)` | Move a comment
|
|
57
|
+
| `update_status(id, status)` | Move a comment along the board (`queue` → `todo` → `in_progress` → `in_review` → `resolved`) so triage state stays in sync. Move to `in_review` when a change is ready — only a person resolves. |
|
|
58
58
|
|
|
59
59
|
## Install
|
|
60
60
|
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,8 @@ import { realpathSync } from "fs";
|
|
|
8
8
|
import { argv } from "process";
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
import { Buffer } from "buffer";
|
|
11
|
+
import { COMMENT_STAGES, normalizeStatus, STAGE_LABELS } from "@loupekit/shared";
|
|
12
|
+
var STAGE_ARG = z.string().describe(`Stage: ${COMMENT_STAGES.join(" / ")}. Legacy "open" and "done" are accepted too.`);
|
|
11
13
|
var API = (process.env.LOUPE_API || "http://localhost:8787").replace(/\/$/, "");
|
|
12
14
|
var PROJECT_KEY = process.env.LOUPE_PROJECT_KEY || "pk_demo_acme";
|
|
13
15
|
var ADMIN = process.env.LOUPE_ADMIN_KEY || "";
|
|
@@ -54,10 +56,13 @@ async function listComments({ status, url }) {
|
|
|
54
56
|
const q = new URLSearchParams({ projectKey: PROJECT_KEY });
|
|
55
57
|
if (url) q.set("url", url);
|
|
56
58
|
let comments = await api(`/v1/comments?${q}`);
|
|
57
|
-
if (status)
|
|
59
|
+
if (status) {
|
|
60
|
+
const want = normalizeStatus(status);
|
|
61
|
+
comments = comments.filter((c) => normalizeStatus(c.status) === want);
|
|
62
|
+
}
|
|
58
63
|
if (!comments.length) return wrap("No comments match.");
|
|
59
64
|
const lines = comments.map(
|
|
60
|
-
(c) => `- [${c.status}] #${c.id} \u2014 ${titleOf(c)}: ${c.body}
|
|
65
|
+
(c) => `- [${STAGE_LABELS[normalizeStatus(c.status)]}] #${c.id} \u2014 ${titleOf(c)}: ${c.body}
|
|
61
66
|
\u21B3 ${targetOf(c)} on ${c.url} (by ${c.author.name})`
|
|
62
67
|
);
|
|
63
68
|
return wrap(`${comments.length} comment(s):
|
|
@@ -70,7 +75,7 @@ async function getComment({ id }) {
|
|
|
70
75
|
const c = await api(`/v1/comments/${encodeURIComponent(id)}`);
|
|
71
76
|
if (c.kind === "free") {
|
|
72
77
|
const text2 = [
|
|
73
|
-
`# Feedback #${c.id} from ${c.author.name} (${c.status})`,
|
|
78
|
+
`# Feedback #${c.id} from ${c.author.name} (${STAGE_LABELS[normalizeStatus(c.status)]})`,
|
|
74
79
|
``,
|
|
75
80
|
`**Title:** ${titleOf(c)}`,
|
|
76
81
|
`**Note:** ${c.body}`,
|
|
@@ -82,7 +87,7 @@ async function getComment({ id }) {
|
|
|
82
87
|
return wrap(text2, ...imgs.map((i) => ({ type: "image", data: i.data, mimeType: i.mimeType })));
|
|
83
88
|
}
|
|
84
89
|
const text = [
|
|
85
|
-
`# Feedback #${c.id} from ${c.author.name} (${c.status})`,
|
|
90
|
+
`# Feedback #${c.id} from ${c.author.name} (${STAGE_LABELS[normalizeStatus(c.status)]})`,
|
|
86
91
|
``,
|
|
87
92
|
`**Title:** ${titleOf(c)}`,
|
|
88
93
|
`**Request:** ${c.body}`,
|
|
@@ -122,8 +127,9 @@ async function getComment({ id }) {
|
|
|
122
127
|
return wrap(text, ...images.map((i) => ({ type: "image", data: i.data, mimeType: i.mimeType })));
|
|
123
128
|
}
|
|
124
129
|
async function updateStatus({ id, status }) {
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
const stage = normalizeStatus(status);
|
|
131
|
+
await api(`/v1/comments/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify({ status: stage }) });
|
|
132
|
+
return wrap(`#${id} \u2192 ${STAGE_LABELS[stage]}`);
|
|
127
133
|
}
|
|
128
134
|
async function proposeChange({ id, html, css, notes }) {
|
|
129
135
|
const proposal = {
|
|
@@ -136,12 +142,12 @@ async function proposeChange({ id, html, css, notes }) {
|
|
|
136
142
|
await api(`/v1/comments/${encodeURIComponent(id)}`, { method: "PATCH", body: JSON.stringify({ proposal }) });
|
|
137
143
|
return wrap(`Proposal saved for #${id}. The dev team can now review your modified HTML/CSS in the dashboard.`);
|
|
138
144
|
}
|
|
139
|
-
var server = new McpServer({ name: "loupe", version: "0.10.
|
|
145
|
+
var server = new McpServer({ name: "loupe", version: "0.10.8" });
|
|
140
146
|
server.tool(
|
|
141
147
|
"list_comments",
|
|
142
148
|
"List Loupe product-feedback comments for the project as a task backlog. Use this to see what a PM has flagged, then work through the items.",
|
|
143
149
|
{
|
|
144
|
-
status:
|
|
150
|
+
status: STAGE_ARG.optional().describe(`Filter by stage. Omit for all.`),
|
|
145
151
|
url: z.string().optional().describe("Filter to a single page path, e.g. /checkout.")
|
|
146
152
|
},
|
|
147
153
|
listComments
|
|
@@ -154,8 +160,8 @@ server.tool(
|
|
|
154
160
|
);
|
|
155
161
|
server.tool(
|
|
156
162
|
"update_status",
|
|
157
|
-
"
|
|
158
|
-
{ id: z.string(), status:
|
|
163
|
+
"Move a comment along the board. Set In Progress when you start it, and In Review when the change is ready for a human \u2014 only a person resolves a comment, so never set Resolved yourself.",
|
|
164
|
+
{ id: z.string(), status: STAGE_ARG },
|
|
159
165
|
updateStatus
|
|
160
166
|
);
|
|
161
167
|
server.tool(
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"email": "m.ashraf.saed@gmail.com",
|
|
6
6
|
"url": "https://www.linkedin.com/in/mohamedashrafelsaed/"
|
|
7
7
|
},
|
|
8
|
-
"version": "0.10.
|
|
8
|
+
"version": "0.10.8-next.53",
|
|
9
9
|
"description": "MCP server that exposes Loupe comments to Claude Code as an actionable, fully-contextualized backlog.",
|
|
10
10
|
"keywords": [
|
|
11
11
|
"loupe",
|
|
@@ -46,6 +46,6 @@
|
|
|
46
46
|
"zod": "^3.24.1"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@loupekit/shared": "0.10.
|
|
49
|
+
"@loupekit/shared": "0.10.8-next.53"
|
|
50
50
|
}
|
|
51
51
|
}
|