@myspec/mcp-server 0.5.0-next.117 → 0.5.0-next.119

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 (2) hide show
  1. package/dist/index.js +58 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1353,7 +1353,11 @@ var KNOWN_CONFLICT_REASONS = [
1353
1353
  "precondition_malformed",
1354
1354
  "slug_taken",
1355
1355
  "blob_reclaimed",
1356
- "lock_timeout"
1356
+ "lock_timeout",
1357
+ "content_moved",
1358
+ "file_trashed",
1359
+ "thread_not_orphaned",
1360
+ "version_conflict"
1357
1361
  ];
1358
1362
  var PlatformHttpError = class extends Error {
1359
1363
  status;
@@ -1860,6 +1864,7 @@ var SPEC_FILE_LOCK_TTL_MS = 2 * 6e4;
1860
1864
 
1861
1865
  // ../../packages/platform-client/project/types/comment.types.ts
1862
1866
  var COMMENT_THREAD_FILTER_PARAM = "status";
1867
+ var COMMENT_UNRESOLVED_ONLY_PARAM = "unresolved_only";
1863
1868
  var MAX_COMMENT_BODY_LENGTH = 1e4;
1864
1869
  var MAX_ANCHOR_QUOTE_LENGTH = 2e3;
1865
1870
  var MAX_ANCHOR_CONTEXT_LENGTH = 64;
@@ -1950,9 +1955,16 @@ function transformSpecFileCommentThreadList(raw) {
1950
1955
  function transformProjectCommentCounts(raw) {
1951
1956
  return (raw.counts ?? []).map(transformSpecFileCommentCountResponse);
1952
1957
  }
1958
+ function transformProjectActivityCommentThread(raw) {
1959
+ return {
1960
+ ...transformSpecFileCommentThreadResponse(raw),
1961
+ specFilePath: typeof raw.spec_file_path === "string" ? raw.spec_file_path : null,
1962
+ specFileTrashed: raw.spec_file_trashed === true
1963
+ };
1964
+ }
1953
1965
  function transformProjectCommentActivity(raw) {
1954
1966
  return {
1955
- threads: (raw.threads ?? []).map(transformSpecFileCommentThreadResponse),
1967
+ threads: (raw.threads ?? []).map(transformProjectActivityCommentThread),
1956
1968
  total: raw.total,
1957
1969
  limit: raw.limit,
1958
1970
  offset: raw.offset
@@ -2671,6 +2683,9 @@ var HttpSpecFileCommentClient = class {
2671
2683
  if (opts?.offset !== void 0) {
2672
2684
  query.set("offset", String(opts.offset));
2673
2685
  }
2686
+ if (opts?.unresolvedOnly === true) {
2687
+ query.set(COMMENT_UNRESOLVED_ONLY_PARAM, "true");
2688
+ }
2674
2689
  const suffix = query.toString() ? `?${query.toString()}` : "";
2675
2690
  const raw = await this.httpClient.get(
2676
2691
  `/project/v1/projects/${segment(projectId)}/comments${suffix}`,
@@ -5135,6 +5150,26 @@ function threadSummary(thread, opts = {}) {
5135
5150
  function uuidField(what) {
5136
5151
  return z24.uuid().describe(what);
5137
5152
  }
5153
+ var CONFLICT_REASON = {
5154
+ fileTrashed: "file_trashed",
5155
+ lockTimeout: "lock_timeout",
5156
+ contentMoved: "content_moved",
5157
+ threadNotOrphaned: "thread_not_orphaned",
5158
+ versionConflict: "version_conflict"
5159
+ };
5160
+ function conflictAdvice(err, parts) {
5161
+ const reason = conflictOf(err)?.reason;
5162
+ switch (reason) {
5163
+ case CONFLICT_REASON.lockTimeout:
5164
+ return "Nothing was written: another write held the file briefly and this one timed out waiting. Retry the same call unchanged.";
5165
+ case CONFLICT_REASON.contentMoved:
5166
+ return "Nothing was written: the file changed while the passage was being located, so the anchor would have pointed at text that is no longer current. Re-read the file, find the passage again, and retry.";
5167
+ case CONFLICT_REASON.fileTrashed:
5168
+ return parts.whenTrashed;
5169
+ default:
5170
+ return parts.otherwise;
5171
+ }
5172
+ }
5138
5173
  var listInputSchema = {
5139
5174
  file_id: uuidField("UUID of the spec file whose comments to list."),
5140
5175
  status: z24.enum(["open", "resolved", "orphaned"]).optional().describe(
@@ -5195,7 +5230,16 @@ var createSpecFileCommentThreadTool = {
5195
5230
  } catch (err) {
5196
5231
  if (isPlatformConflictError(err)) {
5197
5232
  return errorResult(
5198
- `No thread was created on ${args.file_id}: the file is in the Trash Bin, so it gathers no new discussion. Restore it with restore_spec_file_from_trash first.`
5233
+ `No thread was created on ${args.file_id}. ` + conflictAdvice(err, {
5234
+ // CONFIRMED trashed: the platform said so, so this states it.
5235
+ whenTrashed: "The file is in the Trash Bin, so it gathers no new discussion. Restore it with restore_spec_file_from_trash first.",
5236
+ // NOT confirmed — an older platform, or a reason this build does
5237
+ // not know. Worded as a hypothesis with a way to check it, which
5238
+ // is also what keeps the two branches distinguishable in a test:
5239
+ // asserting the trashed wording alone would pass against this one
5240
+ // too, so deleting the branch above would go unnoticed.
5241
+ otherwise: "The write was refused as a conflict, and the platform gave no reason. The usual cause is a trashed file \u2014 confirm with get_spec_file before doing anything else."
5242
+ })
5199
5243
  );
5200
5244
  }
5201
5245
  throw err;
@@ -5222,7 +5266,10 @@ var replySpecFileCommentThreadTool = {
5222
5266
  } catch (err) {
5223
5267
  if (isPlatformConflictError(err)) {
5224
5268
  return errorResult(
5225
- `No reply was posted to ${args.thread_id}: the file is in the Trash Bin, so it gathers no new discussion. Restore it with restore_spec_file_from_trash first.`
5269
+ `No reply was posted to ${args.thread_id}. ` + conflictAdvice(err, {
5270
+ whenTrashed: "The file is in the Trash Bin, so it gathers no new discussion. Restore it with restore_spec_file_from_trash first.",
5271
+ otherwise: "The reply was refused as a conflict, and the platform gave no reason. The usual cause is a trashed file \u2014 confirm with get_spec_file before doing anything else."
5272
+ })
5226
5273
  );
5227
5274
  }
5228
5275
  throw err;
@@ -5258,7 +5305,13 @@ var updateSpecFileCommentTool = {
5258
5305
  } catch (err) {
5259
5306
  if (isPlatformConflictError(err)) {
5260
5307
  return errorResult(
5261
- `${args.comment_id} was NOT edited: it has changed since the version you passed. Re-read it with list_spec_file_comments, re-apply your change, and retry with the new content_version.`
5308
+ `${args.comment_id} was NOT edited. ` + conflictAdvice(err, {
5309
+ // An edit is allowed on a trashed file (AR-PRJ-45), so the
5310
+ // trashed reason cannot reach this route — both branches below
5311
+ // describe the version race, which is the only conflict it emits.
5312
+ whenTrashed: "It has changed since the version you passed. Re-read it with list_spec_file_comments, re-apply your change, and retry with the new content_version.",
5313
+ otherwise: "It has changed since the version you passed. Re-read it with list_spec_file_comments, re-apply your change, and retry with the new content_version."
5314
+ })
5262
5315
  );
5263
5316
  }
5264
5317
  throw err;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myspec/mcp-server",
3
- "version": "0.5.0-next.117",
3
+ "version": "0.5.0-next.119",
4
4
  "description": "MySpec MCP server — exposes MySpec platform projects, files and attachments to MCP-aware clients via OAuth-authenticated access tokens.",
5
5
  "type": "module",
6
6
  "repository": {