lace-mcp 0.0.2-alpha.23 → 0.0.2-alpha.25

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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +179 -59
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -30,6 +30,7 @@ The Lace desktop app must be open and signed in for the MCP server to work.
30
30
  | --- | --- |
31
31
  | `search_decisions` | Search and filter resolved decisions with pagination. No params returns the top 20 |
32
32
  | `apply_decision` | Implementation kit for a decision: screenshots, targeting, instructions. `include` controls detail level (`discussion` requires the canvas owner to enable chat sharing) |
33
+ | `publish_artifact` | Publish a local or remote artifact URL back into Lace and receive a shareable review canvas |
33
34
  | `list_canvases` | Browse review canvases with page names and decision counts |
34
35
  | `list_projects` | Browse projects with thread and canvas counts |
35
36
 
package/dist/cli.js CHANGED
@@ -78947,6 +78947,79 @@ var init_mcp = __esm({
78947
78947
  }
78948
78948
  });
78949
78949
 
78950
+ // ../../libs/shared/src/reviewCommentRunBinding.ts
78951
+ var reviewCommentRunBindingSchema;
78952
+ var init_reviewCommentRunBinding = __esm({
78953
+ "../../libs/shared/src/reviewCommentRunBinding.ts"() {
78954
+ "use strict";
78955
+ init_zod();
78956
+ reviewCommentRunBindingSchema = external_exports.object({
78957
+ bindingSource: external_exports.literal("prepared-context"),
78958
+ canvasId: external_exports.string().trim().min(1),
78959
+ commentRunId: external_exports.string().trim().min(1),
78960
+ pageId: external_exports.string().trim().min(1),
78961
+ screenshotId: external_exports.string().trim().min(1).nullable(),
78962
+ shotId: external_exports.string().trim().min(1).nullable(),
78963
+ sourceCaptureStatus: external_exports.enum(["unavailable", "live", "pending-durable", "durable"]),
78964
+ viewport: external_exports.object({
78965
+ height: external_exports.number().int().positive().nullable(),
78966
+ width: external_exports.number().int().positive().nullable()
78967
+ })
78968
+ });
78969
+ }
78970
+ });
78971
+
78972
+ // ../../libs/shared/src/decisionCanvas/canvasMutations.ts
78973
+ var CANVAS_ANNOTATION_CHANGE_EVENT_TYPES, CANVAS_PAGE_CHANGE_EVENT_TYPES, CANVAS_REPLY_CHANGE_EVENT_TYPES, CANVAS_THREAD_CHANGE_EVENT_TYPES, CANVAS_CHANGE_EVENT_TYPES;
78974
+ var init_canvasMutations = __esm({
78975
+ "../../libs/shared/src/decisionCanvas/canvasMutations.ts"() {
78976
+ "use strict";
78977
+ CANVAS_ANNOTATION_CHANGE_EVENT_TYPES = [
78978
+ "annotation-created",
78979
+ "annotation-updated",
78980
+ "annotation-deleted",
78981
+ "annotation-endorsed",
78982
+ "annotation-resolved",
78983
+ "annotation-reopened"
78984
+ ];
78985
+ CANVAS_PAGE_CHANGE_EVENT_TYPES = ["page-added", "page-removed", "page-reordered", "page-updated"];
78986
+ CANVAS_REPLY_CHANGE_EVENT_TYPES = ["reply-created", "reply-updated", "reply-deleted"];
78987
+ CANVAS_THREAD_CHANGE_EVENT_TYPES = ["thread-linked", "thread-unlinked"];
78988
+ CANVAS_CHANGE_EVENT_TYPES = [
78989
+ ...CANVAS_ANNOTATION_CHANGE_EVENT_TYPES,
78990
+ ...CANVAS_PAGE_CHANGE_EVENT_TYPES,
78991
+ ...CANVAS_REPLY_CHANGE_EVENT_TYPES,
78992
+ "canvas-created",
78993
+ "canvas-updated",
78994
+ ...CANVAS_THREAD_CHANGE_EVENT_TYPES
78995
+ ];
78996
+ }
78997
+ });
78998
+
78999
+ // ../../libs/shared/src/decisionCanvas/mcpInstructions.ts
79000
+ var LACE_MCP_INSTRUCTIONS;
79001
+ var init_mcpInstructions = __esm({
79002
+ "../../libs/shared/src/decisionCanvas/mcpInstructions.ts"() {
79003
+ "use strict";
79004
+ LACE_MCP_INSTRUCTIONS = `Lace surfaces UI decisions from product reviews. Decisions drive code changes, slideshows, graphics, and prototypes.
79005
+
79006
+ Discovery:
79007
+ - search_decisions: find decisions by text, canvas, project, app, time, or element. No params = top 20 ranked.
79008
+ - list_canvases: browse review canvases to find canvas IDs for filtering.
79009
+ - list_projects: browse projects to find project IDs for scoping.
79010
+
79011
+ Action:
79012
+ - apply_decision: get the implementation kit for a decision. Set include to control detail level (instructions, crop, discussion, all).
79013
+
79014
+ Publish:
79015
+ - publish_artifact: publish a Vite+React prototype to a shareable canvas link for commenting. Pass source files as [{path, content}]. Returns canvas_id and share_url.
79016
+
79017
+ Workflow: search_decisions -> pick a decision -> apply_decision with the desired include level -> build a prototype -> publish_artifact with source files -> share the returned URL for commenting.
79018
+
79019
+ All tools scope to canvases you have access to. Some canvases may be view-only (title and status visible, no decisions). Decision IDs from search_decisions are valid for apply_decision.`;
79020
+ }
79021
+ });
79022
+
78950
79023
  // ../../libs/shared/src/decisionCanvas/types.ts
