@web-remarq/mcp 0.1.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/README.md +70 -0
- package/bin/web-remarq-mcp.mjs +5 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +338 -0
- package/dist/server.js.map +1 -0
- package/package.json +61 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @web-remarq/mcp
|
|
2
|
+
|
|
3
|
+
MCP server for [web-remarq](https://github.com/DPostnik/web-remarq) — gives AI
|
|
4
|
+
agents (Claude Code, Cursor, Codex, Windsurf) direct access to project
|
|
5
|
+
annotations stored in the cloud backend (`@web-remarq/cloud`).
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
- Lists annotations with filters by route, status, viewport, or file substring
|
|
10
|
+
- Returns full annotation details including `source: { file, line, column }`
|
|
11
|
+
for the annotated element and grep-friendly search hints
|
|
12
|
+
- Drives the lifecycle: `acknowledge` (pending → in-progress), `claim_fix`
|
|
13
|
+
(→ fixed_unverified), `dismiss` (with optional reason)
|
|
14
|
+
- All MCP-driven changes are recorded as `actor: 'agent'` in the annotation's
|
|
15
|
+
lifecycle history, visible in the widget's History viewer
|
|
16
|
+
|
|
17
|
+
`verify` and `reject` are **not** exposed — verification is human-only via the
|
|
18
|
+
browser widget, by design (core v0.7.0 verification gate).
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
1. A Supabase project provisioned with `@web-remarq/cloud` (≥0.2.0). Run both
|
|
23
|
+
`001_init.sql` and `002_lifecycle.sql` from the cloud package.
|
|
24
|
+
2. A project key generated via `npx @web-remarq/cloud gen-key --name "..."`.
|
|
25
|
+
|
|
26
|
+
## Configuration
|
|
27
|
+
|
|
28
|
+
Add to your editor's MCP config. For Claude Code: use `claude mcp add` CLI or
|
|
29
|
+
edit `~/.claude.json` directly. For Cursor: `~/.cursor/mcp.json`. Other editors:
|
|
30
|
+
consult their MCP setup docs. The JSON shape is the same across editors:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"mcpServers": {
|
|
35
|
+
"web-remarq": {
|
|
36
|
+
"command": "npx",
|
|
37
|
+
"args": ["-y", "@web-remarq/mcp"],
|
|
38
|
+
"env": {
|
|
39
|
+
"REMARQ_PROJECT_KEY": "pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
40
|
+
"REMARQ_SUPABASE_URL": "https://abc.supabase.co",
|
|
41
|
+
"REMARQ_SUPABASE_ANON_KEY": "eyJ..."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
All three env vars are required. The server exits with code 1 and a clear
|
|
49
|
+
stderr message if any are missing or malformed.
|
|
50
|
+
|
|
51
|
+
## Tools
|
|
52
|
+
|
|
53
|
+
| Tool | Input | Returns |
|
|
54
|
+
|------|-------|---------|
|
|
55
|
+
| `list_annotations` | `{ route?, status?, viewportBucket?, file?, limit? }` | `{ annotations[], total }` |
|
|
56
|
+
| `get_annotation` | `{ id }` | Full `AgentAnnotation` shape (source + searchHints + lifecycle) |
|
|
57
|
+
| `acknowledge` | `{ id }` | `{ ok, status }` after `pending → in_progress` |
|
|
58
|
+
| `claim_fix` | `{ id }` | `{ ok, status }` after `pending\|in_progress → fixed_unverified` |
|
|
59
|
+
| `dismiss` | `{ id, reason? }` | `{ ok, status }` after non-terminal → `dismissed` |
|
|
60
|
+
|
|
61
|
+
### Error codes
|
|
62
|
+
|
|
63
|
+
- `annotation_not_found` — id absent in project (also returned if RLS hides it)
|
|
64
|
+
- `invalid_transition` — lifecycle action not allowed from current status; payload includes `currentStatus`
|
|
65
|
+
- `storage_error` — Supabase / network failure; payload includes root cause
|
|
66
|
+
- `validation_error` — input failed zod schema (auto from MCP SDK)
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
MIT
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
// src/server.ts
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
|
|
5
|
+
// src/config.ts
|
|
6
|
+
var ConfigError = class extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "ConfigError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function require_(env, key) {
|
|
13
|
+
const v = env[key];
|
|
14
|
+
if (!v || v.trim() === "") {
|
|
15
|
+
throw new ConfigError(`Missing required env var: ${key}`);
|
|
16
|
+
}
|
|
17
|
+
return v;
|
|
18
|
+
}
|
|
19
|
+
function parseEnv(env) {
|
|
20
|
+
const projectKey = require_(env, "REMARQ_PROJECT_KEY");
|
|
21
|
+
const supabaseUrl = require_(env, "REMARQ_SUPABASE_URL");
|
|
22
|
+
const supabaseAnonKey = require_(env, "REMARQ_SUPABASE_ANON_KEY");
|
|
23
|
+
if (!projectKey.startsWith("pk_")) {
|
|
24
|
+
throw new ConfigError("REMARQ_PROJECT_KEY must start with `pk_` (generated by `npx @web-remarq/cloud gen-key`)");
|
|
25
|
+
}
|
|
26
|
+
if (!supabaseUrl.startsWith("https://")) {
|
|
27
|
+
throw new ConfigError("REMARQ_SUPABASE_URL must start with https://");
|
|
28
|
+
}
|
|
29
|
+
return { projectKey, supabaseUrl, supabaseAnonKey };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// src/storage-factory.ts
|
|
33
|
+
import { createCloudStorage } from "@web-remarq/cloud";
|
|
34
|
+
function createStorage(config) {
|
|
35
|
+
return createCloudStorage({
|
|
36
|
+
projectKey: config.projectKey,
|
|
37
|
+
supabaseUrl: config.supabaseUrl,
|
|
38
|
+
supabaseAnonKey: config.supabaseAnonKey,
|
|
39
|
+
onError: "throw"
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// src/tools/list-annotations.ts
|
|
44
|
+
import { z } from "zod";
|
|
45
|
+
|
|
46
|
+
// src/errors.ts
|
|
47
|
+
function toolError(code, message, details) {
|
|
48
|
+
const payload = { code, message, details };
|
|
49
|
+
return {
|
|
50
|
+
isError: true,
|
|
51
|
+
content: [{ type: "text", text: JSON.stringify(payload) }]
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function toolSuccess(value) {
|
|
55
|
+
return {
|
|
56
|
+
content: [{ type: "text", text: JSON.stringify(value) }]
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// src/tools/list-annotations.ts
|
|
61
|
+
var STATUS_VALUES = ["pending", "in_progress", "fixed_unverified", "verified", "dismissed"];
|
|
62
|
+
var listAnnotationsInputSchema = z.object({
|
|
63
|
+
route: z.string().optional(),
|
|
64
|
+
status: z.union([z.enum(STATUS_VALUES), z.array(z.enum(STATUS_VALUES))]).optional(),
|
|
65
|
+
viewportBucket: z.number().int().optional(),
|
|
66
|
+
file: z.string().optional(),
|
|
67
|
+
limit: z.number().int().min(1).max(200).optional()
|
|
68
|
+
});
|
|
69
|
+
function parseSource(annotation) {
|
|
70
|
+
const fp = annotation.fingerprint;
|
|
71
|
+
const raw = fp.sourceLocation ?? fp.detectedSource;
|
|
72
|
+
if (!raw) return null;
|
|
73
|
+
const parts = raw.split(":");
|
|
74
|
+
if (parts.length < 2) return null;
|
|
75
|
+
const column = parseInt(parts.pop(), 10);
|
|
76
|
+
const line = parseInt(parts.pop(), 10);
|
|
77
|
+
const file = parts.join(":");
|
|
78
|
+
if (!file || isNaN(line)) return null;
|
|
79
|
+
const component = fp.componentName ?? fp.detectedComponent ?? void 0;
|
|
80
|
+
return { file, line, column: isNaN(column) ? 0 : column, ...component ? { component } : {} };
|
|
81
|
+
}
|
|
82
|
+
function toThin(a) {
|
|
83
|
+
return {
|
|
84
|
+
id: a.id,
|
|
85
|
+
route: a.route,
|
|
86
|
+
comment: a.comment,
|
|
87
|
+
status: a.status,
|
|
88
|
+
viewport: a.viewportBucket,
|
|
89
|
+
timestamp: a.timestamp,
|
|
90
|
+
source: parseSource(a)
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async function handleListAnnotations(input, storage) {
|
|
94
|
+
let store;
|
|
95
|
+
try {
|
|
96
|
+
store = await storage.load();
|
|
97
|
+
} catch (err) {
|
|
98
|
+
return toolError("storage_error", err instanceof Error ? err.message : String(err));
|
|
99
|
+
}
|
|
100
|
+
const all = store?.annotations ?? [];
|
|
101
|
+
const statusFilter = Array.isArray(input.status) ? new Set(input.status) : input.status ? /* @__PURE__ */ new Set([input.status]) : null;
|
|
102
|
+
const filtered = all.filter((a) => {
|
|
103
|
+
if (input.route !== void 0 && a.route !== input.route) return false;
|
|
104
|
+
if (statusFilter && !statusFilter.has(a.status)) return false;
|
|
105
|
+
if (input.viewportBucket !== void 0 && a.viewportBucket !== input.viewportBucket) return false;
|
|
106
|
+
if (input.file !== void 0) {
|
|
107
|
+
const src = a.fingerprint.sourceLocation ?? a.fingerprint.detectedSource ?? "";
|
|
108
|
+
if (!src.includes(input.file)) return false;
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
});
|
|
112
|
+
const limit = input.limit ?? 50;
|
|
113
|
+
const thinned = filtered.slice(0, limit).map(toThin);
|
|
114
|
+
return toolSuccess({ annotations: thinned, total: filtered.length });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/tools/get-annotation.ts
|
|
118
|
+
import { z as z2 } from "zod";
|
|
119
|
+
import { generateAgentExport } from "web-remarq/core";
|
|
120
|
+
var getAnnotationInputSchema = z2.object({
|
|
121
|
+
id: z2.string()
|
|
122
|
+
});
|
|
123
|
+
async function handleGetAnnotation(input, storage) {
|
|
124
|
+
let store;
|
|
125
|
+
try {
|
|
126
|
+
store = await storage.load();
|
|
127
|
+
} catch (err) {
|
|
128
|
+
return toolError("storage_error", err instanceof Error ? err.message : String(err));
|
|
129
|
+
}
|
|
130
|
+
const annotation = store?.annotations.find((a) => a.id === input.id);
|
|
131
|
+
if (!annotation) {
|
|
132
|
+
return toolError("annotation_not_found", `Annotation ${input.id} not found in this project`);
|
|
133
|
+
}
|
|
134
|
+
const agentExport = generateAgentExport([annotation], annotation.viewportBucket);
|
|
135
|
+
const agentAnnotation = agentExport.annotations[0];
|
|
136
|
+
return toolSuccess(agentAnnotation);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/tools/acknowledge.ts
|
|
140
|
+
import { z as z3 } from "zod";
|
|
141
|
+
import { transition, InvalidTransitionError } from "web-remarq/core";
|
|
142
|
+
var acknowledgeInputSchema = z3.object({
|
|
143
|
+
id: z3.string()
|
|
144
|
+
});
|
|
145
|
+
async function handleAcknowledge(input, storage) {
|
|
146
|
+
let store;
|
|
147
|
+
try {
|
|
148
|
+
store = await storage.load();
|
|
149
|
+
} catch (err) {
|
|
150
|
+
return toolError("storage_error", err instanceof Error ? err.message : String(err));
|
|
151
|
+
}
|
|
152
|
+
const annotation = store?.annotations.find((a) => a.id === input.id);
|
|
153
|
+
if (!annotation) {
|
|
154
|
+
return toolError("annotation_not_found", `Annotation ${input.id} not found in this project`);
|
|
155
|
+
}
|
|
156
|
+
let result;
|
|
157
|
+
try {
|
|
158
|
+
result = transition(annotation, "acknowledge", { actor: "agent" });
|
|
159
|
+
} catch (err) {
|
|
160
|
+
if (err instanceof InvalidTransitionError) {
|
|
161
|
+
return toolError("invalid_transition", err.message, {
|
|
162
|
+
currentStatus: annotation.status,
|
|
163
|
+
requestedTransition: "acknowledge"
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
throw err;
|
|
167
|
+
}
|
|
168
|
+
const updated = {
|
|
169
|
+
...annotation,
|
|
170
|
+
status: result.status,
|
|
171
|
+
lifecycle: [...annotation.lifecycle, result.event]
|
|
172
|
+
};
|
|
173
|
+
try {
|
|
174
|
+
await storage.save(updated);
|
|
175
|
+
} catch (err) {
|
|
176
|
+
return toolError("storage_error", err instanceof Error ? err.message : String(err));
|
|
177
|
+
}
|
|
178
|
+
return toolSuccess({ ok: true, status: result.status });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/tools/claim-fix.ts
|
|
182
|
+
import { z as z4 } from "zod";
|
|
183
|
+
import { transition as transition2, InvalidTransitionError as InvalidTransitionError2 } from "web-remarq/core";
|
|
184
|
+
var claimFixInputSchema = z4.object({
|
|
185
|
+
id: z4.string()
|
|
186
|
+
});
|
|
187
|
+
async function handleClaimFix(input, storage) {
|
|
188
|
+
let store;
|
|
189
|
+
try {
|
|
190
|
+
store = await storage.load();
|
|
191
|
+
} catch (err) {
|
|
192
|
+
return toolError("storage_error", err instanceof Error ? err.message : String(err));
|
|
193
|
+
}
|
|
194
|
+
const annotation = store?.annotations.find((a) => a.id === input.id);
|
|
195
|
+
if (!annotation) {
|
|
196
|
+
return toolError("annotation_not_found", `Annotation ${input.id} not found in this project`);
|
|
197
|
+
}
|
|
198
|
+
let result;
|
|
199
|
+
try {
|
|
200
|
+
result = transition2(annotation, "claimFix", { actor: "agent" });
|
|
201
|
+
} catch (err) {
|
|
202
|
+
if (err instanceof InvalidTransitionError2) {
|
|
203
|
+
return toolError("invalid_transition", err.message, {
|
|
204
|
+
currentStatus: annotation.status,
|
|
205
|
+
requestedTransition: "claimFix"
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
throw err;
|
|
209
|
+
}
|
|
210
|
+
const updated = {
|
|
211
|
+
...annotation,
|
|
212
|
+
status: result.status,
|
|
213
|
+
lifecycle: [...annotation.lifecycle, result.event]
|
|
214
|
+
};
|
|
215
|
+
try {
|
|
216
|
+
await storage.save(updated);
|
|
217
|
+
} catch (err) {
|
|
218
|
+
return toolError("storage_error", err instanceof Error ? err.message : String(err));
|
|
219
|
+
}
|
|
220
|
+
return toolSuccess({ ok: true, status: result.status });
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// src/tools/dismiss.ts
|
|
224
|
+
import { z as z5 } from "zod";
|
|
225
|
+
import { transition as transition3, InvalidTransitionError as InvalidTransitionError3 } from "web-remarq/core";
|
|
226
|
+
var dismissInputSchema = z5.object({
|
|
227
|
+
id: z5.string(),
|
|
228
|
+
reason: z5.string().optional()
|
|
229
|
+
});
|
|
230
|
+
async function handleDismiss(input, storage) {
|
|
231
|
+
let store;
|
|
232
|
+
try {
|
|
233
|
+
store = await storage.load();
|
|
234
|
+
} catch (err) {
|
|
235
|
+
return toolError("storage_error", err instanceof Error ? err.message : String(err));
|
|
236
|
+
}
|
|
237
|
+
const annotation = store?.annotations.find((a) => a.id === input.id);
|
|
238
|
+
if (!annotation) {
|
|
239
|
+
return toolError("annotation_not_found", `Annotation ${input.id} not found in this project`);
|
|
240
|
+
}
|
|
241
|
+
let result;
|
|
242
|
+
try {
|
|
243
|
+
result = transition3(annotation, "dismiss", { actor: "agent", reason: input.reason });
|
|
244
|
+
} catch (err) {
|
|
245
|
+
if (err instanceof InvalidTransitionError3) {
|
|
246
|
+
return toolError("invalid_transition", err.message, {
|
|
247
|
+
currentStatus: annotation.status,
|
|
248
|
+
requestedTransition: "dismiss"
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
const updated = {
|
|
254
|
+
...annotation,
|
|
255
|
+
status: result.status,
|
|
256
|
+
lifecycle: [...annotation.lifecycle, result.event]
|
|
257
|
+
};
|
|
258
|
+
try {
|
|
259
|
+
await storage.save(updated);
|
|
260
|
+
} catch (err) {
|
|
261
|
+
return toolError("storage_error", err instanceof Error ? err.message : String(err));
|
|
262
|
+
}
|
|
263
|
+
return toolSuccess({ ok: true, status: result.status });
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/tools/index.ts
|
|
267
|
+
function cast(p) {
|
|
268
|
+
return p;
|
|
269
|
+
}
|
|
270
|
+
function registerTools(server, storage) {
|
|
271
|
+
server.registerTool(
|
|
272
|
+
"list_annotations",
|
|
273
|
+
{
|
|
274
|
+
description: "List annotations in the project with optional filters (route, status, viewport, file).",
|
|
275
|
+
inputSchema: listAnnotationsInputSchema.shape
|
|
276
|
+
},
|
|
277
|
+
(input) => cast(handleListAnnotations(input, storage))
|
|
278
|
+
);
|
|
279
|
+
server.registerTool(
|
|
280
|
+
"get_annotation",
|
|
281
|
+
{
|
|
282
|
+
description: "Get full annotation details including source file:line:col and grep search hints.",
|
|
283
|
+
inputSchema: getAnnotationInputSchema.shape
|
|
284
|
+
},
|
|
285
|
+
(input) => cast(handleGetAnnotation(input, storage))
|
|
286
|
+
);
|
|
287
|
+
server.registerTool(
|
|
288
|
+
"acknowledge",
|
|
289
|
+
{
|
|
290
|
+
description: "Mark an annotation as in-progress (pending \u2192 in_progress).",
|
|
291
|
+
inputSchema: acknowledgeInputSchema.shape
|
|
292
|
+
},
|
|
293
|
+
(input) => cast(handleAcknowledge(input, storage))
|
|
294
|
+
);
|
|
295
|
+
server.registerTool(
|
|
296
|
+
"claim_fix",
|
|
297
|
+
{
|
|
298
|
+
description: "Claim a fix for an annotation (\u2192 fixed_unverified). Human verification still required.",
|
|
299
|
+
inputSchema: claimFixInputSchema.shape
|
|
300
|
+
},
|
|
301
|
+
(input) => cast(handleClaimFix(input, storage))
|
|
302
|
+
);
|
|
303
|
+
server.registerTool(
|
|
304
|
+
"dismiss",
|
|
305
|
+
{
|
|
306
|
+
description: "Dismiss an annotation with an optional reason (terminal state).",
|
|
307
|
+
inputSchema: dismissInputSchema.shape
|
|
308
|
+
},
|
|
309
|
+
(input) => cast(handleDismiss(input, storage))
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// src/server.ts
|
|
314
|
+
async function main() {
|
|
315
|
+
let config;
|
|
316
|
+
try {
|
|
317
|
+
config = parseEnv(process.env);
|
|
318
|
+
} catch (err) {
|
|
319
|
+
if (err instanceof ConfigError) {
|
|
320
|
+
console.error(`[web-remarq-mcp] config error: ${err.message}`);
|
|
321
|
+
process.exit(1);
|
|
322
|
+
}
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
325
|
+
const storage = createStorage(config);
|
|
326
|
+
const server = new McpServer({
|
|
327
|
+
name: "web-remarq",
|
|
328
|
+
version: "0.1.0"
|
|
329
|
+
});
|
|
330
|
+
registerTools(server, storage);
|
|
331
|
+
const transport = new StdioServerTransport();
|
|
332
|
+
await server.connect(transport);
|
|
333
|
+
}
|
|
334
|
+
main().catch((err) => {
|
|
335
|
+
console.error("[web-remarq-mcp] fatal:", err);
|
|
336
|
+
process.exit(1);
|
|
337
|
+
});
|
|
338
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/config.ts","../src/storage-factory.ts","../src/tools/list-annotations.ts","../src/errors.ts","../src/tools/get-annotation.ts","../src/tools/acknowledge.ts","../src/tools/claim-fix.ts","../src/tools/dismiss.ts","../src/tools/index.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { parseEnv, ConfigError } from './config.js'\nimport { createStorage } from './storage-factory.js'\nimport { registerTools } from './tools/index.js'\n\nasync function main(): Promise<void> {\n let config\n try {\n config = parseEnv(process.env)\n } catch (err) {\n if (err instanceof ConfigError) {\n console.error(`[web-remarq-mcp] config error: ${err.message}`)\n process.exit(1)\n }\n throw err\n }\n\n const storage = createStorage(config)\n const server = new McpServer({\n name: 'web-remarq',\n version: '0.1.0',\n })\n\n registerTools(server, storage)\n\n const transport = new StdioServerTransport()\n await server.connect(transport)\n}\n\nmain().catch((err) => {\n console.error('[web-remarq-mcp] fatal:', err)\n process.exit(1)\n})\n","export interface MCPConfig {\n projectKey: string\n supabaseUrl: string\n supabaseAnonKey: string\n}\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message)\n this.name = 'ConfigError'\n }\n}\n\nfunction require_(env: NodeJS.ProcessEnv, key: string): string {\n const v = env[key]\n if (!v || v.trim() === '') {\n throw new ConfigError(`Missing required env var: ${key}`)\n }\n return v\n}\n\nexport function parseEnv(env: NodeJS.ProcessEnv): MCPConfig {\n const projectKey = require_(env, 'REMARQ_PROJECT_KEY')\n const supabaseUrl = require_(env, 'REMARQ_SUPABASE_URL')\n const supabaseAnonKey = require_(env, 'REMARQ_SUPABASE_ANON_KEY')\n\n if (!projectKey.startsWith('pk_')) {\n throw new ConfigError('REMARQ_PROJECT_KEY must start with `pk_` (generated by `npx @web-remarq/cloud gen-key`)')\n }\n if (!supabaseUrl.startsWith('https://')) {\n throw new ConfigError('REMARQ_SUPABASE_URL must start with https://')\n }\n\n return { projectKey, supabaseUrl, supabaseAnonKey }\n}\n","import { createCloudStorage } from '@web-remarq/cloud'\nimport type { StorageAdapter } from 'web-remarq'\nimport type { MCPConfig } from './config'\n\nexport function createStorage(config: MCPConfig): StorageAdapter {\n return createCloudStorage({\n projectKey: config.projectKey,\n supabaseUrl: config.supabaseUrl,\n supabaseAnonKey: config.supabaseAnonKey,\n onError: 'throw',\n })\n}\n","import { z } from 'zod'\nimport type { Annotation, AnnotationStatus, StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\n\nconst STATUS_VALUES = ['pending', 'in_progress', 'fixed_unverified', 'verified', 'dismissed'] as const\n\nexport const listAnnotationsInputSchema = z.object({\n route: z.string().optional(),\n status: z.union([z.enum(STATUS_VALUES), z.array(z.enum(STATUS_VALUES))]).optional(),\n viewportBucket: z.number().int().optional(),\n file: z.string().optional(),\n limit: z.number().int().min(1).max(200).optional(),\n})\n\nexport type ListAnnotationsInput = z.infer<typeof listAnnotationsInputSchema>\n\ninterface ThinAnnotation {\n id: string\n route: string\n comment: string\n status: AnnotationStatus\n viewport: number\n timestamp: number\n source: { file: string; line: number; column: number; component?: string } | null\n}\n\nfunction parseSource(annotation: Annotation): ThinAnnotation['source'] {\n const fp = annotation.fingerprint\n const raw = fp.sourceLocation ?? fp.detectedSource\n if (!raw) return null\n const parts = raw.split(':')\n if (parts.length < 2) return null\n const column = parseInt(parts.pop()!, 10)\n const line = parseInt(parts.pop()!, 10)\n const file = parts.join(':')\n if (!file || isNaN(line)) return null\n const component = fp.componentName ?? fp.detectedComponent ?? undefined\n return { file, line, column: isNaN(column) ? 0 : column, ...(component ? { component } : {}) }\n}\n\nfunction toThin(a: Annotation): ThinAnnotation {\n return {\n id: a.id,\n route: a.route,\n comment: a.comment,\n status: a.status,\n viewport: a.viewportBucket,\n timestamp: a.timestamp,\n source: parseSource(a),\n }\n}\n\nexport async function handleListAnnotations(input: ListAnnotationsInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const all = store?.annotations ?? []\n\n const statusFilter = Array.isArray(input.status)\n ? new Set(input.status)\n : input.status\n ? new Set([input.status])\n : null\n\n const filtered = all.filter((a) => {\n if (input.route !== undefined && a.route !== input.route) return false\n if (statusFilter && !statusFilter.has(a.status)) return false\n if (input.viewportBucket !== undefined && a.viewportBucket !== input.viewportBucket) return false\n if (input.file !== undefined) {\n const src = a.fingerprint.sourceLocation ?? a.fingerprint.detectedSource ?? ''\n if (!src.includes(input.file)) return false\n }\n return true\n })\n\n const limit = input.limit ?? 50\n const thinned = filtered.slice(0, limit).map(toThin)\n\n return toolSuccess({ annotations: thinned, total: filtered.length })\n}\n","export type ToolErrorCode =\n | 'annotation_not_found'\n | 'invalid_transition'\n | 'storage_error'\n | 'validation_error'\n\nexport interface ToolErrorPayload {\n code: ToolErrorCode\n message: string\n details?: Record<string, unknown>\n}\n\nexport interface ToolErrorResult {\n isError: true\n content: Array<{ type: 'text'; text: string }>\n}\n\nexport function toolError(code: ToolErrorCode, message: string, details?: Record<string, unknown>): ToolErrorResult {\n const payload: ToolErrorPayload = { code, message, details }\n return {\n isError: true,\n content: [{ type: 'text', text: JSON.stringify(payload) }],\n }\n}\n\nexport interface ToolSuccessResult {\n isError?: false\n content: Array<{ type: 'text'; text: string }>\n}\n\nexport function toolSuccess(value: unknown): ToolSuccessResult {\n return {\n content: [{ type: 'text', text: JSON.stringify(value) }],\n }\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { generateAgentExport } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const getAnnotationInputSchema = z.object({\n id: z.string(),\n})\n\nexport type GetAnnotationInput = z.infer<typeof getAnnotationInputSchema>\n\nexport async function handleGetAnnotation(input: GetAnnotationInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n // Reuse core agent-export to build the rich shape (source + searchHints + lifecycle).\n // generateAgentExport takes an array — pass the single annotation, then extract.\n const agentExport = generateAgentExport([annotation], annotation.viewportBucket)\n const agentAnnotation = agentExport.annotations[0]\n\n return toolSuccess(agentAnnotation)\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const acknowledgeInputSchema = z.object({\n id: z.string(),\n})\n\nexport type AcknowledgeInput = z.infer<typeof acknowledgeInputSchema>\n\nexport async function handleAcknowledge(input: AcknowledgeInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'acknowledge', { actor: 'agent' })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'acknowledge',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const claimFixInputSchema = z.object({\n id: z.string(),\n})\n\nexport type ClaimFixInput = z.infer<typeof claimFixInputSchema>\n\nexport async function handleClaimFix(input: ClaimFixInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'claimFix', { actor: 'agent' })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'claimFix',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { transition, InvalidTransitionError } from 'web-remarq/core'\nimport { toolError, toolSuccess } from '../errors'\n\nexport const dismissInputSchema = z.object({\n id: z.string(),\n reason: z.string().optional(),\n})\n\nexport type DismissInput = z.infer<typeof dismissInputSchema>\n\nexport async function handleDismiss(input: DismissInput, storage: StorageAdapter) {\n let store\n try {\n store = await storage.load()\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n const annotation = store?.annotations.find((a) => a.id === input.id)\n if (!annotation) {\n return toolError('annotation_not_found', `Annotation ${input.id} not found in this project`)\n }\n\n let result\n try {\n result = transition(annotation, 'dismiss', { actor: 'agent', reason: input.reason })\n } catch (err) {\n if (err instanceof InvalidTransitionError) {\n return toolError('invalid_transition', err.message, {\n currentStatus: annotation.status,\n requestedTransition: 'dismiss',\n })\n }\n throw err\n }\n\n const updated = {\n ...annotation,\n status: result.status,\n lifecycle: [...annotation.lifecycle, result.event],\n }\n\n try {\n await storage.save(updated)\n } catch (err) {\n return toolError('storage_error', err instanceof Error ? err.message : String(err))\n }\n\n return toolSuccess({ ok: true, status: result.status })\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport type { StorageAdapter } from 'web-remarq'\n\nimport { listAnnotationsInputSchema, handleListAnnotations } from './list-annotations.js'\nimport { getAnnotationInputSchema, handleGetAnnotation } from './get-annotation.js'\nimport { acknowledgeInputSchema, handleAcknowledge } from './acknowledge.js'\nimport { claimFixInputSchema, handleClaimFix } from './claim-fix.js'\nimport { dismissInputSchema, handleDismiss } from './dismiss.js'\n\n// Cast helper: our tool results satisfy CallToolResult at runtime; the SDK's\n// inferred type carries an index signature that our narrower types lack.\nfunction cast(p: Promise<{ isError?: boolean; content: Array<{ type: 'text'; text: string }> }>): Promise<CallToolResult> {\n return p as Promise<CallToolResult>\n}\n\nexport function registerTools(server: McpServer, storage: StorageAdapter): void {\n server.registerTool(\n 'list_annotations',\n {\n description: 'List annotations in the project with optional filters (route, status, viewport, file).',\n inputSchema: listAnnotationsInputSchema.shape,\n },\n (input) => cast(handleListAnnotations(input, storage)),\n )\n\n server.registerTool(\n 'get_annotation',\n {\n description: 'Get full annotation details including source file:line:col and grep search hints.',\n inputSchema: getAnnotationInputSchema.shape,\n },\n (input) => cast(handleGetAnnotation(input, storage)),\n )\n\n server.registerTool(\n 'acknowledge',\n {\n description: 'Mark an annotation as in-progress (pending → in_progress).',\n inputSchema: acknowledgeInputSchema.shape,\n },\n (input) => cast(handleAcknowledge(input, storage)),\n )\n\n server.registerTool(\n 'claim_fix',\n {\n description: 'Claim a fix for an annotation (→ fixed_unverified). Human verification still required.',\n inputSchema: claimFixInputSchema.shape,\n },\n (input) => cast(handleClaimFix(input, storage)),\n )\n\n server.registerTool(\n 'dismiss',\n {\n description: 'Dismiss an annotation with an optional reason (terminal state).',\n inputSchema: dismissInputSchema.shape,\n },\n (input) => cast(handleDismiss(input, storage)),\n )\n}\n"],"mappings":"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","names":["z","z","z","z","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError","z","transition","InvalidTransitionError"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@web-remarq/mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for web-remarq — AI agents read annotations and drive lifecycle via Supabase cloud backend",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/server.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/server.d.ts",
|
|
10
|
+
"import": "./dist/server.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"web-remarq-mcp": "./bin/web-remarq-mcp.mjs"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"bin",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsup",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"test": "vitest run"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/DPostnik/web-remarq.git"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/DPostnik/web-remarq",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/DPostnik/web-remarq/issues"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"mcp",
|
|
36
|
+
"model-context-protocol",
|
|
37
|
+
"annotation",
|
|
38
|
+
"web-remarq",
|
|
39
|
+
"claude-code",
|
|
40
|
+
"cursor"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
48
|
+
"zod": "^3.23.0",
|
|
49
|
+
"@web-remarq/cloud": "^0.2.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"web-remarq": ">=0.7.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^20.0.0",
|
|
56
|
+
"tsup": "^8.5.1",
|
|
57
|
+
"typescript": "^5.9.3",
|
|
58
|
+
"vitest": "^3.0.0",
|
|
59
|
+
"web-remarq": "*"
|
|
60
|
+
}
|
|
61
|
+
}
|