@attentionform/astra-mcp-server 0.4.2 → 0.5.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.
@@ -1,3 +1,5 @@
1
+ import { handleExportOriginalDocument, handleRestoreOriginalDocument } from './original';
2
+ import { type OriginalInfo } from '@attentionform/astra-engine';
1
3
  import type { McpSessionStore } from '../../session-store';
2
4
  import type { McpErrorShape } from '../errors';
3
5
  import type { ChangedValue, DiscardedUnsavedSummary } from '../diff';
@@ -24,6 +26,7 @@ export declare function handleGetDocumentHistory(store: McpSessionStore, input:
24
26
  history: HistoryEntry[];
25
27
  /** R-6 sidecar-removal warning (string when a regenerated chain replaced recorded history, else null). Additive, never a failure. */
26
28
  warning: string | null;
29
+ original: OriginalInfo;
27
30
  } | McpErrorShape>;
28
31
  export declare function handleRevertDocument(store: McpSessionStore, input: unknown): Promise<{
29
32
  ok: true;
@@ -94,6 +97,8 @@ export declare function handlePreviewRevert(store: McpSessionStore, input: unkno
94
97
  } | McpErrorShape>;
95
98
  /** Git-history dispatch table (registered alongside lean-6 in index.ts). */
96
99
  export declare const GIT_HISTORY_HANDLERS: {
100
+ readonly export_original_document: typeof handleExportOriginalDocument;
101
+ readonly restore_original_document: typeof handleRestoreOriginalDocument;
97
102
  readonly get_document_history: typeof handleGetDocumentHistory;
98
103
  readonly preview_revert: typeof handlePreviewRevert;
99
104
  readonly revert_document: typeof handleRevertDocument;
@@ -17,6 +17,8 @@ export declare function handleOpenDocument(store: McpSessionStore, input: unknow
17
17
  evicted: string[];
18
18
  pendingNormalizations: string[];
19
19
  validation: OpenValidationField;
20
+ original?: import('@attentionform/astra-engine').OriginalInfo;
21
+ originalWarning?: string;
20
22
  } | McpErrorShape>;
21
23
  /**
22
24
  * Phase C-2: docs rendering under ~2000 tokens return the full TOON
@@ -25,6 +27,15 @@ export declare function handleOpenDocument(store: McpSessionStore, input: unknow
25
27
  * full dump to first window — the navigation remedy teaches paging.
26
28
  */
27
29
  export declare const INSPECT_FULL_TOON_TOKEN_THRESHOLD = 2000;
30
+ /** What the `outline` tier counts, over the whole document: rows of that tier are headings only. */
31
+ export interface OutlineCounts {
32
+ /** Headings in the document (all of them, whatever `sectionId`, `offset` or `limit` selected). */
33
+ headings: number;
34
+ nodes: number;
35
+ tables: number;
36
+ images: number;
37
+ words: number;
38
+ }
28
39
  export interface InspectWindowEnvelope {
29
40
  totalNodes: number;
30
41
  returnedNodes: number;
@@ -66,6 +77,12 @@ export declare function handleInspectDocument(store: McpSessionStore, input: unk
66
77
  truncated: boolean;
67
78
  /** Present when windowed: teaches search -> aroundNode zoom -> offset paging. */
68
79
  remedy?: string;
80
+ /** Outline tier only: whole-document counts, because rowCount/totalNodes count heading rows there. */
81
+ outline?: OutlineCounts;
82
+ /** Outline tier with aroundNode: the heading the node resolved to (null before the first heading). */
83
+ aroundResolvedTo?: string | null;
84
+ /** Outline tier: why a window is empty or not centred where aroundNode pointed. */
85
+ note?: string;
69
86
  /** Compact summary of the session style guide (absent when none attached). */
70
87
  styleGuide?: StyleGuideSummary;
71
88
  comments?: unknown;
@@ -0,0 +1,25 @@
1
+ import type { McpSessionStore } from '../../session-store';
2
+ /** Read-only export with respect to the live session. Overwriting its own path is deliberately refused. */
3
+ export declare function handleExportOriginalDocument(store: McpSessionStore, input: unknown): Promise<import("../errors").McpErrorShape | {
4
+ ok: true;
5
+ sessionId: string;
6
+ path: string;
7
+ original: import("@attentionform/astra-engine").OriginalInfo;
8
+ }>;
9
+ /** Exact-byte restore. Candidate session is staged separately; normal serialization never overwrites the result. */
10
+ export declare function handleRestoreOriginalDocument(store: McpSessionStore, input: unknown): Promise<import("../errors").McpErrorShape | {
11
+ warning?: string | undefined;
12
+ durabilityUnconfirmed?: boolean | undefined;
13
+ ok: true;
14
+ sessionId: string;
15
+ path: string;
16
+ revision: number;
17
+ dirty: false;
18
+ commitOid: string;
19
+ original: {
20
+ available: true;
21
+ sha256: string;
22
+ bytes: number;
23
+ capturedAt: string;
24
+ };
25
+ }>;
@@ -37,6 +37,12 @@ export declare function handleGetStats(store: McpSessionStore, input: unknown):
37
37
  callouts: number;
38
38
  images: number;
39
39
  pages: number;
40
+ pageTerms: {
41
+ words: number;
42
+ tables: number;
43
+ images: number;
44
+ pageBreaks: number;
45
+ };
40
46
  } | McpErrorShape>;
41
47
  export interface SanitizeDocumentOk {
42
48
  ok: true;
@@ -11,6 +11,7 @@ export declare const OpenDocumentSchema: z.ZodObject<{
11
11
  export declare const InspectDocumentSchema: z.ZodObject<{
12
12
  sessionId: z.ZodString;
13
13
  fidelity: z.ZodOptional<z.ZodEnum<{
14
+ outline: "outline";
14
15
  compact: "compact";
15
16
  standard: "standard";
16
17
  full: "full";
@@ -203,7 +204,25 @@ export declare const ExecuteBatchSchema: z.ZodObject<{
203
204
  fontSize: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
204
205
  sz: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
205
206
  fontFamily: z.ZodOptional<z.ZodString>;
206
- highlight: z.ZodOptional<z.ZodString>;
207
+ highlight: z.ZodOptional<z.ZodEnum<{
208
+ none: "none";
209
+ red: "red";
210
+ green: "green";
211
+ blue: "blue";
212
+ black: "black";
213
+ white: "white";
214
+ yellow: "yellow";
215
+ cyan: "cyan";
216
+ magenta: "magenta";
217
+ darkBlue: "darkBlue";
218
+ darkCyan: "darkCyan";
219
+ darkGreen: "darkGreen";
220
+ darkMagenta: "darkMagenta";
221
+ darkRed: "darkRed";
222
+ darkYellow: "darkYellow";
223
+ darkGray: "darkGray";
224
+ lightGray: "lightGray";
225
+ }>>;
207
226
  lineSpacing: z.ZodOptional<z.ZodNumber>;
208
227
  spacingBefore: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
209
228
  spacingAfter: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
@@ -237,7 +256,25 @@ export declare const ExecuteBatchSchema: z.ZodObject<{
237
256
  fontSize: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
238
257
  sz: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
239
258
  fontFamily: z.ZodOptional<z.ZodString>;
240
- highlight: z.ZodOptional<z.ZodString>;
259
+ highlight: z.ZodOptional<z.ZodEnum<{
260
+ none: "none";
261
+ red: "red";
262
+ green: "green";
263
+ blue: "blue";
264
+ black: "black";
265
+ white: "white";
266
+ yellow: "yellow";
267
+ cyan: "cyan";
268
+ magenta: "magenta";
269
+ darkBlue: "darkBlue";
270
+ darkCyan: "darkCyan";
271
+ darkGreen: "darkGreen";
272
+ darkMagenta: "darkMagenta";
273
+ darkRed: "darkRed";
274
+ darkYellow: "darkYellow";
275
+ darkGray: "darkGray";
276
+ lightGray: "lightGray";
277
+ }>>;
241
278
  lineSpacing: z.ZodOptional<z.ZodNumber>;
242
279
  spacingBefore: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
243
280
  spacingAfter: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
@@ -270,7 +307,25 @@ export declare const ExecuteBatchSchema: z.ZodObject<{
270
307
  fontSize: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
271
308
  sz: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
272
309
  fontFamily: z.ZodOptional<z.ZodString>;
273
- highlight: z.ZodOptional<z.ZodString>;
310
+ highlight: z.ZodOptional<z.ZodEnum<{
311
+ none: "none";
312
+ red: "red";
313
+ green: "green";
314
+ blue: "blue";
315
+ black: "black";
316
+ white: "white";
317
+ yellow: "yellow";
318
+ cyan: "cyan";
319
+ magenta: "magenta";
320
+ darkBlue: "darkBlue";
321
+ darkCyan: "darkCyan";
322
+ darkGreen: "darkGreen";
323
+ darkMagenta: "darkMagenta";
324
+ darkRed: "darkRed";
325
+ darkYellow: "darkYellow";
326
+ darkGray: "darkGray";
327
+ lightGray: "lightGray";
328
+ }>>;
274
329
  lineSpacing: z.ZodOptional<z.ZodNumber>;
275
330
  spacingBefore: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
276
331
  spacingAfter: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
@@ -377,7 +432,7 @@ export declare const ExecuteBatchSchema: z.ZodObject<{
377
432
  }>>;
378
433
  border: z.ZodOptional<z.ZodString>;
379
434
  color: z.ZodOptional<z.ZodString>;
380
- sz: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
435
+ sz: z.ZodOptional<z.ZodNumber>;
381
436
  vAlign: z.ZodOptional<z.ZodString>;
382
437
  align: z.ZodOptional<z.ZodPreprocess<z.ZodEnum<{
383
438
  center: "center";
@@ -777,7 +832,7 @@ export declare const ExecuteBatchSchema: z.ZodObject<{
777
832
  }, z.core.$strict>, z.ZodObject<{
778
833
  action: z.ZodLiteral<"pageBorder">;
779
834
  style: z.ZodOptional<z.ZodString>;
780
- sz: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
835
+ sz: z.ZodOptional<z.ZodNumber>;
781
836
  fontSize: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
782
837
  color: z.ZodOptional<z.ZodString>;
783
838
  marginOffset: z.ZodOptional<z.ZodEnum<{
@@ -971,3 +1026,13 @@ export type GetStatsInput = z.infer<typeof GetStatsSchema>;
971
1026
  export type SanitizeDocumentInput = z.infer<typeof SanitizeDocumentSchema>;
972
1027
  export type NormalizeDocumentInput = z.infer<typeof NormalizeDocumentSchema>;
973
1028
  export type ImportDocumentInput = z.infer<typeof ImportDocumentSchema>;
1029
+ /** Exact retained-input recovery. These paths never serialize the exported original. */
1030
+ export declare const ExportOriginalDocumentSchema: z.ZodObject<{
1031
+ sessionId: z.ZodString;
1032
+ outPath: z.ZodString;
1033
+ overwrite: z.ZodOptional<z.ZodBoolean>;
1034
+ }, z.core.$strict>;
1035
+ export declare const RestoreOriginalDocumentSchema: z.ZodObject<{
1036
+ sessionId: z.ZodString;
1037
+ discard: z.ZodOptional<z.ZodBoolean>;
1038
+ }, z.core.$strict>;
@@ -6,7 +6,7 @@ export declare const LEAN6_TOOL_NAMES: readonly ["open_document", "inspect_docum
6
6
  export type Lean6ToolName = (typeof LEAN6_TOOL_NAMES)[number];
7
7
  export declare function getLean6ToolNames(): Lean6ToolName[];
8
8
  /** Git-history tool names (history browsing + preview + revert + redo; registered alongside lean-6). */
9
- export declare const GIT_HISTORY_TOOL_NAMES: readonly ["get_document_history", "preview_revert", "revert_document", "redo_document"];
9
+ export declare const GIT_HISTORY_TOOL_NAMES: readonly ["get_document_history", "export_original_document", "restore_original_document", "preview_revert", "revert_document", "redo_document"];
10
10
  export type GitHistoryToolName = (typeof GIT_HISTORY_TOOL_NAMES)[number];
11
11
  export declare function getGitHistoryToolNames(): GitHistoryToolName[];
12
12
  /** Document-audit tool names (read-only preflight + census + scrub + canonical repair + file ingest). */
@@ -10,3 +10,4 @@ export * from './mcp/handlers/save-close';
10
10
  export * from './mcp/handlers/history';
11
11
  export * from './mcp/handlers/export-audit';
12
12
  export * from './mcp/registry';
13
+ export * from './mcp/handlers/original';
@@ -1,4 +1,4 @@
1
- import { type DocumentAST, type DocxParserMacroOptions, DocxParser, OperationEngine, ToonGenerator, canonicalizeForAsset as canonicalizeForMcp, type StyleGuideConfig, type ValidationBaseline } from '@attentionform/astra-engine';
1
+ import { type DocumentAST, type DocxParserMacroOptions, DocxParser, OperationEngine, ToonGenerator, canonicalizeForAsset as canonicalizeForMcp, type OriginalInfo, type StyleGuideConfig, type ValidationBaseline } from '@attentionform/astra-engine';
2
2
  /**
3
3
  * Sprint-2 Muse session store (MCP Lean-6 backing).
4
4
  *
@@ -146,6 +146,22 @@ export interface DocHandle {
146
146
  openBaseline?: ValidationBaseline | null;
147
147
  /** sha256 of the file bytes read at open, to tell whether the file on disk is still the opened one. */
148
148
  openSha256?: string;
149
+ /** Fingerprint of the last bytes read or successfully written by ASTra. */
150
+ lastWrittenSha256?: string;
151
+ /** Status of the retained original as this session last learned it. Read it through `resolveSessionOriginal`. */
152
+ originalInfo?: OriginalInfo;
153
+ /**
154
+ * What this session pinned about the retained original, so a later check cannot hand it another history's
155
+ * original: `retained` is the SHA-256 of the verified retained original read at open; `input` is the SHA-256 of
156
+ * the file this session opened, for a session that opened while history initialization was still running.
157
+ * No pin: this session has no claim on any original.
158
+ */
159
+ originalPin?: {
160
+ kind: 'retained' | 'input';
161
+ sha256: string;
162
+ };
163
+ originalWarning?: string;
164
+ macroPolicy?: DocxParserMacroOptions;
149
165
  }
150
166
  /**
151
167
  * Per-commit audit metadata recorded alongside each history commit.
@@ -290,6 +306,9 @@ export declare function validateOpenBufferLabel(rawLabel: unknown): string;
290
306
  * Collects the versioned package extras (media/rels/styles/headers) for git.
291
307
  * document.xml is committed separately; everything matching
292
308
  * isTrackedPackageFile is snapshotted alongside it.
309
+ *
310
+ * Throws when the package snapshot cannot be collected. An empty record would be committed as a complete
311
+ * snapshot with no package parts, and a later revert would then remove the real parts as if that were intended.
293
312
  */
294
313
  export declare function collectTrackedExtrasForGit(parser: DocxParser): Record<string, Buffer>;
295
314
  /**
@@ -299,7 +318,18 @@ export declare function collectTrackedExtrasForGit(parser: DocxParser): Record<s
299
318
  * Best-effort at open (callers swallow failures so open semantics never
300
319
  * change); hard requirement before commitChange at save/revert/redo.
301
320
  */
302
- export declare function ensureGitRepo(docPath: string, xml: string, extras: Record<string, Buffer>): Promise<boolean>;
321
+ export declare function ensureGitRepo(docPath: string, xml: string, extras: Record<string, Buffer>, originalBytes?: Buffer): Promise<boolean>;
322
+ /**
323
+ * The retained original's status for this session, checked now. A session pins one hash when it opens (see
324
+ * `DocHandle.originalPin`); the working document's own bytes are never compared with the original, because an
325
+ * edited document legitimately differs from it.
326
+ * - `retained` pin: the stored original must still verify and still have the pinned SHA-256.
327
+ * - `input` pin (the session opened while another process was initializing the history): the session becomes
328
+ * eligible only once that initialization is complete and the verified original has the SHA-256 of the file
329
+ * this session opened. Until then it reports `initializing`; a different original never upgrades it.
330
+ * - no pin: the status recorded at open stands.
331
+ */
332
+ export declare function resolveSessionOriginal(handle: DocHandle): Promise<OriginalInfo>;
303
333
  /** Outcome of McpSessionStore.closeDocument (dirty state read under the delete lock). */
304
334
  export interface CloseDocumentOutcome {
305
335
  closed: boolean;
@@ -389,7 +419,7 @@ export declare class McpSessionStore {
389
419
  * Macro/active content refuses by default (E_VALIDATION naming the parts);
390
420
  * pass {allowMacros:true} to preserve or {stripMacros:true} to strip.
391
421
  */
392
- openDocument(filePath: string, sessionId?: string, macroOpts?: DocxParserMacroOptions): Promise<DocHandle>;
422
+ openDocument(filePath: string, sessionId?: string, macroOpts?: DocxParserMacroOptions, captureInput?: boolean): Promise<DocHandle>;
393
423
  /**
394
424
  * Opens a document from an in-memory buffer (tests / headless flows).
395
425
  * `labelPath` is the display path recorded on the handle. L4: absolute
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@attentionform/astra-mcp-server",
3
3
  "mcpName": "com.attentionform/astra-mcp-server",
4
- "version": "0.4.2",
4
+ "version": "0.5.1",
5
5
  "description": "Official Model Context Protocol (MCP) server for ASTra document IDE",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -42,8 +42,8 @@
42
42
  "adm-zip-gate": "node ../../scripts/check-adm-zip-imports.mjs"
43
43
  },
44
44
  "dependencies": {
45
- "@attentionform/astra-engine": "^0.4.2",
46
- "@attentionform/ooxml-validator": "^0.4.2",
45
+ "@attentionform/astra-engine": "^0.5.1",
46
+ "@attentionform/ooxml-validator": "^0.5.1",
47
47
  "@modelcontextprotocol/sdk": "^1.32.2",
48
48
  "@xmldom/xmldom": "0.8.15",
49
49
  "adm-zip": "0.6.1",