78951
79024
  function isFullPageBbox(target) {
78952
79025
  if (target.bbox_x1 == null || target.bbox_y1 == null || target.bbox_x2 == null || target.bbox_y2 == null) {
@@ -78957,11 +79030,14 @@ function isFullPageBbox(target) {
78957
79030
  function isCanvasDecisionAnnotation(annotation) {
78958
79031
  return annotation.kind == null || annotation.kind === CANVAS_ANNOTATION_KIND_DECISION;
78959
79032
  }
78960
- var CANVAS_ANNOTATION_KIND_ELEMENT, CANVAS_ANNOTATION_KIND_DECISION, CANVAS_ANNOTATION_KIND_VALUES, CANVAS_ANNOTATION_STATUS_VALUES, CANVAS_ANNOTATION_ANCHOR_STATE_VALUES, CANVAS_ANNOTATION_ANCHOR_SOURCE_VALUES, CANVAS_ANNOTATION_HEADLINE_MAX_LENGTH, uuidSchema, optionalCanvasTextSchema, canvasBboxCoordinateSchema, optionalIsoDateSchema, createCanvasAnnotationInputSchema, createUnboundAnnotationInputSchema, FULL_PAGE_EPSILON, canvasBboxCoordinateNullableSchema, enrichAnnotationPatchSchema, enrichAnnotationsBulkInputSchema, CANVAS_ANNOTATION_CHANGE_EVENT_TYPES, CANVAS_PAGE_CHANGE_EVENT_TYPES, CANVAS_REPLY_CHANGE_EVENT_TYPES, CANVAS_THREAD_CHANGE_EVENT_TYPES, CANVAS_CHANGE_EVENT_TYPES, LACE_MCP_INSTRUCTIONS;
79033
+ var CANVAS_ANNOTATION_KIND_ELEMENT, CANVAS_ANNOTATION_KIND_DECISION, CANVAS_ANNOTATION_KIND_VALUES, CANVAS_ANNOTATION_STATUS_VALUES, CANVAS_ANNOTATION_ANCHOR_STATE_VALUES, CANVAS_ANNOTATION_ANCHOR_SOURCE_VALUES, CANVAS_ANNOTATION_HEADLINE_MAX_LENGTH, uuidSchema, optionalCanvasTextSchema, canvasBboxCoordinateSchema, canvasBboxCoordinateNullableSchema, optionalIsoDateSchema, createCanvasAnnotationInputSchema, createUnboundAnnotationInputSchema, FULL_PAGE_EPSILON, enrichAnnotationPatchSchema, enrichAnnotationsBulkInputSchema;
78961
79034
  var init_types7 = __esm({
78962
79035
  "../../libs/shared/src/decisionCanvas/types.ts"() {
78963
79036
  "use strict";
78964
79037
  init_zod();
79038
+ init_reviewCommentRunBinding();
79039
+ init_canvasMutations();
79040
+ init_mcpInstructions();
78965
79041
  CANVAS_ANNOTATION_KIND_ELEMENT = "element";
78966
79042
  CANVAS_ANNOTATION_KIND_DECISION = "decision";
78967
79043
  CANVAS_ANNOTATION_KIND_VALUES = [CANVAS_ANNOTATION_KIND_ELEMENT, CANVAS_ANNOTATION_KIND_DECISION];
@@ -78972,6 +79048,7 @@ var init_types7 = __esm({
78972
79048
  uuidSchema = external_exports.string().uuid();
78973
79049
  optionalCanvasTextSchema = external_exports.string().trim().min(1).optional().nullable();
78974
79050
  canvasBboxCoordinateSchema = external_exports.number().min(0).max(1);
79051
+ canvasBboxCoordinateNullableSchema = external_exports.number().min(0).max(1).nullable();
78975
79052
  optionalIsoDateSchema = external_exports.string().trim().min(1).optional().nullable();
78976
79053
  createCanvasAnnotationInputSchema = external_exports.object({
78977
79054
  id: uuidSchema.optional(),
@@ -79008,7 +79085,8 @@ var init_types7 = __esm({
79008
79085
  element_fusion_source: optionalCanvasTextSchema,
79009
79086
  element_content: optionalCanvasTextSchema,
79010
79087
  element_detection_source: optionalCanvasTextSchema,
79011
- element_value: optionalCanvasTextSchema
79088
+ element_value: optionalCanvasTextSchema,
79089
+ comment_run_binding: reviewCommentRunBindingSchema.optional().nullable()
79012
79090
  }).refine((value) => value.bbox_x1 < value.bbox_x2 && value.bbox_y1 < value.bbox_y2).refine((value) => {
79013
79091
  const status = value.status ?? "suggested";
79014
79092
  if (status === "resolved") return value.resolved_at !== null && value.resolved_at !== void 0;
@@ -79021,8 +79099,8 @@ var init_types7 = __esm({
79021
79099
  comment_lineage_id: uuidSchema.optional(),
79022
79100
  headline: external_exports.string().trim().min(1).max(CANVAS_ANNOTATION_HEADLINE_MAX_LENGTH),
79023
79101
  body: external_exports.string().trim().optional().nullable(),
79024
- pin_x: canvasBboxCoordinateSchema,
79025
- pin_y: canvasBboxCoordinateSchema,
79102
+ pin_x: canvasBboxCoordinateNullableSchema,
79103
+ pin_y: canvasBboxCoordinateNullableSchema,
79026
79104
  screenshot_id: external_exports.string().trim().min(1).optional(),
79027
79105
  element_eid: optionalCanvasTextSchema,
79028
79106
  element_tag: optionalCanvasTextSchema,
@@ -79044,12 +79122,14 @@ var init_types7 = __esm({
79044
79122
  sibling_before_tag: optionalCanvasTextSchema,
79045
79123
  sibling_before_text: optionalCanvasTextSchema,
79046
79124
  sibling_after_tag: optionalCanvasTextSchema,
79047
- sibling_after_text: optionalCanvasTextSchema
79125
+ sibling_after_text: optionalCanvasTextSchema,
79126
+ comment_run_binding: reviewCommentRunBindingSchema.optional().nullable()
79048
79127
  });
79049
79128
  FULL_PAGE_EPSILON = 0.01;
79050
- canvasBboxCoordinateNullableSchema = external_exports.number().min(0).max(1).nullable();
79051
79129
  enrichAnnotationPatchSchema = external_exports.object({
79052
79130
  id: external_exports.string().uuid(),
79131
+ page_id: external_exports.string().uuid().nullable().optional(),
79132
+ binding_status: external_exports.enum(["pending", "bound"]).optional(),
79053
79133
  element_eid: optionalCanvasTextSchema,
79054
79134
  element_role: optionalCanvasTextSchema,
79055
79135
  element_visible_text: optionalCanvasTextSchema,
@@ -79069,38 +79149,6 @@ var init_types7 = __esm({
79069
79149
  enrichAnnotationsBulkInputSchema = external_exports.object({
79070
79150
  patches: external_exports.array(enrichAnnotationPatchSchema).min(1).max(500)
79071
79151
  });
79072
- CANVAS_ANNOTATION_CHANGE_EVENT_TYPES = [
79073
- "annotation-created",
79074
- "annotation-updated",
79075
- "annotation-deleted",
79076
- "annotation-endorsed",
79077
- "annotation-resolved",
79078
- "annotation-reopened"
79079
- ];
79080
- CANVAS_PAGE_CHANGE_EVENT_TYPES = ["page-added", "page-removed", "page-reordered", "page-updated"];
79081
- CANVAS_REPLY_CHANGE_EVENT_TYPES = ["reply-created", "reply-updated", "reply-deleted"];
79082
- CANVAS_THREAD_CHANGE_EVENT_TYPES = ["thread-linked", "thread-unlinked"];
79083
- CANVAS_CHANGE_EVENT_TYPES = [
79084
- ...CANVAS_ANNOTATION_CHANGE_EVENT_TYPES,
79085
- ...CANVAS_PAGE_CHANGE_EVENT_TYPES,
79086
- ...CANVAS_REPLY_CHANGE_EVENT_TYPES,
79087
- "canvas-created",
79088
- "canvas-updated",
79089
- ...CANVAS_THREAD_CHANGE_EVENT_TYPES
79090
- ];
79091
- LACE_MCP_INSTRUCTIONS = `Lace surfaces UI decisions from product reviews. Decisions drive code changes, slideshows, graphics, and prototypes.
79092
-
79093
- Discovery:
79094
- - search_decisions: find decisions by text, canvas, project, app, time, or element. No params = top 20 ranked.
79095
- - list_canvases: browse review canvases to find canvas IDs for filtering.
79096
- - list_projects: browse projects to find project IDs for scoping.
79097
-
79098
- Action:
79099
- - apply_decision: get the implementation kit for a decision. Set include to control detail level (instructions, crop, discussion, all).
79100
-
79101
- Workflow: search_decisions -> pick a decision -> apply_decision with the desired include mode.
79102
-
79103
- All tools scope to canvases you have access to. Some canvases may be view-only (title and status visible, no decisions). Decision IDs from search_decisions are valid for apply_decision.`;
79104
79152
  }
79105
79153
  });
79106
79154
 
@@ -79341,7 +79389,7 @@ function serializeDecisionXml(decision) {
79341
79389
  return [
79342
79390
  `<review-item${attr("status", decision.status)}${optionalAttr("anchor_state", anchorState)}${attr("created_at", decision.createdAt)}${optionalAttr("resolved_at", decision.resolvedAt)}>`,
79343
79391
  decision.bbox ? ` <bbox${attr("x1", decision.bbox[0])}${attr("y1", decision.bbox[1])}${attr("x2", decision.bbox[2])}${attr("y2", decision.bbox[3])} />` : "",
79344
- decision.pin && !decision.bbox ? ` <pin${attr("x", decision.pin.x)}${attr("y", decision.pin.y)} />` : "",
79392
+ decision.pin ? ` <pin${attr("x", decision.pin.x)}${attr("y", decision.pin.y)} />` : "",
79345
79393
  ` <element${optionalAttr("role", decision.element.role)}${optionalAttr("label", decision.element.label)}${optionalAttr("type", decision.element.type)}${optionalAttr("value", decision.element.value)}>${actionsXml}`,
79346
79394
  " </element>",
79347
79395
  decision.domContext ? ` <dom-context${optionalAttr("element_tag", decision.domContext.elementTag)}${optionalAttr("parent_tag", decision.domContext.parentTag)}${optionalAttr("parent_text", decision.domContext.parentText)}${optionalAttr("sibling_before_tag", decision.domContext.siblingBeforeTag)}${optionalAttr("sibling_before_text", decision.domContext.siblingBeforeText)}${optionalAttr("sibling_after_tag", decision.domContext.siblingAfterTag)}${optionalAttr("sibling_after_text", decision.domContext.siblingAfterText)} />` : "",
@@ -79442,6 +79490,13 @@ var init_mcpFormat = __esm({
79442
79490
  }
79443
79491
  });
79444
79492
 
79493
+ // ../../libs/shared/src/decisionCanvas/pageImageRecovery.ts
79494
+ var init_pageImageRecovery = __esm({
79495
+ "../../libs/shared/src/decisionCanvas/pageImageRecovery.ts"() {
79496
+ "use strict";
79497
+ }
79498
+ });
79499
+
79445
79500
  // ../../libs/shared/src/decisionCanvas/pagePrimaryImage.ts
79446
79501
  var init_pagePrimaryImage = __esm({
79447
79502
  "../../libs/shared/src/decisionCanvas/pagePrimaryImage.ts"() {
@@ -79458,6 +79513,7 @@ var init_decisionCanvas = __esm({
79458
79513
  init_flow();
79459
79514
  init_interactions();
79460
79515
  init_mcpFormat();
79516
+ init_pageImageRecovery();
79461
79517
  init_pagePrimaryImage();
79462
79518
  init_readModel();
79463
79519
  init_types7();
@@ -79502,26 +79558,8 @@ function isValidBbox(decision) {
79502
79558
  return decision.bbox_x1 != null && decision.bbox_y1 != null && decision.bbox_x2 != null && decision.bbox_y2 != null && [decision.bbox_x1, decision.bbox_y1, decision.bbox_x2, decision.bbox_y2].every(Number.isFinite) && decision.bbox_x1 < decision.bbox_x2 && decision.bbox_y1 < decision.bbox_y2 && // Page-scoped comments are stored as a full-page box; they have no region to crop.
79503
79559
  !isFullPageBbox(decision);
79504
79560
  }
79505
- function placementTimestamp(decision) {
79506
- const createdAt = Date.parse(decision.created_at);
79507
- if (Number.isFinite(createdAt)) return createdAt;
79508
- const resolvedAt = decision.resolved_at ? Date.parse(decision.resolved_at) : Number.NaN;
79509
- return Number.isFinite(resolvedAt) ? resolvedAt : 0;
79510
- }
79511
- function findHistoricalNonDetachedPlacement(decision, allDecisions) {
79512
- let newest = null;
79513
- for (const candidate of allDecisions) {
79514
- if (candidate.id === decision.id) continue;
79515
- if (candidate.comment_lineage_id !== decision.comment_lineage_id) continue;
79516
- if (candidate.anchor_state === "detached") continue;
79517
- if (!newest || placementTimestamp(candidate) > placementTimestamp(newest)) {
79518
- newest = candidate;
79519
- }
79520
- }
79521
- return newest;
79522
- }
79523
79561
  function resolveCropSource(detail) {
79524
- return detail.decision.anchor_state === "detached" ? findHistoricalNonDetachedPlacement(detail.decision, detail.allDecisions) : detail.decision;
79562
+ return detail.decision.anchor_state === "detached" ? null : detail.decision;
79525
79563
  }
79526
79564
  function decisionBbox(decision) {
79527
79565
  if (!isValidBbox(decision)) return null;
@@ -79693,6 +79731,7 @@ function registerListCanvasesTool({ server: server2, loader, getScope, onToolInv
79693
79731
  description: "List review canvases in the current org. Returns title, project, page names, and decision counts per page. Call this when the user mentions a specific design file, screen, or review session by name \u2014 use the returned canvas IDs and titles to scope search_decisions queries.",
79694
79732
  inputSchema: {
79695
79733
  status: external_exports.enum(["active", "archived"]).default("active").optional(),
79734
+ content_type: external_exports.enum(["review", "artifact"]).optional().describe("Filter by canvas content type"),
79696
79735
  projectId: external_exports.string().uuid().optional().describe("Filter by project ID"),
79697
79736
  limit: external_exports.number().int().min(1).max(100).default(50).optional(),
79698
79737
  cursor: external_exports.string().optional()
@@ -79747,11 +79786,64 @@ function registerListProjectsTool({ server: server2, loader, getScope, onToolInv
79747
79786
  }
79748
79787
  );
79749
79788
  }
79789
+ function registerPublishArtifactTool({
79790
+ server: server2,
79791
+ loader,
79792
+ getScope,
79793
+ onToolInvoked,
79794
+ onToolError
79795
+ }) {
79796
+ if (!loader.publishArtifact) return;
79797
+ const publishArtifact = loader.publishArtifact;
79798
+ server2.registerTool(
79799
+ "publish_artifact",
79800
+ {
79801
+ title: "Publish Artifact",
79802
+ description: "Publish a Vite+React prototype to a shareable Lace canvas link for commenting. Returns canvas_id and share_url in the response content.",
79803
+ inputSchema: {
79804
+ title: external_exports.string().describe("Artifact title"),
79805
+ files: external_exports.array(
79806
+ external_exports.object({
79807
+ path: external_exports.string().describe("File path relative to project root (no leading /, no ..)"),
79808
+ content: external_exports.string().describe("File content as text")
79809
+ })
79810
+ ).describe("Source files (no node_modules). Must include package.json.")
79811
+ },
79812
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
79813
+ },
79814
+ async (params) => {
79815
+ onToolInvoked?.("publish_artifact");
79816
+ try {
79817
+ const result = await publishArtifact({ title: params.title, files: params.files }, loaderScope(getScope()));
79818
+ return {
79819
+ content: [
79820
+ {
79821
+ type: "text",
79822
+ text: `Artifact published successfully.
79823
+
79824
+ Canvas ID: ${result.canvasId}
79825
+ Share URL: ${result.shareUrl}
79826
+
79827
+ Share this link with reviewers. They can comment directly on your prototype.`
79828
+ }
79829
+ ]
79830
+ };
79831
+ } catch (e) {
79832
+ onToolError?.(e, { toolName: "publish_artifact" });
79833
+ return loaderErrorResponse(
79834
+ e,
79835
+ "Failed to publish artifact. Check that your files include a valid package.json and try again."
79836
+ );
79837
+ }
79838
+ }
79839
+ );
79840
+ }
79750
79841
  function registerMcpTools(opts) {
79751
79842
  registerSearchDecisionsTool(opts);
79752
79843
  registerApplyDecisionTool(opts);
79753
79844
  registerListCanvasesTool(opts);
79754
79845
  registerListProjectsTool(opts);
79846
+ registerPublishArtifactTool(opts);
79755
79847
  }
79756
79848
  var searchDecisionsSchema;
79757
79849
  var init_mcpToolRegistration = __esm({
@@ -79844,6 +79936,24 @@ async function fetchJson(config4, path) {
79844
79936
  if (!response.ok) throw new DecisionLoaderError(`Request failed (${response.status}: ${response.statusText})`);
79845
79937
  return await response.json();
79846
79938
  }
79939
+ async function postJsonOnce(config4, path, body) {
79940
+ const response = await fetch(`${config4.apiBase}${path}`, {
79941
+ method: "POST",
79942
+ headers: {
79943
+ "Content-Type": "application/json",
79944
+ Accept: "application/json",
79945
+ Authorization: `Bearer ${config4.token}`,
79946
+ "x-org-id": config4.orgId
79947
+ },
79948
+ body: JSON.stringify(body),
79949
+ signal: AbortSignal.timeout(API_ARTIFACT_PUBLISH_TIMEOUT_MS)
79950
+ });
79951
+ if (!response.ok) {
79952
+ const text = await response.text().catch(() => "");
79953
+ throw new DecisionLoaderError(`Request failed (${response.status}): ${text || response.statusText}`);
79954
+ }
79955
+ return await response.json();
79956
+ }
79847
79957
  function searchParamsFromRecord(query) {
79848
79958
  const params = new URLSearchParams();
79849
79959
  for (const [key, value] of Object.entries(query)) {
@@ -80005,6 +80115,7 @@ function createHttpDecisionLoader() {
80005
80115
  const config4 = requireConfig();
80006
80116
  const params = new URLSearchParams();
80007
80117
  if (query.status) params.set("status", query.status);
80118
+ if (query.content_type) params.set("content_type", query.content_type);
80008
80119
  if (query.projectId) params.set("projectId", query.projectId);
80009
80120
  params.set("limit", String(query.limit ?? 50));
80010
80121
  if (query.cursor) params.set("cursor", query.cursor);
@@ -80016,10 +80127,18 @@ function createHttpDecisionLoader() {
80016
80127
  params.set("limit", String(query.limit ?? 50));
80017
80128
  if (query.cursor) params.set("cursor", query.cursor);
80018
80129
  return fetchJson(config4, `/projects?${params}`);
80130
+ },
80131
+ async publishArtifact(input, _scope) {
80132
+ const result = await postJsonOnce(
80133
+ requireConfig(),
80134
+ "/lace/artifacts/publish",
80135
+ input
80136
+ );
80137
+ return { canvasId: result.canvas_id, shareUrl: result.share_url };
80019
80138
  }
80020
80139
  };
80021
80140
  }
80022
- var API_FETCH_TIMEOUT_MS;
80141
+ var API_FETCH_TIMEOUT_MS, API_ARTIFACT_PUBLISH_TIMEOUT_MS;
80023
80142
  var init_decisionLoaderHttp = __esm({
80024
80143
  "src/decisionLoaderHttp.ts"() {
80025
80144
  "use strict";
@@ -80027,6 +80146,7 @@ var init_decisionLoaderHttp = __esm({
80027
80146
  init_mcpDecisionLoader();
80028
80147
  init_auth();
80029
80148
  API_FETCH_TIMEOUT_MS = 3e4;
80149
+ API_ARTIFACT_PUBLISH_TIMEOUT_MS = 12e4;
80030
80150
  }
80031
80151
  });
80032
80152
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lace-mcp",
3
- "version": "0.0.2-alpha.23",
3
+ "version": "0.0.2-alpha.25",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist/cli.js",