@bendyline/docblocks-cli 1.1.2 → 2.0.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/README.md +60 -88
- package/dist/commands/convert.d.ts +12 -2
- package/dist/commands/convert.d.ts.map +1 -1
- package/dist/commands/convert.js +272 -101
- package/dist/commands/convert.js.map +1 -1
- package/dist/commands/mcp.d.ts +1 -1
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +90 -4
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/parse.js +1 -1
- package/dist/commands/parse.js.map +1 -1
- package/dist/commands/serve.d.ts +9 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +209 -44
- package/dist/commands/serve.js.map +1 -1
- package/dist/commands/themes.js +1 -1
- package/dist/commands/themes.js.map +1 -1
- package/dist/commands/transforms.js +1 -1
- package/dist/commands/transforms.js.map +1 -1
- package/dist/commands/video.d.ts +8 -1
- package/dist/commands/video.d.ts.map +1 -1
- package/dist/commands/video.js +50 -30
- package/dist/commands/video.js.map +1 -1
- package/dist/contained-file.d.ts +8 -0
- package/dist/contained-file.d.ts.map +1 -0
- package/dist/contained-file.js +77 -0
- package/dist/contained-file.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/agentic-tools.d.ts +16 -0
- package/dist/mcp/agentic-tools.d.ts.map +1 -0
- package/dist/mcp/agentic-tools.js +967 -0
- package/dist/mcp/agentic-tools.js.map +1 -0
- package/dist/mcp/artifact-store.d.ts +98 -0
- package/dist/mcp/artifact-store.d.ts.map +1 -0
- package/dist/mcp/artifact-store.js +542 -0
- package/dist/mcp/artifact-store.js.map +1 -0
- package/dist/mcp/authority.d.ts +53 -0
- package/dist/mcp/authority.d.ts.map +1 -0
- package/dist/mcp/authority.js +433 -0
- package/dist/mcp/authority.js.map +1 -0
- package/dist/mcp/conversion-service.d.ts +111 -0
- package/dist/mcp/conversion-service.d.ts.map +1 -0
- package/dist/mcp/conversion-service.js +512 -0
- package/dist/mcp/conversion-service.js.map +1 -0
- package/dist/mcp/discovery-tools.d.ts +4 -0
- package/dist/mcp/discovery-tools.d.ts.map +1 -0
- package/dist/mcp/discovery-tools.js +114 -0
- package/dist/mcp/discovery-tools.js.map +1 -0
- package/dist/mcp/document-service.d.ts +47 -0
- package/dist/mcp/document-service.d.ts.map +1 -0
- package/dist/mcp/document-service.js +424 -0
- package/dist/mcp/document-service.js.map +1 -0
- package/dist/mcp/error-result.d.ts +17 -0
- package/dist/mcp/error-result.d.ts.map +1 -0
- package/dist/mcp/error-result.js +82 -0
- package/dist/mcp/error-result.js.map +1 -0
- package/dist/mcp/intelligence.d.ts +15 -0
- package/dist/mcp/intelligence.d.ts.map +1 -0
- package/dist/mcp/intelligence.js +855 -0
- package/dist/mcp/intelligence.js.map +1 -0
- package/dist/mcp/output-bounds.d.ts +13 -0
- package/dist/mcp/output-bounds.d.ts.map +1 -0
- package/dist/mcp/output-bounds.js +61 -0
- package/dist/mcp/output-bounds.js.map +1 -0
- package/dist/mcp/preview-service.d.ts +54 -0
- package/dist/mcp/preview-service.d.ts.map +1 -0
- package/dist/mcp/preview-service.js +454 -0
- package/dist/mcp/preview-service.js.map +1 -0
- package/dist/mcp/progress.d.ts +18 -0
- package/dist/mcp/progress.d.ts.map +1 -0
- package/dist/mcp/progress.js +28 -0
- package/dist/mcp/progress.js.map +1 -0
- package/dist/mcp/prompts.d.ts +4 -0
- package/dist/mcp/prompts.d.ts.map +1 -0
- package/dist/mcp/prompts.js +124 -0
- package/dist/mcp/prompts.js.map +1 -0
- package/dist/mcp/rendered-conversion.d.ts +34 -0
- package/dist/mcp/rendered-conversion.d.ts.map +1 -0
- package/dist/mcp/rendered-conversion.js +364 -0
- package/dist/mcp/rendered-conversion.js.map +1 -0
- package/dist/mcp/server.d.ts +67 -10
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +227 -496
- package/dist/mcp/server.js.map +1 -1
- package/dist/preview-policy.d.ts +8 -0
- package/dist/preview-policy.d.ts.map +1 -0
- package/dist/preview-policy.js +85 -0
- package/dist/preview-policy.js.map +1 -0
- package/dist/render-html.d.ts +8 -0
- package/dist/render-html.d.ts.map +1 -1
- package/dist/render-html.js +32 -7
- package/dist/render-html.js.map +1 -1
- package/dist/version.d.ts +4 -0
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +95 -6
- package/dist/version.js.map +1 -1
- package/package.json +11 -11
- package/dist/converters/docx-to-md.d.ts +0 -10
- package/dist/converters/docx-to-md.d.ts.map +0 -1
- package/dist/converters/docx-to-md.js +0 -17
- package/dist/converters/docx-to-md.js.map +0 -1
- package/dist/converters/pdf-to-md.d.ts +0 -14
- package/dist/converters/pdf-to-md.d.ts.map +0 -1
- package/dist/converters/pdf-to-md.js +0 -51
- package/dist/converters/pdf-to-md.js.map +0 -1
- package/dist/converters/pptx-to-md.d.ts +0 -13
- package/dist/converters/pptx-to-md.d.ts.map +0 -1
- package/dist/converters/pptx-to-md.js +0 -67
- package/dist/converters/pptx-to-md.js.map +0 -1
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdtemp, open, rm } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { MCP_WIRE_LIMITS, parseConversionResult, } from '@bendyline/docblocks/mcp';
|
|
6
|
+
const DEFAULT_MAX_ARTIFACT_BYTES = 500 * 1024 * 1024;
|
|
7
|
+
const DEFAULT_MAX_TOTAL_BYTES = 1024 * 1024 * 1024;
|
|
8
|
+
const DEFAULT_MAX_ARTIFACTS = 64;
|
|
9
|
+
const DEFAULT_ARTIFACT_TTL_MS = 30 * 60 * 1000;
|
|
10
|
+
const DEFAULT_MAX_RESOURCE_BYTES = 25 * 1024 * 1024;
|
|
11
|
+
const DEFAULT_MAX_REPORT_BYTES = 8 * 1024 * 1024;
|
|
12
|
+
const DEFAULT_MAX_REPORT_TOTAL_BYTES = 64 * 1024 * 1024;
|
|
13
|
+
const ARTIFACT_IO_CHUNK_BYTES = 1024 * 1024;
|
|
14
|
+
const ARTIFACT_IO_DISPOSE_DRAIN_MS = 250;
|
|
15
|
+
export const MCP_ARTIFACT_STORE_LIMITS = Object.freeze({
|
|
16
|
+
maxArtifactBytes: MCP_WIRE_LIMITS.artifactBytes,
|
|
17
|
+
maxArtifactTotalBytes: 4 * 1024 * 1024 * 1024,
|
|
18
|
+
maxArtifactCount: 1024,
|
|
19
|
+
artifactTtlMs: 24 * 60 * 60 * 1000,
|
|
20
|
+
maxArtifactResourceBytes: 100 * 1024 * 1024,
|
|
21
|
+
maxArtifactReportBytes: 32 * 1024 * 1024,
|
|
22
|
+
maxArtifactReportTotalBytes: 256 * 1024 * 1024,
|
|
23
|
+
});
|
|
24
|
+
const DEFAULT_ARTIFACT_STORE_DEPENDENCIES = Object.freeze({
|
|
25
|
+
readFile: readFileCancellable,
|
|
26
|
+
writeFile: writeFileCancellable,
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Per-server immutable artifact storage. Artifacts are deliberately scoped to
|
|
30
|
+
* one MCP server instance: an opaque URI from another session conveys no
|
|
31
|
+
* authority and cannot be resolved here.
|
|
32
|
+
*/
|
|
33
|
+
export class ArtifactStore {
|
|
34
|
+
constructor(options = {}, dependencies = {}) {
|
|
35
|
+
this.records = new Map();
|
|
36
|
+
this.totalBytes = 0;
|
|
37
|
+
this.totalReportBytes = 0;
|
|
38
|
+
this.reservedBytes = 0;
|
|
39
|
+
this.reservedCount = 0;
|
|
40
|
+
this.disposed = false;
|
|
41
|
+
this.disposePromise = null;
|
|
42
|
+
this.activeIo = new Set();
|
|
43
|
+
this.tail = Promise.resolve();
|
|
44
|
+
this.dependencies = { ...DEFAULT_ARTIFACT_STORE_DEPENDENCIES, ...dependencies };
|
|
45
|
+
this.maximumArtifactBytes = positiveInteger(options.maxArtifactBytes ?? DEFAULT_MAX_ARTIFACT_BYTES, 'artifact byte limit', MCP_ARTIFACT_STORE_LIMITS.maxArtifactBytes);
|
|
46
|
+
this.maximumTotalBytes = positiveInteger(options.maxArtifactTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES, 'artifact total-byte limit', MCP_ARTIFACT_STORE_LIMITS.maxArtifactTotalBytes);
|
|
47
|
+
this.maximumCount = positiveInteger(options.maxArtifactCount ?? DEFAULT_MAX_ARTIFACTS, 'artifact count limit', MCP_ARTIFACT_STORE_LIMITS.maxArtifactCount);
|
|
48
|
+
this.ttlMs = positiveInteger(options.artifactTtlMs ?? DEFAULT_ARTIFACT_TTL_MS, 'artifact TTL', MCP_ARTIFACT_STORE_LIMITS.artifactTtlMs);
|
|
49
|
+
this.maximumResourceBytes = positiveInteger(options.maxArtifactResourceBytes ?? DEFAULT_MAX_RESOURCE_BYTES, 'artifact resource byte limit', MCP_ARTIFACT_STORE_LIMITS.maxArtifactResourceBytes);
|
|
50
|
+
this.maximumReportBytes = positiveInteger(options.maxArtifactReportBytes ?? DEFAULT_MAX_REPORT_BYTES, 'artifact report byte limit', MCP_ARTIFACT_STORE_LIMITS.maxArtifactReportBytes);
|
|
51
|
+
this.maximumReportTotalBytes = positiveInteger(options.maxArtifactReportTotalBytes ?? DEFAULT_MAX_REPORT_TOTAL_BYTES, 'artifact report total-byte limit', MCP_ARTIFACT_STORE_LIMITS.maxArtifactReportTotalBytes);
|
|
52
|
+
if (this.maximumTotalBytes < this.maximumArtifactBytes) {
|
|
53
|
+
throw new Error('Artifact total-byte limit must be at least the per-artifact limit');
|
|
54
|
+
}
|
|
55
|
+
if (this.maximumReportTotalBytes < this.maximumReportBytes) {
|
|
56
|
+
throw new Error('Artifact report total-byte limit must be at least the per-report limit');
|
|
57
|
+
}
|
|
58
|
+
this.directory = mkdtemp(join(tmpdir(), 'docblocks-mcp-artifacts-'));
|
|
59
|
+
// Construction is synchronous for server setup, while the backing
|
|
60
|
+
// directory is not. Observe failure immediately and expose it through
|
|
61
|
+
// ready() so transport admission can fail deterministically.
|
|
62
|
+
void this.directory.catch(() => undefined);
|
|
63
|
+
}
|
|
64
|
+
/** Resolve only after the session-scoped backing directory exists. */
|
|
65
|
+
async ready() {
|
|
66
|
+
await this.directory;
|
|
67
|
+
}
|
|
68
|
+
async put(options, signal) {
|
|
69
|
+
throwIfAborted(signal);
|
|
70
|
+
const bytes = Buffer.from(options.bytes);
|
|
71
|
+
if (bytes.byteLength > this.maximumArtifactBytes) {
|
|
72
|
+
throw new Error('MCP artifact exceeds the configured per-artifact limit');
|
|
73
|
+
}
|
|
74
|
+
const sha256 = await hashBytesCancellable(bytes, signal);
|
|
75
|
+
const id = randomUUID();
|
|
76
|
+
const path = join(await this.directory, `${id}.artifact`);
|
|
77
|
+
throwIfAborted(signal);
|
|
78
|
+
const created = new Date();
|
|
79
|
+
const ref = immutableArtifactRef({
|
|
80
|
+
id,
|
|
81
|
+
uri: `docblocks://artifacts/${id}`,
|
|
82
|
+
format: options.format,
|
|
83
|
+
mimeType: options.mimeType,
|
|
84
|
+
size: bytes.byteLength,
|
|
85
|
+
sha256,
|
|
86
|
+
sourceFormat: options.sourceFormat ?? null,
|
|
87
|
+
sourceSha256: options.sourceSha256 ?? null,
|
|
88
|
+
suggestedFilename: options.suggestedFilename,
|
|
89
|
+
appliedOptions: options.appliedOptions ?? [],
|
|
90
|
+
engineVersions: options.engineVersions ?? [],
|
|
91
|
+
createdAt: created.toISOString(),
|
|
92
|
+
expiresAt: new Date(created.getTime() + this.ttlMs).toISOString(),
|
|
93
|
+
});
|
|
94
|
+
const reservation = { bytes: bytes.byteLength, active: true };
|
|
95
|
+
const acquisition = await this.lock(() => {
|
|
96
|
+
this.assertActive();
|
|
97
|
+
throwIfAborted(signal);
|
|
98
|
+
const expiredPaths = this.takeExpiredLocked();
|
|
99
|
+
if (this.records.size + this.reservedCount >= this.maximumCount) {
|
|
100
|
+
throw new Error('MCP artifact store reached its configured count limit');
|
|
101
|
+
}
|
|
102
|
+
if (this.totalBytes + this.reservedBytes + bytes.byteLength > this.maximumTotalBytes) {
|
|
103
|
+
throw new Error('MCP artifact store reached its configured total-byte limit');
|
|
104
|
+
}
|
|
105
|
+
this.reservedCount += 1;
|
|
106
|
+
this.reservedBytes += bytes.byteLength;
|
|
107
|
+
return { expiredPaths, io: this.createIoLeaseLocked(signal) };
|
|
108
|
+
});
|
|
109
|
+
await removeFilesBestEffort(acquisition.expiredPaths);
|
|
110
|
+
try {
|
|
111
|
+
await this.dependencies.writeFile(path, bytes, acquisition.io.controller.signal);
|
|
112
|
+
throwIfAborted(acquisition.io.controller.signal);
|
|
113
|
+
await this.lock(() => {
|
|
114
|
+
this.assertActive();
|
|
115
|
+
throwIfAborted(acquisition.io.controller.signal);
|
|
116
|
+
this.releaseReservationLocked(reservation);
|
|
117
|
+
this.records.set(id, {
|
|
118
|
+
ref,
|
|
119
|
+
path,
|
|
120
|
+
conversionReport: null,
|
|
121
|
+
reportBytes: 0,
|
|
122
|
+
activeReaders: 0,
|
|
123
|
+
pendingDelete: false,
|
|
124
|
+
});
|
|
125
|
+
this.totalBytes += bytes.byteLength;
|
|
126
|
+
});
|
|
127
|
+
// Publication is the commit boundary. Cancellation after this point must
|
|
128
|
+
// not report a failure for an artifact that is already discoverable.
|
|
129
|
+
return ref;
|
|
130
|
+
}
|
|
131
|
+
catch (caught) {
|
|
132
|
+
await this.lock(() => this.releaseReservationLocked(reservation));
|
|
133
|
+
await rm(path, { force: true }).catch(() => undefined);
|
|
134
|
+
throw caught;
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
this.completeIoLease(acquisition.io);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async get(uriOrId, signal) {
|
|
141
|
+
throwIfAborted(signal);
|
|
142
|
+
return (await this.record(uriOrId)).ref;
|
|
143
|
+
}
|
|
144
|
+
/** Persist the exact bounded conversion report beside its immutable artifact. */
|
|
145
|
+
async attachConversionReport(report) {
|
|
146
|
+
const parsed = parseConversionResult(report);
|
|
147
|
+
if (!parsed)
|
|
148
|
+
throw new Error('Invalid MCP conversion report');
|
|
149
|
+
const serialized = JSON.stringify(parsed);
|
|
150
|
+
const reportBytes = Buffer.byteLength(serialized, 'utf8');
|
|
151
|
+
if (reportBytes > this.maximumReportBytes) {
|
|
152
|
+
throw new Error('MCP conversion report exceeds the configured byte limit');
|
|
153
|
+
}
|
|
154
|
+
await this.lock(() => {
|
|
155
|
+
this.assertActive();
|
|
156
|
+
const stored = this.records.get(artifactId(parsed.artifact.uri));
|
|
157
|
+
if (!stored || !sameArtifact(stored.ref, parsed.artifact)) {
|
|
158
|
+
throw new Error('Conversion report does not match an active MCP artifact');
|
|
159
|
+
}
|
|
160
|
+
const nextTotal = this.totalReportBytes - stored.reportBytes + reportBytes;
|
|
161
|
+
if (nextTotal > this.maximumReportTotalBytes) {
|
|
162
|
+
throw new Error('MCP conversion reports exceed the configured aggregate byte limit');
|
|
163
|
+
}
|
|
164
|
+
// `put()` and this attachment are one publication lifecycle in the
|
|
165
|
+
// conversion service. Do not let an intentionally tiny test TTL split
|
|
166
|
+
// those two steps; ordinary reads still enforce expiration immediately.
|
|
167
|
+
stored.conversionReport = serialized;
|
|
168
|
+
this.totalReportBytes = nextTotal;
|
|
169
|
+
stored.reportBytes = reportBytes;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/** Retrieve a fresh validated copy of an artifact's original conversion report. */
|
|
173
|
+
async getConversionReport(uriOrId) {
|
|
174
|
+
const stored = await this.record(uriOrId);
|
|
175
|
+
if (!stored.conversionReport)
|
|
176
|
+
throw new Error('MCP artifact has no conversion report');
|
|
177
|
+
const parsed = parseConversionResult(JSON.parse(stored.conversionReport));
|
|
178
|
+
if (!parsed)
|
|
179
|
+
throw new Error('Stored MCP conversion report is corrupt');
|
|
180
|
+
return parsed;
|
|
181
|
+
}
|
|
182
|
+
/** Remove an unpublished artifact after a later atomic lifecycle step fails. */
|
|
183
|
+
async discard(uriOrId) {
|
|
184
|
+
const removed = await this.lock(() => {
|
|
185
|
+
this.assertActive();
|
|
186
|
+
const expiredPaths = this.takeExpiredLocked();
|
|
187
|
+
const id = artifactId(uriOrId);
|
|
188
|
+
const stored = this.records.get(id);
|
|
189
|
+
return {
|
|
190
|
+
expiredPaths,
|
|
191
|
+
path: stored ? this.removeRecordLocked(id, stored) : null,
|
|
192
|
+
};
|
|
193
|
+
});
|
|
194
|
+
await removeFilesBestEffort(removed.expiredPaths);
|
|
195
|
+
if (removed.path)
|
|
196
|
+
await rm(removed.path, { force: true });
|
|
197
|
+
}
|
|
198
|
+
async read(uriOrId, signal) {
|
|
199
|
+
return this.readBytes(uriOrId, this.maximumArtifactBytes, signal);
|
|
200
|
+
}
|
|
201
|
+
/** Resource reads are opt-in but still bounded to avoid accidental huge base64 responses. */
|
|
202
|
+
async readResource(uriOrId, signal) {
|
|
203
|
+
const result = await this.readBytesWithRef(uriOrId, this.maximumResourceBytes, signal, true);
|
|
204
|
+
return { ref: result.ref, bytes: result.bytes };
|
|
205
|
+
}
|
|
206
|
+
async completeIds(prefix) {
|
|
207
|
+
const result = await this.lock(() => {
|
|
208
|
+
this.assertActive();
|
|
209
|
+
return {
|
|
210
|
+
expiredPaths: this.takeExpiredLocked(),
|
|
211
|
+
ids: [...this.records.keys()]
|
|
212
|
+
.filter((id) => id.startsWith(prefix))
|
|
213
|
+
.sort()
|
|
214
|
+
.slice(0, 100),
|
|
215
|
+
};
|
|
216
|
+
});
|
|
217
|
+
await removeFilesBestEffort(result.expiredPaths);
|
|
218
|
+
return result.ids;
|
|
219
|
+
}
|
|
220
|
+
/** Complete only artifacts that have an attached conversion report. */
|
|
221
|
+
async completeReportIds(prefix) {
|
|
222
|
+
const result = await this.lock(() => {
|
|
223
|
+
this.assertActive();
|
|
224
|
+
return {
|
|
225
|
+
expiredPaths: this.takeExpiredLocked(),
|
|
226
|
+
ids: [...this.records.entries()]
|
|
227
|
+
.filter(([id, stored]) => id.startsWith(prefix) && stored.conversionReport !== null)
|
|
228
|
+
.map(([id]) => id)
|
|
229
|
+
.sort()
|
|
230
|
+
.slice(0, 100),
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
await removeFilesBestEffort(result.expiredPaths);
|
|
234
|
+
return result.ids;
|
|
235
|
+
}
|
|
236
|
+
dispose() {
|
|
237
|
+
this.disposePromise ?? (this.disposePromise = this.disposeOnce());
|
|
238
|
+
return this.disposePromise;
|
|
239
|
+
}
|
|
240
|
+
async record(uriOrId) {
|
|
241
|
+
const result = await this.lock(() => {
|
|
242
|
+
this.assertActive();
|
|
243
|
+
const expiredPaths = this.takeExpiredLocked();
|
|
244
|
+
return { expiredPaths, stored: this.findRecordLocked(uriOrId) };
|
|
245
|
+
});
|
|
246
|
+
await removeFilesBestEffort(result.expiredPaths);
|
|
247
|
+
return result.stored;
|
|
248
|
+
}
|
|
249
|
+
findRecordLocked(uriOrId) {
|
|
250
|
+
const id = artifactId(uriOrId);
|
|
251
|
+
const stored = this.records.get(id);
|
|
252
|
+
if (!stored)
|
|
253
|
+
throw new Error('Unknown or expired MCP artifact');
|
|
254
|
+
return stored;
|
|
255
|
+
}
|
|
256
|
+
takeExpiredLocked() {
|
|
257
|
+
const now = Date.now();
|
|
258
|
+
const paths = [];
|
|
259
|
+
for (const [id, stored] of this.records) {
|
|
260
|
+
const expiresAt = stored.ref.expiresAt
|
|
261
|
+
? Date.parse(stored.ref.expiresAt)
|
|
262
|
+
: Number.POSITIVE_INFINITY;
|
|
263
|
+
if (expiresAt > now)
|
|
264
|
+
continue;
|
|
265
|
+
const path = this.removeRecordLocked(id, stored);
|
|
266
|
+
if (path)
|
|
267
|
+
paths.push(path);
|
|
268
|
+
}
|
|
269
|
+
return paths;
|
|
270
|
+
}
|
|
271
|
+
async readBytes(uriOrId, maximumBytes, signal) {
|
|
272
|
+
return (await this.readBytesWithRef(uriOrId, maximumBytes, signal, false)).bytes;
|
|
273
|
+
}
|
|
274
|
+
async readBytesWithRef(uriOrId, maximumBytes, signal, resourceRead) {
|
|
275
|
+
throwIfAborted(signal);
|
|
276
|
+
const acquisition = await this.lock(() => {
|
|
277
|
+
this.assertActive();
|
|
278
|
+
throwIfAborted(signal);
|
|
279
|
+
const expiredPaths = this.takeExpiredLocked();
|
|
280
|
+
const stored = this.findRecordLocked(uriOrId);
|
|
281
|
+
if (stored.ref.size > maximumBytes) {
|
|
282
|
+
if (resourceRead) {
|
|
283
|
+
throw new Error('Artifact is too large for an MCP resource response; use save_artifact');
|
|
284
|
+
}
|
|
285
|
+
throw new Error('MCP artifact exceeds the configured read byte limit');
|
|
286
|
+
}
|
|
287
|
+
const io = this.createIoLeaseLocked(signal);
|
|
288
|
+
stored.activeReaders += 1;
|
|
289
|
+
return { expiredPaths, stored, io };
|
|
290
|
+
});
|
|
291
|
+
await removeFilesBestEffort(acquisition.expiredPaths);
|
|
292
|
+
try {
|
|
293
|
+
const bytes = await this.dependencies.readFile(acquisition.stored.path, {
|
|
294
|
+
signal: acquisition.io.controller.signal,
|
|
295
|
+
maximumBytes,
|
|
296
|
+
expectedBytes: acquisition.stored.ref.size,
|
|
297
|
+
});
|
|
298
|
+
throwIfAborted(acquisition.io.controller.signal);
|
|
299
|
+
if (bytes.byteLength !== acquisition.stored.ref.size) {
|
|
300
|
+
throw new Error('Stored MCP artifact byte length does not match its immutable metadata');
|
|
301
|
+
}
|
|
302
|
+
return { ref: acquisition.stored.ref, bytes };
|
|
303
|
+
}
|
|
304
|
+
finally {
|
|
305
|
+
let deletePath = null;
|
|
306
|
+
await this.lock(() => {
|
|
307
|
+
acquisition.stored.activeReaders -= 1;
|
|
308
|
+
if (acquisition.stored.activeReaders === 0 && acquisition.stored.pendingDelete) {
|
|
309
|
+
deletePath = acquisition.stored.path;
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
this.completeIoLease(acquisition.io);
|
|
313
|
+
if (deletePath)
|
|
314
|
+
await rm(deletePath, { force: true }).catch(() => undefined);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
removeRecordLocked(id, stored) {
|
|
318
|
+
this.records.delete(id);
|
|
319
|
+
this.totalBytes -= stored.ref.size;
|
|
320
|
+
this.totalReportBytes -= stored.reportBytes;
|
|
321
|
+
if (stored.activeReaders > 0) {
|
|
322
|
+
stored.pendingDelete = true;
|
|
323
|
+
return null;
|
|
324
|
+
}
|
|
325
|
+
return stored.path;
|
|
326
|
+
}
|
|
327
|
+
releaseReservationLocked(reservation) {
|
|
328
|
+
if (!reservation.active)
|
|
329
|
+
return;
|
|
330
|
+
reservation.active = false;
|
|
331
|
+
this.reservedCount -= 1;
|
|
332
|
+
this.reservedBytes -= reservation.bytes;
|
|
333
|
+
}
|
|
334
|
+
createIoLeaseLocked(externalSignal) {
|
|
335
|
+
throwIfAborted(externalSignal);
|
|
336
|
+
const controller = new AbortController();
|
|
337
|
+
const forwardCancellation = () => controller.abort(externalSignal?.reason ?? cancellationError());
|
|
338
|
+
if (externalSignal)
|
|
339
|
+
externalSignal.addEventListener('abort', forwardCancellation, { once: true });
|
|
340
|
+
let resolveDone = () => undefined;
|
|
341
|
+
let completed = false;
|
|
342
|
+
const done = new Promise((resolve) => {
|
|
343
|
+
resolveDone = resolve;
|
|
344
|
+
});
|
|
345
|
+
const lease = {
|
|
346
|
+
controller,
|
|
347
|
+
done,
|
|
348
|
+
complete: () => {
|
|
349
|
+
if (completed)
|
|
350
|
+
return;
|
|
351
|
+
completed = true;
|
|
352
|
+
resolveDone();
|
|
353
|
+
},
|
|
354
|
+
detachExternalSignal: () => externalSignal?.removeEventListener('abort', forwardCancellation),
|
|
355
|
+
};
|
|
356
|
+
this.activeIo.add(lease);
|
|
357
|
+
return lease;
|
|
358
|
+
}
|
|
359
|
+
completeIoLease(lease) {
|
|
360
|
+
lease.detachExternalSignal();
|
|
361
|
+
this.activeIo.delete(lease);
|
|
362
|
+
lease.complete();
|
|
363
|
+
}
|
|
364
|
+
async disposeOnce() {
|
|
365
|
+
const leases = await this.lock(() => {
|
|
366
|
+
if (this.disposed)
|
|
367
|
+
return [];
|
|
368
|
+
this.disposed = true;
|
|
369
|
+
for (const stored of this.records.values())
|
|
370
|
+
stored.pendingDelete = true;
|
|
371
|
+
this.records.clear();
|
|
372
|
+
this.totalBytes = 0;
|
|
373
|
+
this.totalReportBytes = 0;
|
|
374
|
+
const current = [...this.activeIo];
|
|
375
|
+
const reason = new Error('MCP artifact store is disposed');
|
|
376
|
+
reason.name = 'ArtifactStoreDisposedError';
|
|
377
|
+
for (const lease of current) {
|
|
378
|
+
if (!lease.controller.signal.aborted)
|
|
379
|
+
lease.controller.abort(reason);
|
|
380
|
+
}
|
|
381
|
+
return current;
|
|
382
|
+
});
|
|
383
|
+
await waitForIoDrain(leases, ARTIFACT_IO_DISPOSE_DRAIN_MS);
|
|
384
|
+
for (const lease of leases) {
|
|
385
|
+
lease.detachExternalSignal();
|
|
386
|
+
this.activeIo.delete(lease);
|
|
387
|
+
}
|
|
388
|
+
await rm(await this.directory, { recursive: true, force: true, maxRetries: 3, retryDelay: 20 });
|
|
389
|
+
}
|
|
390
|
+
assertActive() {
|
|
391
|
+
if (this.disposed)
|
|
392
|
+
throw new Error('MCP artifact store is disposed');
|
|
393
|
+
}
|
|
394
|
+
async lock(work) {
|
|
395
|
+
let release;
|
|
396
|
+
const previous = this.tail;
|
|
397
|
+
this.tail = new Promise((resolve) => {
|
|
398
|
+
release = resolve;
|
|
399
|
+
});
|
|
400
|
+
await previous;
|
|
401
|
+
try {
|
|
402
|
+
return await work();
|
|
403
|
+
}
|
|
404
|
+
finally {
|
|
405
|
+
release?.();
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function artifactId(uriOrId) {
|
|
410
|
+
const artifactIdPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/u;
|
|
411
|
+
if (artifactIdPattern.test(uriOrId)) {
|
|
412
|
+
return uriOrId;
|
|
413
|
+
}
|
|
414
|
+
let parsed;
|
|
415
|
+
try {
|
|
416
|
+
parsed = new URL(uriOrId);
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
throw new Error('Invalid MCP artifact URI');
|
|
420
|
+
}
|
|
421
|
+
const id = parsed.pathname.slice(1);
|
|
422
|
+
if (parsed.protocol !== 'docblocks:' ||
|
|
423
|
+
parsed.hostname !== 'artifacts' ||
|
|
424
|
+
parsed.username !== '' ||
|
|
425
|
+
parsed.password !== '' ||
|
|
426
|
+
parsed.port !== '' ||
|
|
427
|
+
parsed.search !== '' ||
|
|
428
|
+
parsed.hash !== '' ||
|
|
429
|
+
parsed.pathname !== `/${id}` ||
|
|
430
|
+
!artifactIdPattern.test(id) ||
|
|
431
|
+
uriOrId !== `docblocks://artifacts/${id}`) {
|
|
432
|
+
throw new Error('Invalid MCP artifact URI');
|
|
433
|
+
}
|
|
434
|
+
return id;
|
|
435
|
+
}
|
|
436
|
+
function positiveInteger(value, label, maximum) {
|
|
437
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > maximum) {
|
|
438
|
+
throw new Error(`Invalid MCP ${label}; maximum is ${maximum}`);
|
|
439
|
+
}
|
|
440
|
+
return value;
|
|
441
|
+
}
|
|
442
|
+
function sameArtifact(left, right) {
|
|
443
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
444
|
+
}
|
|
445
|
+
/** Clone and freeze every caller-controlled layer before metadata enters quota accounting. */
|
|
446
|
+
function immutableArtifactRef(ref) {
|
|
447
|
+
const appliedOptions = Object.freeze(ref.appliedOptions.map((option) => Object.freeze({ ...option })));
|
|
448
|
+
const engineVersions = Object.freeze(ref.engineVersions.map((engine) => Object.freeze({ ...engine })));
|
|
449
|
+
return Object.freeze({ ...ref, appliedOptions, engineVersions });
|
|
450
|
+
}
|
|
451
|
+
async function writeFileCancellable(path, bytes, signal) {
|
|
452
|
+
throwIfAborted(signal);
|
|
453
|
+
const handle = await open(path, 'wx');
|
|
454
|
+
try {
|
|
455
|
+
let offset = 0;
|
|
456
|
+
while (offset < bytes.byteLength) {
|
|
457
|
+
throwIfAborted(signal);
|
|
458
|
+
const length = Math.min(ARTIFACT_IO_CHUNK_BYTES, bytes.byteLength - offset);
|
|
459
|
+
const { bytesWritten } = await handle.write(bytes, offset, length, offset);
|
|
460
|
+
if (bytesWritten < 1)
|
|
461
|
+
throw new Error('Artifact write made no progress');
|
|
462
|
+
offset += bytesWritten;
|
|
463
|
+
}
|
|
464
|
+
throwIfAborted(signal);
|
|
465
|
+
}
|
|
466
|
+
finally {
|
|
467
|
+
await handle.close();
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
async function readFileCancellable(path, options) {
|
|
471
|
+
throwIfAborted(options.signal);
|
|
472
|
+
const handle = await open(path, 'r');
|
|
473
|
+
try {
|
|
474
|
+
const stats = await handle.stat();
|
|
475
|
+
throwIfAborted(options.signal);
|
|
476
|
+
if (stats.size > options.maximumBytes) {
|
|
477
|
+
throw new Error('Stored MCP artifact exceeds the configured read byte limit');
|
|
478
|
+
}
|
|
479
|
+
if (stats.size !== options.expectedBytes) {
|
|
480
|
+
throw new Error('Stored MCP artifact byte length does not match its immutable metadata');
|
|
481
|
+
}
|
|
482
|
+
const bytes = Buffer.allocUnsafe(stats.size);
|
|
483
|
+
let offset = 0;
|
|
484
|
+
while (offset < bytes.byteLength) {
|
|
485
|
+
throwIfAborted(options.signal);
|
|
486
|
+
const length = Math.min(ARTIFACT_IO_CHUNK_BYTES, bytes.byteLength - offset);
|
|
487
|
+
const { bytesRead } = await handle.read(bytes, offset, length, offset);
|
|
488
|
+
if (bytesRead < 1) {
|
|
489
|
+
throw new Error('Stored MCP artifact ended before its immutable byte length');
|
|
490
|
+
}
|
|
491
|
+
offset += bytesRead;
|
|
492
|
+
}
|
|
493
|
+
throwIfAborted(options.signal);
|
|
494
|
+
return bytes;
|
|
495
|
+
}
|
|
496
|
+
finally {
|
|
497
|
+
await handle.close();
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
async function hashBytesCancellable(bytes, signal) {
|
|
501
|
+
const hash = createHash('sha256');
|
|
502
|
+
for (let offset = 0; offset < bytes.byteLength; offset += ARTIFACT_IO_CHUNK_BYTES) {
|
|
503
|
+
throwIfAborted(signal);
|
|
504
|
+
hash.update(bytes.subarray(offset, offset + ARTIFACT_IO_CHUNK_BYTES));
|
|
505
|
+
if (offset + ARTIFACT_IO_CHUNK_BYTES < bytes.byteLength) {
|
|
506
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
throwIfAborted(signal);
|
|
510
|
+
return hash.digest('hex');
|
|
511
|
+
}
|
|
512
|
+
async function removeFilesBestEffort(paths) {
|
|
513
|
+
await Promise.allSettled(paths.map((path) => rm(path, { force: true })));
|
|
514
|
+
}
|
|
515
|
+
async function waitForIoDrain(leases, timeoutMs) {
|
|
516
|
+
if (leases.length === 0)
|
|
517
|
+
return;
|
|
518
|
+
let timer;
|
|
519
|
+
try {
|
|
520
|
+
await Promise.race([
|
|
521
|
+
Promise.allSettled(leases.map((lease) => lease.done)).then(() => undefined),
|
|
522
|
+
new Promise((resolve) => {
|
|
523
|
+
timer = setTimeout(resolve, timeoutMs);
|
|
524
|
+
}),
|
|
525
|
+
]);
|
|
526
|
+
}
|
|
527
|
+
finally {
|
|
528
|
+
if (timer)
|
|
529
|
+
clearTimeout(timer);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
function throwIfAborted(signal) {
|
|
533
|
+
if (!signal?.aborted)
|
|
534
|
+
return;
|
|
535
|
+
throw signal.reason ?? cancellationError();
|
|
536
|
+
}
|
|
537
|
+
function cancellationError() {
|
|
538
|
+
const error = new Error('MCP artifact I/O was cancelled');
|
|
539
|
+
error.name = 'AbortError';
|
|
540
|
+
return error;
|
|
541
|
+
}
|
|
542
|
+
//# sourceMappingURL=artifact-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"artifact-store.js","sourceRoot":"","sources":["../../src/mcp/artifact-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface McpFileAuthorityOptions {
|
|
2
|
+
readRoots?: readonly string[];
|
|
3
|
+
writeRoots?: readonly string[];
|
|
4
|
+
maxInputFileBytes?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface McpFileAuthorityDependencies {
|
|
7
|
+
/** Test seam after each bounded input read chunk, before cancellation is rechecked. */
|
|
8
|
+
afterInputReadChunk?(readBytes: number, totalBytes: number): Promise<void> | void;
|
|
9
|
+
/** Test seam after durable staging but before the final precondition check. */
|
|
10
|
+
afterMaterializationStage?(temporaryPath: string): Promise<void> | void;
|
|
11
|
+
/** Test seam after each bounded write chunk, before cancellation is rechecked. */
|
|
12
|
+
afterMaterializationWriteChunk?(writtenBytes: number, totalBytes: number): Promise<void> | void;
|
|
13
|
+
/** Test seam after each bounded hash chunk, before cancellation is rechecked. */
|
|
14
|
+
afterMaterializationHashChunk?(readBytes: number, totalBytes: number): Promise<void> | void;
|
|
15
|
+
/** Synchronous test notification at the irreversible publication boundary. */
|
|
16
|
+
afterMaterializationPublish?(targetPath: string): void;
|
|
17
|
+
}
|
|
18
|
+
export declare const MCP_FILE_AUTHORITY_LIMITS: Readonly<{
|
|
19
|
+
maxInputFileBytes: number;
|
|
20
|
+
maxRootsPerCapability: 64;
|
|
21
|
+
}>;
|
|
22
|
+
export interface McpRootDescriptor {
|
|
23
|
+
id: string;
|
|
24
|
+
label: string;
|
|
25
|
+
read: boolean;
|
|
26
|
+
write: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface McpMaterializationOptions {
|
|
29
|
+
ifExists?: 'error' | 'replace';
|
|
30
|
+
expectedSha256?: string;
|
|
31
|
+
signal?: AbortSignal;
|
|
32
|
+
}
|
|
33
|
+
/** Host-startup authority. Tool arguments can narrow it but can never expand it. */
|
|
34
|
+
export declare class McpFileAuthority {
|
|
35
|
+
private readonly readRoots;
|
|
36
|
+
private readonly writeRoots;
|
|
37
|
+
private readonly maxInputFileBytes;
|
|
38
|
+
private readonly dependencies;
|
|
39
|
+
private constructor();
|
|
40
|
+
static create(options?: McpFileAuthorityOptions, dependencies?: McpFileAuthorityDependencies): Promise<McpFileAuthority>;
|
|
41
|
+
authorizeRead(requestedPath: string): Promise<string>;
|
|
42
|
+
/** Opaque, non-authoritative aliases for the roots granted at server startup. */
|
|
43
|
+
listRoots(): McpRootDescriptor[];
|
|
44
|
+
/** Resolve a root-relative read without ever treating the alias as new authority. */
|
|
45
|
+
authorizeRootRead(rootId: string, workspacePath: string): Promise<string>;
|
|
46
|
+
/** Resolve a root-relative write without ever treating the alias as new authority. */
|
|
47
|
+
authorizeRootWrite(rootId: string, workspacePath: string): Promise<string>;
|
|
48
|
+
readFile(requestedPath: string, signal?: AbortSignal): Promise<Buffer>;
|
|
49
|
+
authorizeWrite(requestedPath: string): Promise<string>;
|
|
50
|
+
/** Publish bounded bytes through an operation-owned sibling file. */
|
|
51
|
+
materializeBytes(requestedPath: string, content: Uint8Array, maximumBytes: number, options?: McpMaterializationOptions): Promise<string>;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=authority.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authority.d.ts","sourceRoot":"","sources":["../../src/mcp/authority.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,uBAAuB;IACtC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC9B,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,4BAA4B;IAC3C,uFAAuF;IACvF,mBAAmB,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAClF,+EAA+E;IAC/E,yBAAyB,CAAC,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACxE,kFAAkF;IAClF,8BAA8B,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChG,iFAAiF;IACjF,6BAA6B,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5F,8EAA8E;IAC9E,2BAA2B,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACxD;AAGD,eAAO,MAAM,yBAAyB;;;EAGpC,CAAC;AAkBH,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,oFAAoF;AACpF,qBAAa,gBAAgB;IAEzB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAJ/B,OAAO;WAOa,MAAM,CACxB,OAAO,GAAE,uBAA4B,EACrC,YAAY,GAAE,4BAAiC,GAC9C,OAAO,CAAC,gBAAgB,CAAC;IAuBf,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAclE,iFAAiF;IAC1E,SAAS,IAAI,iBAAiB,EAAE;IAsBvC,qFAAqF;IACxE,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWtF,sFAAsF;IACzE,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY1E,QAAQ,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAYtE,cAAc,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA4BnE,qEAAqE;IACxD,gBAAgB,CAC3B,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,UAAU,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,MAAM,CAAC;CAoGnB"}
|