@web-remarq/mcp 0.2.0 → 0.2.1
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 +31 -0
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -78,6 +78,37 @@ loop:
|
|
|
78
78
|
... work the fix ...
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
### Parallel mode (dispatcher + background subagents)
|
|
82
|
+
|
|
83
|
+
The serial loop above blocks on each fix: feedback that arrives while the
|
|
84
|
+
agent is editing waits its turn. If the client can run background subagents
|
|
85
|
+
(Claude Code's Task tool, for example), run the main agent as a dispatcher
|
|
86
|
+
instead - acknowledge, hand off, return to watching:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
loop:
|
|
90
|
+
result = watch_annotations({ timeoutSeconds: 60 })
|
|
91
|
+
if result.timedOut: continue
|
|
92
|
+
for each annotation in result.annotations:
|
|
93
|
+
acknowledge({ id: annotation.id }) # BEFORE dispatch - closes the
|
|
94
|
+
# redelivery window while the
|
|
95
|
+
# subagent spins up
|
|
96
|
+
dispatch background subagent: # fix the files, then claim_fix
|
|
97
|
+
# do not wait for subagents - go straight back to watch_annotations
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Copy-paste prompt to put an agent on duty in this mode:
|
|
101
|
+
|
|
102
|
+
> You are on annotation duty for this project. Designers drop feedback via
|
|
103
|
+
> the web-remarq MCP server. Run this loop until I tell you to stop: call
|
|
104
|
+
> `watch_annotations` (timeoutSeconds: 60); if it times out, call it again.
|
|
105
|
+
> For EACH annotation it returns, call `acknowledge` with its id first, then
|
|
106
|
+
> dispatch a background subagent that applies the fix to the project files
|
|
107
|
+
> and calls `claim_fix` when done. Do not fix anything yourself in the main
|
|
108
|
+
> loop and do not wait for subagents - go straight back to
|
|
109
|
+
> `watch_annotations` so new feedback is never missed. If a comment is
|
|
110
|
+
> ambiguous or unactionable, `dismiss` it with a reason instead of guessing.
|
|
111
|
+
|
|
81
112
|
## Cloud mode prerequisites
|
|
82
113
|
|
|
83
114
|
1. A Supabase project provisioned with `@web-remarq/cloud` (≥0.2.0). Run both
|
package/dist/server.js
CHANGED
|
@@ -524,7 +524,7 @@ function registerTools(server, storage, opts) {
|
|
|
524
524
|
server.registerTool(
|
|
525
525
|
"watch_annotations",
|
|
526
526
|
{
|
|
527
|
-
description: 'Wait for pending annotations (long-poll). Returns immediately if pending annotations exist; otherwise blocks until one appears or timeoutSeconds (default 25) elapses, then returns {"annotations": [], "timedOut": true}. Call this in a loop to continuously pick up designer feedback.
|
|
527
|
+
description: 'Wait for pending annotations (long-poll). Returns immediately if pending annotations exist; otherwise blocks until one appears or timeoutSeconds (default 25) elapses, then returns {"annotations": [], "timedOut": true}. Call this in a loop to continuously pick up designer feedback. If your environment can run background subagents (e.g. a Task tool), act as a dispatcher: for each returned annotation call acknowledge first (so it stops being redelivered), hand the fix to a background subagent that will claim_fix when done, and return to watch_annotations immediately instead of fixing inline - new feedback must never wait on a fix in progress. Without subagents, acknowledge each annotation before you start fixing it.',
|
|
528
528
|
inputSchema: watchAnnotationsInputSchema.shape
|
|
529
529
|
},
|
|
530
530
|
(input) => cast(handleWatchAnnotations(input, storage, opts.waitForChange))
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts","../src/config.ts","../src/storage-factory.ts","../src/file-storage-adapter.ts","../src/http-server.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/watch-annotations.ts","../src/tools/index.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport type { StorageAdapter } from 'web-remarq'\nimport { parseEnv, ConfigError } from './config.js'\nimport { createStorage } from './storage-factory.js'\nimport { FileStorageAdapter } from './file-storage-adapter.js'\nimport { startHttpServer } from './http-server.js'\nimport { registerTools, type WaitForChange } from './tools/index.js'\n\nconst CLOUD_POLL_MS = 3000\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 let storage: StorageAdapter\n let waitForChange: WaitForChange\n\n if (config.mode === 'local') {\n const adapter = new FileStorageAdapter(config.dataFile)\n await startHttpServer(adapter, config.port)\n console.error(\n `[web-remarq-mcp] local mode — widget endpoint http://127.0.0.1:${config.port}, store ${config.dataFile}`,\n )\n storage = adapter\n waitForChange = (ms) => adapter.waitForChange(ms)\n } else {\n storage = createStorage(config)\n waitForChange = (ms) =>\n new Promise((resolve) => setTimeout(() => resolve(false), Math.min(ms, CLOUD_POLL_MS)))\n }\n\n const server = new McpServer({\n name: 'web-remarq',\n version: '0.2.0',\n })\n\n registerTools(server, storage, { waitForChange })\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 CloudConfig {\n mode: 'cloud'\n projectKey: string\n supabaseUrl: string\n supabaseAnonKey: string\n}\n\nexport interface LocalConfig {\n mode: 'local'\n port: number\n dataFile: string\n}\n\nexport type MCPConfig = CloudConfig | LocalConfig\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\nconst DEFAULT_PORT = 1817\nconst DEFAULT_DATA_FILE = '.remarq/annotations.json'\n\nexport function parseEnv(env: NodeJS.ProcessEnv): MCPConfig {\n const cloudRequested = Boolean(\n env.REMARQ_PROJECT_KEY || env.REMARQ_SUPABASE_URL || env.REMARQ_SUPABASE_ANON_KEY,\n )\n\n if (cloudRequested) {\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 { mode: 'cloud', projectKey, supabaseUrl, supabaseAnonKey }\n }\n\n const rawPort = env.REMARQ_PORT ?? String(DEFAULT_PORT)\n const port = Number(rawPort)\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new ConfigError(`REMARQ_PORT must be an integer between 1 and 65535, got \"${rawPort}\"`)\n }\n\n return { mode: 'local', port, dataFile: env.REMARQ_DATA_FILE ?? DEFAULT_DATA_FILE }\n}\n","import { createCloudStorage } from '@web-remarq/cloud'\nimport type { StorageAdapter } from 'web-remarq'\nimport type { CloudConfig } from './config'\n\nexport function createStorage(config: CloudConfig): StorageAdapter {\n return createCloudStorage({\n projectKey: config.projectKey,\n supabaseUrl: config.supabaseUrl,\n supabaseAnonKey: config.supabaseAnonKey,\n onError: 'throw',\n })\n}\n","import { EventEmitter } from 'node:events'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport type { Annotation, AnnotationStore, StorageAdapter } from 'web-remarq'\n\n/**\n * Local-mode StorageAdapter over a JSON file (default .remarq/annotations.json).\n * All mutations flow through this process (MCP tools + the local HTTP server),\n * so change notification is a plain in-memory emitter — no fs.watch needed.\n */\nexport class FileStorageAdapter implements StorageAdapter {\n /** Monotonic revision — bumps on every mutation. Exposed via GET /store. */\n rev = 0\n private emitter = new EventEmitter()\n /** Serializes mutations (save/remove/clear) so concurrent read-modify-write ops don't clobber each other. */\n private queue: Promise<void> = Promise.resolve()\n\n constructor(private filePath: string) {\n this.emitter.setMaxListeners(0)\n }\n\n async load(): Promise<AnnotationStore | null> {\n if (!existsSync(this.filePath)) return null\n let parsed: unknown\n try {\n parsed = JSON.parse(readFileSync(this.filePath, 'utf8'))\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(`annotations store corrupted at ${this.filePath}: ${message}`)\n }\n const store = parsed as { annotations?: unknown }\n return {\n version: 1,\n annotations: Array.isArray(store.annotations) ? (store.annotations as Annotation[]) : [],\n }\n }\n\n async save(annotation: Annotation): Promise<void> {\n return this.enqueue(async () => {\n const store = (await this.load()) ?? { version: 1 as const, annotations: [] }\n const idx = store.annotations.findIndex((a) => a.id === annotation.id)\n if (idx === -1) store.annotations.push(annotation)\n else store.annotations[idx] = annotation\n this.persist(store)\n })\n }\n\n async remove(id: string): Promise<void> {\n return this.enqueue(async () => {\n const store = (await this.load()) ?? { version: 1 as const, annotations: [] }\n store.annotations = store.annotations.filter((a) => a.id !== id)\n this.persist(store)\n })\n }\n\n async clear(): Promise<void> {\n return this.enqueue(async () => {\n this.persist({ version: 1, annotations: [] })\n })\n }\n\n /** Chains `op` onto the mutation queue; a rejected op doesn't poison later ops. */\n private enqueue(op: () => Promise<void>): Promise<void> {\n const result = this.queue.then(op)\n // Swallow the rejection on the shared chain so the next enqueued op still runs;\n // the caller's own `result` promise still rejects with the original error.\n this.queue = result.catch(() => undefined)\n return result\n }\n\n /** Resolves true on the next mutation, false after timeoutMs. */\n waitForChange(timeoutMs: number): Promise<boolean> {\n return new Promise((resolve) => {\n const onChange = (): void => {\n clearTimeout(timer)\n resolve(true)\n }\n const timer = setTimeout(() => {\n this.emitter.off('change', onChange)\n resolve(false)\n }, timeoutMs)\n this.emitter.once('change', onChange)\n })\n }\n\n private persist(store: AnnotationStore): void {\n const dir = dirname(this.filePath)\n mkdirSync(dir, { recursive: true })\n // Auto-ignore the store when it lives in the conventional .remarq dir.\n // NEVER write a wildcard .gitignore into an arbitrary user directory.\n if (basename(dir) === '.remarq') {\n const gitignore = join(dir, '.gitignore')\n if (!existsSync(gitignore)) writeFileSync(gitignore, '*\\n')\n }\n const tmp = `${this.filePath}.tmp`\n writeFileSync(tmp, JSON.stringify(store, null, 2))\n renameSync(tmp, this.filePath)\n this.rev++\n this.emitter.emit('change')\n }\n}\n","import * as http from 'node:http'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { FileStorageAdapter } from './file-storage-adapter.js'\n\nconst CORS_HEADERS: Record<string, string> = {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'content-type',\n}\n\nconst MAX_BODY_BYTES = 1024 * 1024\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { ...CORS_HEADERS, 'content-type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let size = 0\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > MAX_BODY_BYTES) {\n reject(new Error('body too large'))\n req.destroy()\n return\n }\n chunks.push(chunk)\n })\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))\n req.on('error', reject)\n })\n}\n\nasync function handle(req: IncomingMessage, res: ServerResponse, storage: FileStorageAdapter): Promise<void> {\n if (req.method === 'OPTIONS') {\n res.writeHead(204, CORS_HEADERS)\n res.end()\n return\n }\n\n const pathname = new URL(req.url ?? '/', 'http://localhost').pathname\n const annMatch = pathname.match(/^\\/annotations\\/([^/]+)$/)\n\n try {\n if (req.method === 'GET' && pathname === '/store') {\n // Capture rev before the await, not after: a concurrent mutation between\n // load() and reading storage.rev would pair a newer rev with the older\n // content this response body carries. Under-reporting is safe (the\n // client's next poll re-diffs); over-reporting is not.\n const rev = storage.rev\n const store = (await storage.load()) ?? { version: 1 as const, annotations: [] }\n json(res, 200, { rev, store })\n return\n }\n\n if (req.method === 'PUT' && annMatch) {\n const id = decodeURIComponent(annMatch[1])\n let annotation: { id?: unknown }\n try {\n annotation = JSON.parse(await readBody(req))\n } catch {\n json(res, 400, { error: 'invalid JSON body' })\n return\n }\n if (!annotation || annotation.id !== id) {\n json(res, 400, { error: 'annotation.id must match the URL id' })\n return\n }\n // The store is trusted local input from the widget; no schema validation.\n await storage.save(annotation as never)\n json(res, 200, { rev: storage.rev })\n return\n }\n\n if (req.method === 'DELETE' && annMatch) {\n await storage.remove(decodeURIComponent(annMatch[1]))\n json(res, 200, { rev: storage.rev })\n return\n }\n\n if (req.method === 'DELETE' && pathname === '/annotations') {\n await storage.clear()\n json(res, 200, { rev: storage.rev })\n return\n }\n\n json(res, 404, { error: 'not found' })\n } catch (err) {\n json(res, 500, { error: err instanceof Error ? err.message : String(err) })\n }\n}\n\n/** Starts the widget-facing endpoint on 127.0.0.1:port. Rejects on bind errors. */\nexport function startHttpServer(storage: FileStorageAdapter, port: number): Promise<http.Server> {\n const server = http.createServer((req, res) => {\n void handle(req, res, storage)\n })\n return new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', () => resolve(server))\n })\n}\n","import { z } from 'zod'\nimport type { Annotation, AnnotationStatus, QualityCheck, StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\n\nconst STATUS_VALUES = ['draft', '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\nexport interface 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 quality?: QualityCheck['score']\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\nexport function 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 ...(a.qualityCheck ? { quality: a.qualityCheck.score } : {}),\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 { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\nimport { toThin } from './list-annotations.js'\n\n/** Waits up to timeoutMs for a backend change. Local mode resolves early on\n * mutation events; cloud mode just sleeps a poll interval and returns false. */\nexport type WaitForChange = (timeoutMs: number) => Promise<boolean>\n\nconst DEFAULT_TIMEOUT_SECONDS = 25\n\nexport const watchAnnotationsInputSchema = z.object({\n timeoutSeconds: z.number().int().min(1).max(120).optional(),\n})\n\nexport type WatchAnnotationsInput = z.infer<typeof watchAnnotationsInputSchema>\n\nexport async function handleWatchAnnotations(\n input: WatchAnnotationsInput,\n storage: StorageAdapter,\n waitForChange: WaitForChange,\n) {\n const timeoutMs = (input.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS) * 1000\n const deadline = Date.now() + timeoutMs\n\n for (;;) {\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\n const pending = (store?.annotations ?? []).filter((a) => a.status === 'pending')\n if (pending.length > 0) {\n return toolSuccess({ annotations: pending.map(toThin), total: pending.length, timedOut: false })\n }\n\n const remaining = deadline - Date.now()\n if (remaining <= 0) {\n return toolSuccess({ annotations: [], total: 0, timedOut: true })\n }\n\n await waitForChange(remaining)\n }\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'\nimport { watchAnnotationsInputSchema, handleWatchAnnotations, type WaitForChange } from './watch-annotations.js'\n\nexport type { WaitForChange } from './watch-annotations.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(\n server: McpServer,\n storage: StorageAdapter,\n opts: { waitForChange: WaitForChange },\n): void {\n server.registerTool(\n 'list_annotations',\n {\n description: 'List annotations in the project with optional filters (route, status, viewport, file). Each item carries a `quality` score (clear | ambiguous | unactionable) when an AI pre-flight check ran.',\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, grep search hints, and the AI quality verdict (`qualityCheck`). If qualityCheck.score is \"ambiguous\" or \"unactionable\", the comment may need designer clarification before fixing — consider dismissing with a reason instead of guessing.',\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 server.registerTool(\n 'watch_annotations',\n {\n description:\n 'Wait for pending annotations (long-poll). Returns immediately if pending annotations exist; otherwise blocks until one appears or timeoutSeconds (default 25) elapses, then returns {\"annotations\": [], \"timedOut\": true}. Call this in a loop to continuously pick up designer feedback. Acknowledge each annotation you start working on so it stops being delivered.',\n inputSchema: watchAnnotationsInputSchema.shape,\n },\n (input) => cast(handleWatchAnnotations(input, storage, opts.waitForChange)),\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","z","z"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/config.ts","../src/storage-factory.ts","../src/file-storage-adapter.ts","../src/http-server.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/watch-annotations.ts","../src/tools/index.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport type { StorageAdapter } from 'web-remarq'\nimport { parseEnv, ConfigError } from './config.js'\nimport { createStorage } from './storage-factory.js'\nimport { FileStorageAdapter } from './file-storage-adapter.js'\nimport { startHttpServer } from './http-server.js'\nimport { registerTools, type WaitForChange } from './tools/index.js'\n\nconst CLOUD_POLL_MS = 3000\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 let storage: StorageAdapter\n let waitForChange: WaitForChange\n\n if (config.mode === 'local') {\n const adapter = new FileStorageAdapter(config.dataFile)\n await startHttpServer(adapter, config.port)\n console.error(\n `[web-remarq-mcp] local mode — widget endpoint http://127.0.0.1:${config.port}, store ${config.dataFile}`,\n )\n storage = adapter\n waitForChange = (ms) => adapter.waitForChange(ms)\n } else {\n storage = createStorage(config)\n waitForChange = (ms) =>\n new Promise((resolve) => setTimeout(() => resolve(false), Math.min(ms, CLOUD_POLL_MS)))\n }\n\n const server = new McpServer({\n name: 'web-remarq',\n version: '0.2.0',\n })\n\n registerTools(server, storage, { waitForChange })\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 CloudConfig {\n mode: 'cloud'\n projectKey: string\n supabaseUrl: string\n supabaseAnonKey: string\n}\n\nexport interface LocalConfig {\n mode: 'local'\n port: number\n dataFile: string\n}\n\nexport type MCPConfig = CloudConfig | LocalConfig\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\nconst DEFAULT_PORT = 1817\nconst DEFAULT_DATA_FILE = '.remarq/annotations.json'\n\nexport function parseEnv(env: NodeJS.ProcessEnv): MCPConfig {\n const cloudRequested = Boolean(\n env.REMARQ_PROJECT_KEY || env.REMARQ_SUPABASE_URL || env.REMARQ_SUPABASE_ANON_KEY,\n )\n\n if (cloudRequested) {\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 { mode: 'cloud', projectKey, supabaseUrl, supabaseAnonKey }\n }\n\n const rawPort = env.REMARQ_PORT ?? String(DEFAULT_PORT)\n const port = Number(rawPort)\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new ConfigError(`REMARQ_PORT must be an integer between 1 and 65535, got \"${rawPort}\"`)\n }\n\n return { mode: 'local', port, dataFile: env.REMARQ_DATA_FILE ?? DEFAULT_DATA_FILE }\n}\n","import { createCloudStorage } from '@web-remarq/cloud'\nimport type { StorageAdapter } from 'web-remarq'\nimport type { CloudConfig } from './config'\n\nexport function createStorage(config: CloudConfig): StorageAdapter {\n return createCloudStorage({\n projectKey: config.projectKey,\n supabaseUrl: config.supabaseUrl,\n supabaseAnonKey: config.supabaseAnonKey,\n onError: 'throw',\n })\n}\n","import { EventEmitter } from 'node:events'\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { basename, dirname, join } from 'node:path'\nimport type { Annotation, AnnotationStore, StorageAdapter } from 'web-remarq'\n\n/**\n * Local-mode StorageAdapter over a JSON file (default .remarq/annotations.json).\n * All mutations flow through this process (MCP tools + the local HTTP server),\n * so change notification is a plain in-memory emitter — no fs.watch needed.\n */\nexport class FileStorageAdapter implements StorageAdapter {\n /** Monotonic revision — bumps on every mutation. Exposed via GET /store. */\n rev = 0\n private emitter = new EventEmitter()\n /** Serializes mutations (save/remove/clear) so concurrent read-modify-write ops don't clobber each other. */\n private queue: Promise<void> = Promise.resolve()\n\n constructor(private filePath: string) {\n this.emitter.setMaxListeners(0)\n }\n\n async load(): Promise<AnnotationStore | null> {\n if (!existsSync(this.filePath)) return null\n let parsed: unknown\n try {\n parsed = JSON.parse(readFileSync(this.filePath, 'utf8'))\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n throw new Error(`annotations store corrupted at ${this.filePath}: ${message}`)\n }\n const store = parsed as { annotations?: unknown }\n return {\n version: 1,\n annotations: Array.isArray(store.annotations) ? (store.annotations as Annotation[]) : [],\n }\n }\n\n async save(annotation: Annotation): Promise<void> {\n return this.enqueue(async () => {\n const store = (await this.load()) ?? { version: 1 as const, annotations: [] }\n const idx = store.annotations.findIndex((a) => a.id === annotation.id)\n if (idx === -1) store.annotations.push(annotation)\n else store.annotations[idx] = annotation\n this.persist(store)\n })\n }\n\n async remove(id: string): Promise<void> {\n return this.enqueue(async () => {\n const store = (await this.load()) ?? { version: 1 as const, annotations: [] }\n store.annotations = store.annotations.filter((a) => a.id !== id)\n this.persist(store)\n })\n }\n\n async clear(): Promise<void> {\n return this.enqueue(async () => {\n this.persist({ version: 1, annotations: [] })\n })\n }\n\n /** Chains `op` onto the mutation queue; a rejected op doesn't poison later ops. */\n private enqueue(op: () => Promise<void>): Promise<void> {\n const result = this.queue.then(op)\n // Swallow the rejection on the shared chain so the next enqueued op still runs;\n // the caller's own `result` promise still rejects with the original error.\n this.queue = result.catch(() => undefined)\n return result\n }\n\n /** Resolves true on the next mutation, false after timeoutMs. */\n waitForChange(timeoutMs: number): Promise<boolean> {\n return new Promise((resolve) => {\n const onChange = (): void => {\n clearTimeout(timer)\n resolve(true)\n }\n const timer = setTimeout(() => {\n this.emitter.off('change', onChange)\n resolve(false)\n }, timeoutMs)\n this.emitter.once('change', onChange)\n })\n }\n\n private persist(store: AnnotationStore): void {\n const dir = dirname(this.filePath)\n mkdirSync(dir, { recursive: true })\n // Auto-ignore the store when it lives in the conventional .remarq dir.\n // NEVER write a wildcard .gitignore into an arbitrary user directory.\n if (basename(dir) === '.remarq') {\n const gitignore = join(dir, '.gitignore')\n if (!existsSync(gitignore)) writeFileSync(gitignore, '*\\n')\n }\n const tmp = `${this.filePath}.tmp`\n writeFileSync(tmp, JSON.stringify(store, null, 2))\n renameSync(tmp, this.filePath)\n this.rev++\n this.emitter.emit('change')\n }\n}\n","import * as http from 'node:http'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport type { FileStorageAdapter } from './file-storage-adapter.js'\n\nconst CORS_HEADERS: Record<string, string> = {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'content-type',\n}\n\nconst MAX_BODY_BYTES = 1024 * 1024\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { ...CORS_HEADERS, 'content-type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let size = 0\n const chunks: Buffer[] = []\n req.on('data', (chunk: Buffer) => {\n size += chunk.length\n if (size > MAX_BODY_BYTES) {\n reject(new Error('body too large'))\n req.destroy()\n return\n }\n chunks.push(chunk)\n })\n req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))\n req.on('error', reject)\n })\n}\n\nasync function handle(req: IncomingMessage, res: ServerResponse, storage: FileStorageAdapter): Promise<void> {\n if (req.method === 'OPTIONS') {\n res.writeHead(204, CORS_HEADERS)\n res.end()\n return\n }\n\n const pathname = new URL(req.url ?? '/', 'http://localhost').pathname\n const annMatch = pathname.match(/^\\/annotations\\/([^/]+)$/)\n\n try {\n if (req.method === 'GET' && pathname === '/store') {\n // Capture rev before the await, not after: a concurrent mutation between\n // load() and reading storage.rev would pair a newer rev with the older\n // content this response body carries. Under-reporting is safe (the\n // client's next poll re-diffs); over-reporting is not.\n const rev = storage.rev\n const store = (await storage.load()) ?? { version: 1 as const, annotations: [] }\n json(res, 200, { rev, store })\n return\n }\n\n if (req.method === 'PUT' && annMatch) {\n const id = decodeURIComponent(annMatch[1])\n let annotation: { id?: unknown }\n try {\n annotation = JSON.parse(await readBody(req))\n } catch {\n json(res, 400, { error: 'invalid JSON body' })\n return\n }\n if (!annotation || annotation.id !== id) {\n json(res, 400, { error: 'annotation.id must match the URL id' })\n return\n }\n // The store is trusted local input from the widget; no schema validation.\n await storage.save(annotation as never)\n json(res, 200, { rev: storage.rev })\n return\n }\n\n if (req.method === 'DELETE' && annMatch) {\n await storage.remove(decodeURIComponent(annMatch[1]))\n json(res, 200, { rev: storage.rev })\n return\n }\n\n if (req.method === 'DELETE' && pathname === '/annotations') {\n await storage.clear()\n json(res, 200, { rev: storage.rev })\n return\n }\n\n json(res, 404, { error: 'not found' })\n } catch (err) {\n json(res, 500, { error: err instanceof Error ? err.message : String(err) })\n }\n}\n\n/** Starts the widget-facing endpoint on 127.0.0.1:port. Rejects on bind errors. */\nexport function startHttpServer(storage: FileStorageAdapter, port: number): Promise<http.Server> {\n const server = http.createServer((req, res) => {\n void handle(req, res, storage)\n })\n return new Promise((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, '127.0.0.1', () => resolve(server))\n })\n}\n","import { z } from 'zod'\nimport type { Annotation, AnnotationStatus, QualityCheck, StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\n\nconst STATUS_VALUES = ['draft', '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\nexport interface 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 quality?: QualityCheck['score']\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\nexport function 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 ...(a.qualityCheck ? { quality: a.qualityCheck.score } : {}),\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 { z } from 'zod'\nimport type { StorageAdapter } from 'web-remarq'\nimport { toolError, toolSuccess } from '../errors'\nimport { toThin } from './list-annotations.js'\n\n/** Waits up to timeoutMs for a backend change. Local mode resolves early on\n * mutation events; cloud mode just sleeps a poll interval and returns false. */\nexport type WaitForChange = (timeoutMs: number) => Promise<boolean>\n\nconst DEFAULT_TIMEOUT_SECONDS = 25\n\nexport const watchAnnotationsInputSchema = z.object({\n timeoutSeconds: z.number().int().min(1).max(120).optional(),\n})\n\nexport type WatchAnnotationsInput = z.infer<typeof watchAnnotationsInputSchema>\n\nexport async function handleWatchAnnotations(\n input: WatchAnnotationsInput,\n storage: StorageAdapter,\n waitForChange: WaitForChange,\n) {\n const timeoutMs = (input.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS) * 1000\n const deadline = Date.now() + timeoutMs\n\n for (;;) {\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\n const pending = (store?.annotations ?? []).filter((a) => a.status === 'pending')\n if (pending.length > 0) {\n return toolSuccess({ annotations: pending.map(toThin), total: pending.length, timedOut: false })\n }\n\n const remaining = deadline - Date.now()\n if (remaining <= 0) {\n return toolSuccess({ annotations: [], total: 0, timedOut: true })\n }\n\n await waitForChange(remaining)\n }\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'\nimport { watchAnnotationsInputSchema, handleWatchAnnotations, type WaitForChange } from './watch-annotations.js'\n\nexport type { WaitForChange } from './watch-annotations.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(\n server: McpServer,\n storage: StorageAdapter,\n opts: { waitForChange: WaitForChange },\n): void {\n server.registerTool(\n 'list_annotations',\n {\n description: 'List annotations in the project with optional filters (route, status, viewport, file). Each item carries a `quality` score (clear | ambiguous | unactionable) when an AI pre-flight check ran.',\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, grep search hints, and the AI quality verdict (`qualityCheck`). If qualityCheck.score is \"ambiguous\" or \"unactionable\", the comment may need designer clarification before fixing — consider dismissing with a reason instead of guessing.',\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 server.registerTool(\n 'watch_annotations',\n {\n description:\n 'Wait for pending annotations (long-poll). Returns immediately if pending annotations exist; otherwise blocks until one appears or timeoutSeconds (default 25) elapses, then returns {\"annotations\": [], \"timedOut\": true}. Call this in a loop to continuously pick up designer feedback. If your environment can run background subagents (e.g. a Task tool), act as a dispatcher: for each returned annotation call acknowledge first (so it stops being redelivered), hand the fix to a background subagent that will claim_fix when done, and return to watch_annotations immediately instead of fixing inline - new feedback must never wait on a fix in progress. Without subagents, acknowledge each annotation before you start fixing it.',\n inputSchema: watchAnnotationsInputSchema.shape,\n },\n (input) => cast(handleWatchAnnotations(input, storage, opts.waitForChange)),\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","z","z"]}
|
package/package.json
CHANGED