@json-to-office/mcp-server 1.8.0 → 1.9.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/dist/cli.js CHANGED
@@ -7,7 +7,7 @@ import { serveStdio } from "@modelcontextprotocol/server/stdio";
7
7
  import { McpServer } from "@modelcontextprotocol/server";
8
8
 
9
9
  // src/lib/version.ts
10
- var SERVER_VERSION = true ? "1.8.0" : "dev-mode";
10
+ var SERVER_VERSION = true ? "1.9.0" : "dev-mode";
11
11
  var SERVER_NAME = "json-to-office";
12
12
  var PACKAGE_NAME = "@json-to-office/mcp-server";
13
13
 
@@ -5253,9 +5253,16 @@ function createWorkspacePersistenceAt(root, limits = {}) {
5253
5253
  },
5254
5254
  async load(handle) {
5255
5255
  if (!isPersistableHandle(handle)) return void 0;
5256
- const meta = await readMeta(handle);
5256
+ let meta = await readMeta(handle);
5257
5257
  if (!meta) return void 0;
5258
- const head = await readRevision(handle, meta.revision);
5258
+ let head = await readRevision(handle, meta.revision);
5259
+ if (!head) {
5260
+ const second = await readMeta(handle);
5261
+ if (second) {
5262
+ meta = second;
5263
+ head = await readRevision(handle, second.revision);
5264
+ }
5265
+ }
5259
5266
  if (!head) {
5260
5267
  await fs7.rm(dirFor(handle), { recursive: true, force: true }).catch(() => void 0);
5261
5268
  return void 0;
@@ -5422,45 +5429,67 @@ function createMemoryWorkspaceStore(options = {}) {
5422
5429
  if (at - entry.touchedAt > limits.idleTtlMs) evict(entry, "ttl");
5423
5430
  }
5424
5431
  }
5432
+ let durable = Promise.resolve();
5433
+ function queued(work) {
5434
+ const running = durable.then(work);
5435
+ durable = running.catch(() => void 0);
5436
+ return running;
5437
+ }
5425
5438
  async function persist(entry) {
5426
5439
  if (!persistence) return void 0;
5427
5440
  try {
5428
- await persistence.save({
5429
- handle: entry.handle,
5430
- format: entry.format,
5431
- createdAt: entry.createdAt,
5432
- updatedAt: entry.updatedAt,
5433
- ...entry.title !== void 0 && { title: entry.title },
5434
- head: {
5435
- revision: entry.revision,
5436
- text: entry.text,
5437
- bytes: entry.bytes
5438
- },
5439
- pins: [...entry.pins.entries()].map(([revision, pin]) => ({
5440
- revision,
5441
- text: pin.text,
5442
- bytes: pin.bytes
5443
- }))
5441
+ const written = await queued(async () => {
5442
+ if (entries.get(entry.handle) !== entry) return false;
5443
+ await saveEntry(entry);
5444
+ return true;
5444
5445
  });
5446
+ if (!written) {
5447
+ entry.persisted = false;
5448
+ return void 0;
5449
+ }
5445
5450
  entry.persisted = true;
5446
5451
  return void 0;
5447
5452
  } catch (error) {
5448
5453
  entry.persisted = false;
5449
- return diagnostic(
5450
- WORKSPACE_ERROR_CODES.NOT_PERSISTED,
5451
- `Revision ${entry.revision} of ${entry.handle} is held in memory but was not written to ${persistence.root}: ${error instanceof Error ? error.message : String(error)}`,
5452
- {
5453
- severity: "warning",
5454
- suggestion: "Export the JSON with jto_workspace_snapshot and keep it yourself; this handle will not survive a lost connection.",
5455
- context: {
5456
- handle: entry.handle,
5457
- revision: entry.revision,
5458
- workspaceRoot: persistence.root
5459
- }
5460
- }
5461
- );
5454
+ return notPersisted(entry, error);
5462
5455
  }
5463
5456
  }
5457
+ async function saveEntry(entry) {
5458
+ if (!persistence) return;
5459
+ await persistence.save({
5460
+ handle: entry.handle,
5461
+ format: entry.format,
5462
+ createdAt: entry.createdAt,
5463
+ updatedAt: entry.updatedAt,
5464
+ ...entry.title !== void 0 && { title: entry.title },
5465
+ head: {
5466
+ revision: entry.revision,
5467
+ text: entry.text,
5468
+ bytes: entry.bytes
5469
+ },
5470
+ pins: [...entry.pins.entries()].map(([revision, pin]) => ({
5471
+ revision,
5472
+ text: pin.text,
5473
+ bytes: pin.bytes
5474
+ }))
5475
+ });
5476
+ }
5477
+ function notPersisted(entry, error) {
5478
+ const root = persistence?.root ?? "";
5479
+ return diagnostic(
5480
+ WORKSPACE_ERROR_CODES.NOT_PERSISTED,
5481
+ `Revision ${entry.revision} of ${entry.handle} is held in memory but was not written to ${root}: ${error instanceof Error ? error.message : String(error)}`,
5482
+ {
5483
+ severity: "warning",
5484
+ suggestion: "Export the JSON with jto_workspace_snapshot and keep it yourself; this handle will not survive a lost connection.",
5485
+ context: {
5486
+ handle: entry.handle,
5487
+ revision: entry.revision,
5488
+ workspaceRoot: root
5489
+ }
5490
+ }
5491
+ );
5492
+ }
5464
5493
  function committed(record, warning) {
5465
5494
  return { ok: true, record, ...warning && { warnings: [warning] } };
5466
5495
  }
@@ -5777,24 +5806,33 @@ function createMemoryWorkspaceStore(options = {}) {
5777
5806
  async close(handle) {
5778
5807
  sweep();
5779
5808
  const entry = entries.get(handle);
5780
- let durable = false;
5781
- if (persistence) {
5782
- try {
5783
- durable = await persistence.remove(handle);
5784
- } catch (error) {
5785
- return failure(
5786
- WORKSPACE_ERROR_CODES.NOT_CLOSED,
5787
- `Workspace ${handle} could not be removed from ${persistence.root}: ${error instanceof Error ? error.message : String(error)}. It is still open and still on disk.`,
5788
- {
5789
- suggestion: "Check the workspace directory is writable, then close again.",
5790
- context: { handle, workspaceRoot: persistence.root }
5791
- }
5792
- );
5793
- }
5809
+ if (!persistence) {
5810
+ if (entry) evict(entry, "closed");
5811
+ return { ok: true, handle, closed: entry !== void 0 };
5812
+ }
5813
+ const root = persistence.root;
5814
+ try {
5815
+ return await queued(async () => {
5816
+ const removed = await persistence.remove(handle);
5817
+ const resident = entries.get(handle);
5818
+ if (resident) evict(resident, "closed");
5819
+ else if (removed) tombstone(handle, "closed", 0);
5820
+ return {
5821
+ ok: true,
5822
+ handle,
5823
+ closed: resident !== void 0 || removed
5824
+ };
5825
+ });
5826
+ } catch (error) {
5827
+ return failure(
5828
+ WORKSPACE_ERROR_CODES.NOT_CLOSED,
5829
+ `Workspace ${handle} could not be removed from ${root}: ${error instanceof Error ? error.message : String(error)}. It is still open and still on disk.`,
5830
+ {
5831
+ suggestion: "Check the workspace directory is writable, then close again.",
5832
+ context: { handle, workspaceRoot: root }
5833
+ }
5834
+ );
5794
5835
  }
5795
- if (entry) evict(entry, "closed");
5796
- else if (durable) tombstone(handle, "closed", 0);
5797
- return { ok: true, handle, closed: entry !== void 0 || durable };
5798
5836
  },
5799
5837
  /**
5800
5838
  * Release memory, keep the disk.