@bedolla/enrivision 0.1.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.
@@ -0,0 +1,509 @@
1
+ /**
2
+ * ANALYZE MEDIA TOOL
3
+ *
4
+ * Implements the `analyze_media` MCP tool:
5
+ * - Validates local file path
6
+ * - Streams the file to EnriProxy via resumable uploads
7
+ * - Triggers server-side analysis and returns text-only results
8
+ *
9
+ * @module tools/AnalyzeMediaTool
10
+ */
11
+ import { existsSync } from "node:fs";
12
+ import { stat, open } from "node:fs/promises";
13
+ import { basename, extname, isAbsolute } from "node:path";
14
+ import { randomUUID } from "node:crypto";
15
+ import { lookup as mimeLookup } from "mime-types";
16
+ import { EnriProxyHttpError } from "../client/EnriProxyClient.js";
17
+ import { assertHttpUrl, assertNonEmptyString, assertObject, optionalBoolean, optionalInt, optionalNumber, optionalString } from "../shared/validation.js";
18
+ import { computeTarSizeBytes, TarStream } from "../shared/tar.js";
19
+ /**
20
+ * Content type for EnriVision media-set archives (tar, no compression).
21
+ */
22
+ const ENRIVISION_MEDIA_SET_TAR_CONTENT_TYPE = "application/vnd.enrivision.media-set+tar";
23
+ /**
24
+ * Fixed manifest entry name inside EnriVision media-set tar archives.
25
+ */
26
+ const ENRIVISION_MEDIA_SET_TAR_MANIFEST_NAME = "manifest.json";
27
+ /**
28
+ * MCP tool that uploads and analyzes local media.
29
+ */
30
+ export class AnalyzeMediaTool {
31
+ /**
32
+ * Tool dependencies.
33
+ */
34
+ deps;
35
+ /**
36
+ * Creates a new {@link AnalyzeMediaTool}.
37
+ *
38
+ * @param deps - Tool dependencies
39
+ */
40
+ constructor(deps) {
41
+ this.deps = deps;
42
+ }
43
+ /**
44
+ * Validates raw MCP tool arguments.
45
+ *
46
+ * @param raw - Raw tool arguments
47
+ * @returns Validated parameters
48
+ */
49
+ parseParams(raw) {
50
+ const obj = assertObject(raw, "arguments");
51
+ const pathRaw = typeof obj["path"] === "string" ? obj["path"].trim() : "";
52
+ const path = pathRaw ? pathRaw : undefined;
53
+ if (path && !isAbsolute(path)) {
54
+ throw new Error("path must be an absolute file path.");
55
+ }
56
+ const pathsRaw = obj["paths"];
57
+ let paths;
58
+ if (typeof pathsRaw !== "undefined") {
59
+ if (!Array.isArray(pathsRaw)) {
60
+ throw new Error("paths must be an array of absolute file paths.");
61
+ }
62
+ const out = [];
63
+ for (const item of pathsRaw) {
64
+ if (typeof item !== "string" || !item.trim()) {
65
+ continue;
66
+ }
67
+ const p = item.trim();
68
+ if (!isAbsolute(p)) {
69
+ throw new Error("paths must contain only absolute file paths.");
70
+ }
71
+ out.push(p);
72
+ }
73
+ if (out.length > 0) {
74
+ paths = out;
75
+ }
76
+ }
77
+ if (!path && (!paths || paths.length === 0)) {
78
+ throw new Error("Provide either 'path' or 'paths'.");
79
+ }
80
+ const context = optionalString(obj["context"]);
81
+ const question = optionalString(obj["question"]);
82
+ const language = optionalString(obj["language"]);
83
+ const maxFrames = optionalInt(obj["max_frames"]);
84
+ const transcribe = optionalBoolean(obj["transcribe"]);
85
+ const transcriptionLanguage = optionalString(obj["transcription_language"]);
86
+ const analysisModeRaw = optionalString(obj["analysis_mode"]);
87
+ const analysisMode = analysisModeRaw === "auto" || analysisModeRaw === "single" || analysisModeRaw === "multipass"
88
+ ? analysisModeRaw
89
+ : analysisModeRaw
90
+ ? (() => {
91
+ throw new Error("analysis_mode must be one of: auto|single|multipass.");
92
+ })()
93
+ : undefined;
94
+ const videoRaw = obj["video"];
95
+ let video;
96
+ if (typeof videoRaw !== "undefined") {
97
+ const v = assertObject(videoRaw, "video");
98
+ video = {
99
+ clipStartSeconds: optionalNumber(v["clip_start_seconds"]),
100
+ clipDurationSeconds: optionalNumber(v["clip_duration_seconds"]),
101
+ segmentSeconds: optionalNumber(v["segment_seconds"]),
102
+ maxSegments: optionalInt(v["max_segments"]),
103
+ maxFramesPerSegment: optionalInt(v["max_frames_per_segment"])
104
+ };
105
+ }
106
+ const documentRaw = obj["document"];
107
+ let document;
108
+ if (typeof documentRaw !== "undefined") {
109
+ const d = assertObject(documentRaw, "document");
110
+ document = {
111
+ maxPagesTotal: optionalInt(d["max_pages_total"]),
112
+ pagesPerBatch: optionalInt(d["pages_per_batch"]),
113
+ maxImagesPerBatch: optionalInt(d["max_images_per_batch"]),
114
+ scannedTextThresholdChars: optionalInt(d["scanned_text_threshold_chars"])
115
+ };
116
+ }
117
+ const audioRaw = obj["audio"];
118
+ let audio;
119
+ if (typeof audioRaw !== "undefined") {
120
+ const a = assertObject(audioRaw, "audio");
121
+ audio = {
122
+ timestamps: optionalBoolean(a["timestamps"]),
123
+ segmentSeconds: optionalNumber(a["segment_seconds"]),
124
+ maxSegments: optionalInt(a["max_segments"])
125
+ };
126
+ }
127
+ const imagesRaw = obj["images"];
128
+ let images;
129
+ if (typeof imagesRaw !== "undefined") {
130
+ const img = assertObject(imagesRaw, "images");
131
+ images = {
132
+ maxImagesTotal: optionalInt(img["max_images_total"]),
133
+ imagesPerBatch: optionalInt(img["images_per_batch"]),
134
+ maxDimension: optionalInt(img["max_dimension"])
135
+ };
136
+ }
137
+ return {
138
+ path,
139
+ paths,
140
+ context,
141
+ question,
142
+ language,
143
+ maxFrames,
144
+ transcribe,
145
+ transcriptionLanguage,
146
+ analysisMode,
147
+ video,
148
+ document,
149
+ audio,
150
+ images
151
+ };
152
+ }
153
+ /**
154
+ * Executes the tool.
155
+ *
156
+ * @param params - Validated parameters
157
+ * @returns Tool result
158
+ */
159
+ async execute(params) {
160
+ const serverUrl = assertHttpUrl(this.deps.defaultServerUrl, "ENRIPROXY_URL");
161
+ const apiKey = assertNonEmptyString(this.deps.defaultApiKey, "ENRIPROXY_API_KEY");
162
+ const timeoutMs = this.deps.defaultTimeoutMs;
163
+ const clientTraceId = `enrivision_${randomUUID()}`;
164
+ const client = this.deps.createClient(serverUrl, apiKey, timeoutMs);
165
+ const resolvedPaths = Array.isArray(params.paths) && params.paths.length > 0
166
+ ? [...params.paths]
167
+ : typeof params.path === "string" && params.path.trim()
168
+ ? [params.path.trim()]
169
+ : [];
170
+ if (resolvedPaths.length === 0) {
171
+ throw new Error("Provide either 'path' or 'paths'.");
172
+ }
173
+ let uploadId;
174
+ if (resolvedPaths.length > 1) {
175
+ uploadId = await this.uploadImageSetAsMediaSetTar(client, resolvedPaths, timeoutMs, clientTraceId);
176
+ }
177
+ else {
178
+ const singlePath = resolvedPaths[0];
179
+ const fileSize = await this.assertReadableFile(singlePath);
180
+ const filename = basename(singlePath);
181
+ const contentType = this.detectMimeType(singlePath);
182
+ const session = await client.createUploadSession({
183
+ filename,
184
+ sizeBytes: fileSize,
185
+ contentType,
186
+ clientTraceId
187
+ });
188
+ const finalOffset = await this.uploadFileResumable(client, singlePath, fileSize, session, timeoutMs);
189
+ if (finalOffset !== fileSize) {
190
+ throw new Error(`Upload incomplete: sent ${finalOffset} of ${fileSize} bytes.`);
191
+ }
192
+ uploadId = session.upload_id;
193
+ }
194
+ const defaultLanguageRaw = typeof process.env["ENRIVISION_DEFAULT_LANGUAGE"] === "string"
195
+ ? process.env["ENRIVISION_DEFAULT_LANGUAGE"].trim()
196
+ : "";
197
+ const language = typeof params.language === "string" && params.language.trim()
198
+ ? params.language.trim()
199
+ : defaultLanguageRaw
200
+ ? defaultLanguageRaw
201
+ : undefined;
202
+ const analysis = await client.analyze({
203
+ uploadId,
204
+ context: params.context,
205
+ question: params.question,
206
+ language,
207
+ maxFrames: params.maxFrames,
208
+ transcribe: params.transcribe,
209
+ transcriptionLanguage: params.transcriptionLanguage,
210
+ analysisMode: params.analysisMode,
211
+ video: params.video,
212
+ document: params.document,
213
+ audio: params.audio,
214
+ images: params.images
215
+ });
216
+ const extraction = this.stripInternalExtractionFields(analysis.extraction);
217
+ return {
218
+ analysis: analysis.analysis,
219
+ media_type: analysis.media_type,
220
+ extraction
221
+ };
222
+ }
223
+ /**
224
+ * Removes internal identifiers (upload ids, routing-only values, etc.) from the
225
+ * extraction payload before returning it to the model.
226
+ *
227
+ * @param extraction - Raw extraction object returned by EnriProxy
228
+ * @returns Sanitized extraction object
229
+ */
230
+ stripInternalExtractionFields(extraction) {
231
+ const stripped = this.stripInternalFields(extraction);
232
+ return this.asPlainObject(stripped);
233
+ }
234
+ /**
235
+ * Recursively strips internal fields from an unknown value.
236
+ *
237
+ * @param value - Unknown value to sanitize
238
+ * @returns Sanitized value
239
+ */
240
+ stripInternalFields(value) {
241
+ if (Array.isArray(value)) {
242
+ return value.map((item) => this.stripInternalFields(item));
243
+ }
244
+ if (!value || typeof value !== "object") {
245
+ return value;
246
+ }
247
+ const record = value;
248
+ const next = {};
249
+ for (const [key, child] of Object.entries(record)) {
250
+ if (key === "upload_id" || key === "uploadId") {
251
+ continue;
252
+ }
253
+ if (key === "detected_media_type") {
254
+ continue;
255
+ }
256
+ if (key === "analysis_mode_requested" || key === "analysis_mode_used") {
257
+ continue;
258
+ }
259
+ if (key === "multipass") {
260
+ continue;
261
+ }
262
+ if (key === "model") {
263
+ continue;
264
+ }
265
+ next[key] = this.stripInternalFields(child);
266
+ }
267
+ return next;
268
+ }
269
+ /**
270
+ * Ensures the sanitized extraction value is a plain JSON object.
271
+ *
272
+ * @param value - Sanitized value
273
+ * @returns Plain object
274
+ */
275
+ asPlainObject(value) {
276
+ if (value && typeof value === "object" && !Array.isArray(value)) {
277
+ return value;
278
+ }
279
+ return {};
280
+ }
281
+ /**
282
+ * Validates that a path exists and is a readable file.
283
+ *
284
+ * @param filePath - Local filesystem path
285
+ * @returns File size in bytes
286
+ */
287
+ async assertReadableFile(filePath) {
288
+ if (!existsSync(filePath)) {
289
+ throw new Error(`File not found: ${filePath}`);
290
+ }
291
+ const st = await stat(filePath);
292
+ if (!st.isFile()) {
293
+ throw new Error(`Not a file: ${filePath}`);
294
+ }
295
+ // Ensure the file is readable.
296
+ const handle = await open(filePath, "r");
297
+ try {
298
+ return st.size;
299
+ }
300
+ finally {
301
+ await handle.close();
302
+ }
303
+ }
304
+ /**
305
+ * Detects MIME type using file extension.
306
+ *
307
+ * @param filePath - File path
308
+ * @returns MIME type string
309
+ */
310
+ detectMimeType(filePath) {
311
+ const detected = mimeLookup(filePath);
312
+ if (typeof detected === "string" && detected.trim()) {
313
+ return detected.trim();
314
+ }
315
+ return "application/octet-stream";
316
+ }
317
+ /**
318
+ * Uploads multiple local images as a single EnriVision media-set tar archive.
319
+ *
320
+ * @remarks
321
+ * This avoids creating many concurrent resumable upload sessions (which are
322
+ * capped per API key) and enables server-side batching + reduce for large
323
+ * screenshot sets.
324
+ *
325
+ * @param client - EnriProxy client
326
+ * @param filePaths - Absolute image file paths
327
+ * @param timeoutMs - Request timeout per HTTP request
328
+ * @param clientTraceId - Client trace id for correlation
329
+ * @returns Upload id for the created tar session
330
+ */
331
+ async uploadImageSetAsMediaSetTar(client, filePaths, timeoutMs, clientTraceId) {
332
+ if (filePaths.length < 2) {
333
+ throw new Error("uploadImageSetAsMediaSetTar requires at least 2 file paths.");
334
+ }
335
+ const files = [];
336
+ for (let i = 0; i < filePaths.length; i += 1) {
337
+ const p = filePaths[i];
338
+ const sizeBytes = await this.assertReadableFile(p);
339
+ const filename = basename(p);
340
+ const contentType = this.detectMimeType(p);
341
+ if (!contentType.toLowerCase().startsWith("image/")) {
342
+ throw new Error(`paths must contain only image files. Not an image: ${p} (${contentType})`);
343
+ }
344
+ const extRaw = extname(filename).toLowerCase();
345
+ const ext = extRaw && /^[a-z0-9.]+$/.test(extRaw) ? extRaw : ".img";
346
+ const entryName = `${String(i + 1).padStart(6, "0")}${ext}`;
347
+ files.push({
348
+ index: i + 1,
349
+ path: p,
350
+ filename,
351
+ sizeBytes,
352
+ contentType,
353
+ entryName
354
+ });
355
+ }
356
+ const manifest = {
357
+ type: "enrivision_media_set",
358
+ version: 1,
359
+ media_type: "image_set",
360
+ items: files.map((f) => ({
361
+ index: f.index,
362
+ name: f.entryName,
363
+ filename: f.filename,
364
+ content_type: f.contentType,
365
+ size_bytes: f.sizeBytes
366
+ }))
367
+ };
368
+ const manifestBuffer = Buffer.from(JSON.stringify(manifest), "utf8");
369
+ const nowSeconds = Math.floor(Date.now() / 1000);
370
+ const entries = [
371
+ {
372
+ name: ENRIVISION_MEDIA_SET_TAR_MANIFEST_NAME,
373
+ source: { type: "buffer", buffer: manifestBuffer },
374
+ mtimeSeconds: nowSeconds
375
+ },
376
+ ...files.map((f) => ({
377
+ name: f.entryName,
378
+ source: { type: "file", path: f.path, sizeBytes: f.sizeBytes },
379
+ mtimeSeconds: nowSeconds
380
+ }))
381
+ ];
382
+ const tarSizeBytes = computeTarSizeBytes(entries);
383
+ const tar = new TarStream(entries);
384
+ if (tar.getSizeBytes() !== tarSizeBytes) {
385
+ throw new Error("Internal error: tar size mismatch.");
386
+ }
387
+ const session = await client.createUploadSession({
388
+ filename: "enrivision-image-set.tar",
389
+ sizeBytes: tarSizeBytes,
390
+ contentType: ENRIVISION_MEDIA_SET_TAR_CONTENT_TYPE,
391
+ clientTraceId
392
+ });
393
+ const chunkSize = Math.max(1, Math.floor(session.chunk_size_bytes));
394
+ let offset = await client.getUploadOffset(session.upload_id);
395
+ if (offset < 0 || offset > tarSizeBytes) {
396
+ throw new Error(`Invalid server offset for tar upload: ${offset}`);
397
+ }
398
+ while (offset < tarSizeBytes) {
399
+ let madeProgress = false;
400
+ for await (const chunk of tar.iterateChunks(offset, chunkSize)) {
401
+ if (chunk.length === 0) {
402
+ continue;
403
+ }
404
+ const expectedOffset = offset;
405
+ const nextOffset = await this.uploadChunkWithRetry(client, session.upload_id, expectedOffset, chunk, timeoutMs);
406
+ offset = nextOffset;
407
+ madeProgress = true;
408
+ const progress = Math.floor((offset / tarSizeBytes) * 100);
409
+ console.error(`enrivision: upload ${progress}% (${offset}/${tarSizeBytes} bytes)`);
410
+ // Offset resync: restart generation from the server-provided offset.
411
+ if (offset !== expectedOffset + chunk.length) {
412
+ break;
413
+ }
414
+ if (offset >= tarSizeBytes) {
415
+ break;
416
+ }
417
+ }
418
+ if (!madeProgress) {
419
+ throw new Error("Upload stalled: no progress while sending tar chunks.");
420
+ }
421
+ }
422
+ if (offset !== tarSizeBytes) {
423
+ throw new Error(`Upload incomplete: sent ${offset} of ${tarSizeBytes} bytes.`);
424
+ }
425
+ return session.upload_id;
426
+ }
427
+ /**
428
+ * Uploads a file to EnriProxy in resumable chunks.
429
+ *
430
+ * @param client - EnriProxy client
431
+ * @param filePath - Local file path
432
+ * @param fileSize - Total file size in bytes
433
+ * @param session - Server-created session
434
+ * @param timeoutMs - Request timeout in milliseconds
435
+ * @returns Final offset
436
+ */
437
+ async uploadFileResumable(client, filePath, fileSize, session, timeoutMs) {
438
+ const chunkSize = Math.max(1, Math.floor(session.chunk_size_bytes));
439
+ const handle = await open(filePath, "r");
440
+ try {
441
+ let offset = await client.getUploadOffset(session.upload_id);
442
+ while (offset < fileSize) {
443
+ const remaining = fileSize - offset;
444
+ const nextSize = Math.min(chunkSize, remaining);
445
+ const buffer = Buffer.allocUnsafe(nextSize);
446
+ const read = await handle.read(buffer, 0, nextSize, offset);
447
+ if (read.bytesRead <= 0) {
448
+ break;
449
+ }
450
+ const chunk = read.bytesRead === buffer.length ? buffer : buffer.subarray(0, read.bytesRead);
451
+ offset = await this.uploadChunkWithRetry(client, session.upload_id, offset, chunk, timeoutMs);
452
+ const progress = Math.floor((offset / fileSize) * 100);
453
+ console.error(`enrivision: upload ${progress}% (${offset}/${fileSize} bytes)`);
454
+ }
455
+ return offset;
456
+ }
457
+ finally {
458
+ await handle.close();
459
+ }
460
+ }
461
+ /**
462
+ * Uploads a single chunk with retry and offset resync.
463
+ *
464
+ * @param client - EnriProxy client
465
+ * @param uploadId - Upload id
466
+ * @param offset - Expected offset
467
+ * @param chunk - Chunk bytes
468
+ * @param timeoutMs - Timeout in ms
469
+ * @returns New offset
470
+ */
471
+ async uploadChunkWithRetry(client, uploadId, offset, chunk, timeoutMs) {
472
+ const maxAttempts = 5;
473
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
474
+ try {
475
+ return await client.appendUploadChunk({ uploadId, offset, chunk, timeoutMs });
476
+ }
477
+ catch (error) {
478
+ const message = error instanceof Error ? error.message : String(error);
479
+ if (error instanceof EnriProxyHttpError) {
480
+ // Offset mismatch: resync and let the caller re-read at the correct offset.
481
+ if (error.status === 409) {
482
+ const actual = await client.getUploadOffset(uploadId);
483
+ if (actual !== offset) {
484
+ console.error(`enrivision: offset resync (${offset} -> ${actual})`);
485
+ return actual;
486
+ }
487
+ }
488
+ // Do not retry on client errors (except 409 which is handled above).
489
+ if (error.status === 400 ||
490
+ error.status === 401 ||
491
+ error.status === 403 ||
492
+ error.status === 404 ||
493
+ error.status === 410 ||
494
+ error.status === 413) {
495
+ throw error;
496
+ }
497
+ }
498
+ if (attempt === maxAttempts) {
499
+ throw error;
500
+ }
501
+ const backoffMs = Math.min(1000 * Math.pow(2, attempt - 1), 10000);
502
+ console.error(`enrivision: retry ${attempt}/${maxAttempts} after ${backoffMs}ms (${message})`);
503
+ await new Promise((resolve) => setTimeout(resolve, backoffMs));
504
+ }
505
+ }
506
+ throw new Error("Upload failed after retries.");
507
+ }
508
+ }
509
+ //# sourceMappingURL=AnalyzeMediaTool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyzeMediaTool.js","sourceRoot":"","sources":["../../src/tools/AnalyzeMediaTool.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@bedolla/enrivision",
3
+ "version": "0.1.0",
4
+ "description": "MCP server that uploads local media to EnriProxy and returns server-side analysis (resumable uploads).",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "enrivision",
9
+ "enriproxy",
10
+ "vision",
11
+ "video",
12
+ "audio",
13
+ "image",
14
+ "document"
15
+ ],
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/Bedolla/EnriVision.git"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/Bedolla/EnriVision/issues"
22
+ },
23
+ "homepage": "https://github.com/Bedolla/EnriVision#readme",
24
+ "license": "AGPL-3.0-only",
25
+ "author": "Pipochas",
26
+ "type": "module",
27
+ "main": "dist/index.js",
28
+ "bin": {
29
+ "enrivision": "dist/index.js"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "scripts": {
40
+ "typecheck": "tsc -p tsconfig.json --noEmit",
41
+ "build": "tsc -p tsconfig.json",
42
+ "prepack": "npm run build",
43
+ "start": "node dist/index.js",
44
+ "test": "vitest run"
45
+ },
46
+ "dependencies": {
47
+ "@modelcontextprotocol/sdk": "1.25.1",
48
+ "mime-types": "3.0.2"
49
+ },
50
+ "devDependencies": {
51
+ "@types/node": "25.0.3",
52
+ "typescript": "5.9.3",
53
+ "vitest": "4.0.16"
54
+ },
55
+ "engines": {
56
+ "node": ">=22"
57
+ }
58
+ }