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

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 +46 -4
  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;
@@ -5135,6 +5139,26 @@ function threadSummary(thread, opts = {}) {
5135
5139
  function uuidField(what) {
5136
5140
  return z24.uuid().describe(what);
5137
5141
  }
5142
+ var CONFLICT_REASON = {
5143
+ fileTrashed: "file_trashed",
5144
+ lockTimeout: "lock_timeout",
5145
+ contentMoved: "content_moved",
5146
+ threadNotOrphaned: "thread_not_orphaned",
5147
+ versionConflict: "version_conflict"
5148
+ };
5149
+ function conflictAdvice(err, parts) {
5150
+ const reason = conflictOf(err)?.reason;
5151
+ switch (reason) {
5152
+ case CONFLICT_REASON.lockTimeout:
5153
+ return "Nothing was written: another write held the file briefly and this one timed out waiting. Retry the same call unchanged.";
5154
+ case CONFLICT_REASON.contentMoved:
5155
+ 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.";
5156
+ case CONFLICT_REASON.fileTrashed:
5157
+ return parts.whenTrashed;
5158
+ default:
5159
+ return parts.otherwise;
5160
+ }
5161
+ }
5138
5162
  var listInputSchema = {
5139
5163
  file_id: uuidField("UUID of the spec file whose comments to list."),
5140
5164
  status: z24.enum(["open", "resolved", "orphaned"]).optional().describe(
@@ -5195,7 +5219,16 @@ var createSpecFileCommentThreadTool = {
5195
5219
  } catch (err) {
5196
5220
  if (isPlatformConflictError(err)) {
5197
5221
  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.`
5222
+ `No thread was created on ${args.file_id}. ` + conflictAdvice(err, {
5223
+ // CONFIRMED trashed: the platform said so, so this states it.
5224
+ whenTrashed: "The file is in the Trash Bin, so it gathers no new discussion. Restore it with restore_spec_file_from_trash first.",
5225
+ // NOT confirmed — an older platform, or a reason this build does
5226
+ // not know. Worded as a hypothesis with a way to check it, which
5227
+ // is also what keeps the two branches distinguishable in a test:
5228
+ // asserting the trashed wording alone would pass against this one
5229
+ // too, so deleting the branch above would go unnoticed.
5230
+ 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."
5231
+ })
5199
5232
  );
5200
5233
  }
5201
5234
  throw err;
@@ -5222,7 +5255,10 @@ var replySpecFileCommentThreadTool = {
5222
5255
  } catch (err) {
5223
5256
  if (isPlatformConflictError(err)) {
5224
5257
  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.`
5258
+ `No reply was posted to ${args.thread_id}. ` + conflictAdvice(err, {
5259
+ whenTrashed: "The file is in the Trash Bin, so it gathers no new discussion. Restore it with restore_spec_file_from_trash first.",
5260
+ 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."
5261
+ })
5226
5262
  );
5227
5263
  }
5228
5264
  throw err;
@@ -5258,7 +5294,13 @@ var updateSpecFileCommentTool = {
5258
5294
  } catch (err) {
5259
5295
  if (isPlatformConflictError(err)) {
5260
5296
  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.`
5297
+ `${args.comment_id} was NOT edited. ` + conflictAdvice(err, {
5298
+ // An edit is allowed on a trashed file (AR-PRJ-45), so the
5299
+ // trashed reason cannot reach this route — both branches below
5300
+ // describe the version race, which is the only conflict it emits.
5301
+ 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.",
5302
+ 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."
5303
+ })
5262
5304
  );
5263
5305
  }
5264
5306
  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.118",
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": {