@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.
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # EnriVision
2
+
3
+ EnriVision is a **Model Context Protocol (MCP)** server over `stdio` that uploads local media to **EnriProxy** and returns **server-side extraction + model analysis**.
4
+
5
+ This is useful for media types that many MCP clients cannot read reliably (videos, audio, scanned PDFs, HEIC/AVIF, large files), while keeping the MCP server itself lightweight.
6
+
7
+ ## What this project is
8
+
9
+ - An MCP server process your MCP host launches (OpenCode, Claude Code, Codex, etc.)
10
+ - A thin client for EnriProxy (resumable upload + structured output)
11
+
12
+ ## Requirements
13
+
14
+ - Node.js `>= 22` (recommended: Node 24 LTS)
15
+ - A reachable EnriProxy server with these endpoints enabled:
16
+ - `POST /v1/uploads`
17
+ - `HEAD /v1/uploads/:id`
18
+ - `PATCH /v1/uploads/:id`
19
+ - `POST /v1/vision/analyze`
20
+ - An EnriProxy API key (configured on the EnriProxy side)
21
+
22
+ ## Install
23
+
24
+ ```powershell
25
+ # Global install
26
+ npm install -g @bedolla/enrivision
27
+
28
+ # Or run without installing
29
+ npx -y @bedolla/enrivision@latest --help
30
+ ```
31
+
32
+ ## Build
33
+
34
+ ```powershell
35
+ npm install
36
+ npm run typecheck
37
+ npm run build
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ### 1) Configure your MCP host
43
+
44
+ EnriVision runs as an MCP server over `stdio`. Your MCP host is responsible for launching the process.
45
+
46
+ Example: global install
47
+
48
+ ```jsonc
49
+ {
50
+ "EnriVision": {
51
+ "type": "stdio",
52
+ "command": "enrivision",
53
+ "args": [],
54
+ "env": {
55
+ "ENRIPROXY_URL": "http://127.0.0.1:8787",
56
+ "ENRIPROXY_API_KEY": "YOUR_ENRIPROXY_API_KEY",
57
+ "ENRIVISION_DEFAULT_LANGUAGE": "es"
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ Example: no install (always uses whatever npm currently tags as `latest`)
64
+
65
+ ```jsonc
66
+ {
67
+ "EnriVision": {
68
+ "type": "stdio",
69
+ "command": "npx",
70
+ "args": ["-y", "@bedolla/enrivision@latest"],
71
+ "env": {
72
+ "ENRIPROXY_URL": "http://127.0.0.1:8787",
73
+ "ENRIPROXY_API_KEY": "YOUR_ENRIPROXY_API_KEY",
74
+ "ENRIVISION_DEFAULT_LANGUAGE": "es"
75
+ }
76
+ }
77
+ }
78
+ ```
79
+
80
+ <details>
81
+ <summary>Use a local dev checkout</summary>
82
+
83
+ ```jsonc
84
+ {
85
+ "EnriVision": {
86
+ "type": "stdio",
87
+ "command": "node",
88
+ "args": ["C:\\\\Users\\\\Administrator\\\\Projects\\\\EnriVision\\\\dist\\\\index.js"],
89
+ "env": {
90
+ "ENRIPROXY_URL": "http://127.0.0.1:8787",
91
+ "ENRIPROXY_API_KEY": "YOUR_ENRIPROXY_API_KEY",
92
+ "ENRIVISION_DEFAULT_LANGUAGE": "es"
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ </details>
99
+
100
+ ## Configuration
101
+
102
+ EnriVision is configured via environment variables:
103
+
104
+ - `ENRIPROXY_URL` (`string`, optional, default: `http://127.0.0.1:8787`)
105
+ - `ENRIPROXY_API_KEY` (`string`, required)
106
+ - `ENRIVISION_TIMEOUT_MS` (`string`, optional, default: `1800000`)
107
+ - Parsed as an integer (milliseconds). Uploads are performed in chunks; this timeout applies per request.
108
+ - `ENRIVISION_DEFAULT_LANGUAGE` (`string`, optional)
109
+ - Default language to send when the tool call does not provide `language`.
110
+
111
+ ## MCP tools
112
+
113
+ EnriVision exposes this MCP tool:
114
+
115
+ - `analyze_media`
116
+
117
+ <details>
118
+ <summary>Tool inputs (option-by-option)</summary>
119
+
120
+ General notes:
121
+
122
+ - The tool accepts a single JSON object as its input (the MCP `arguments`).
123
+ - Exactly one of `path` or `paths` is required.
124
+ - Paths must be absolute on the machine running the MCP server.
125
+ - EnriVision does not accept per-call `server_url`/`api_key` overrides (these are configured via env vars).
126
+
127
+ ### `analyze_media`
128
+
129
+ Inputs:
130
+
131
+ - `path` (`string`, optional): absolute local file path.
132
+ - `paths` (`string[]`, optional): absolute local image paths (useful for UI screenshot sets).
133
+ - `context` (`string`, optional): high-level hint (examples: `ui`, `diagram`, `chart`, `error`, `code`, `meeting`, `tutorial`, `photo`).
134
+ - `question` (`string`, optional): what you want to extract/answer.
135
+ - `language` (`string`, optional): preferred response language (ISO 639-1; e.g., `es`, `en`). If omitted, uses `ENRIVISION_DEFAULT_LANGUAGE` when set.
136
+ - `analysis_mode` (`string`, optional): `auto` | `single` | `multipass`.
137
+ - `max_frames` (`number`, optional): single-pass video frames (`1..20`).
138
+ - `transcribe` (`boolean`, optional): enable/disable transcription (videos).
139
+ - `transcription_language` (`string`, optional): whisper hint (`auto`, `es`, `en`, ...).
140
+
141
+ Video targeting:
142
+
143
+ - `video.clip_start_seconds` (`number`, optional)
144
+ - `video.clip_duration_seconds` (`number`, optional)
145
+
146
+ Multipass tuning (advanced; used only for `analysis_mode: multipass`):
147
+
148
+ - `video.segment_seconds` (`number`, optional)
149
+ - `video.max_segments` (`number`, optional)
150
+ - `video.max_frames_per_segment` (`number`, optional)
151
+ - `document.max_pages_total` (`number`, optional)
152
+ - `document.pages_per_batch` (`number`, optional)
153
+ - `document.max_images_per_batch` (`number`, optional)
154
+ - `document.scanned_text_threshold_chars` (`number`, optional)
155
+ - `audio.timestamps` (`boolean`, optional)
156
+ - `audio.segment_seconds` (`number`, optional)
157
+ - `audio.max_segments` (`number`, optional)
158
+ - `images.max_images_total` (`number`, optional)
159
+ - `images.images_per_batch` (`number`, optional)
160
+ - `images.max_dimension` (`number`, optional)
161
+
162
+ Output:
163
+
164
+ - `analysis` (`string`): model-produced analysis.
165
+ - `media_type` (`string`): detected media type (`video`, `audio`, `image`, `document`, `image_set`).
166
+ - `extraction` (`object`): safe metadata summary (internal routing details are stripped).
167
+
168
+ Example `arguments` object:
169
+
170
+ ```jsonc
171
+ {
172
+ "path": "C:\\\\path\\\\to\\\\video.mp4",
173
+ "question": "What are the key steps demonstrated?",
174
+ "analysis_mode": "auto",
175
+ "transcribe": true,
176
+ "language": "es"
177
+ }
178
+ ```
179
+
180
+ </details>
181
+
182
+ <details>
183
+ <summary>Claude Code CLI Read(...) compatibility (reference)</summary>
184
+
185
+ Many MCP clients include a built-in `Read(...)` tool that can ingest local files and attach them to the model request.
186
+ This is convenient, but the set of supported formats is limited and can change across client versions.
187
+
188
+ If the file you need to analyze is not reliably supported by your client (for example `.avif`, `.heic`, `.svg`, videos,
189
+ audio, or Office documents), prefer EnriVision MCP so the client can upload bytes and EnriProxy can do extraction reliably.
190
+
191
+ </details>
192
+
193
+ <details>
194
+ <summary>Supported media types (by extension)</summary>
195
+
196
+ EnriProxy determines media type using content-type and extension allow-lists.
197
+
198
+ Videos:
199
+
200
+ - `.mp4`, `.mov`, `.avi`, `.mkv`, `.webm`, `.m4v`, `.wmv`, `.flv`, `.3gp`, `.3g2`, `.ts`, `.mts`, `.m2ts`, `.mpeg`, `.mpg`, `.gif`
201
+
202
+ Audio:
203
+
204
+ - `.mp3`, `.mp1`, `.mp2`, `.mpa`, `.mpga`, `.wav`, `.aiff`, `.aif`, `.aifc`, `.caf`, `.flac`, `.m4a`, `.m4b`, `.m4r`, `.aac`, `.ogg`, `.oga`, `.wma`, `.opus`, `.weba`, `.mka`
205
+
206
+ Images:
207
+
208
+ - `.png`, `.apng`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.avif`, `.heic`, `.heif`, `.tiff`, `.tif`, `.bmp`, `.svg`, `.ico`
209
+
210
+ Documents:
211
+
212
+ - `.pdf`, `.docx`, `.pptx`, `.xlsx`, `.jsonl`
213
+
214
+ </details>
@@ -0,0 +1,323 @@
1
+ /**
2
+ * ENRIPROXY CLIENT
3
+ *
4
+ * Minimal HTTP client for EnriProxy endpoints used by EnriVision:
5
+ * - POST /v1/uploads
6
+ * - HEAD /v1/uploads/:id
7
+ * - PATCH /v1/uploads/:id
8
+ * - POST /v1/vision/analyze
9
+ *
10
+ * @module client/EnriProxyClient
11
+ */
12
+ /**
13
+ * Connection configuration for {@link EnriProxyClient}.
14
+ */
15
+ export interface EnriProxyClientConfig {
16
+ /**
17
+ * EnriProxy base URL (e.g., https://proxy.example.com).
18
+ */
19
+ readonly baseUrl: string;
20
+ /**
21
+ * EnriProxy API key (sent as Authorization: Bearer ...).
22
+ */
23
+ readonly apiKey: string;
24
+ /**
25
+ * Default request timeout in milliseconds.
26
+ */
27
+ readonly timeoutMs: number;
28
+ }
29
+ /**
30
+ * Response from POST `/v1/uploads`.
31
+ */
32
+ export interface CreateUploadSessionResponse {
33
+ /**
34
+ * Upload session identifier.
35
+ */
36
+ readonly upload_id: string;
37
+ /**
38
+ * Recommended chunk size in bytes.
39
+ */
40
+ readonly chunk_size_bytes: number;
41
+ /**
42
+ * Expiration timestamp in ms since epoch.
43
+ */
44
+ readonly expires_at: number;
45
+ }
46
+ /**
47
+ * Response from POST `/v1/vision/analyze`.
48
+ */
49
+ export interface AnalyzeVisionResponse {
50
+ /**
51
+ * Text analysis.
52
+ */
53
+ readonly analysis: string;
54
+ /**
55
+ * Detected media type.
56
+ */
57
+ readonly media_type: string;
58
+ /**
59
+ * Extraction metadata.
60
+ */
61
+ readonly extraction: Record<string, unknown>;
62
+ }
63
+ /**
64
+ * Error thrown when EnriProxy returns a non-2xx HTTP response.
65
+ */
66
+ export declare class EnriProxyHttpError extends Error {
67
+ /**
68
+ * HTTP status code returned by the server.
69
+ */
70
+ readonly status: number;
71
+ /**
72
+ * Response headers returned by the server.
73
+ */
74
+ readonly headers: Record<string, string | string[] | undefined>;
75
+ /**
76
+ * Response body returned by the server (best-effort UTF-8).
77
+ */
78
+ readonly body: string;
79
+ /**
80
+ * Creates a new {@link EnriProxyHttpError}.
81
+ *
82
+ * @param message - Error message
83
+ * @param status - HTTP status code
84
+ * @param headers - Response headers
85
+ * @param body - Response body
86
+ */
87
+ constructor(message: string, status: number, headers: Record<string, string | string[] | undefined>, body: string);
88
+ }
89
+ /**
90
+ * Minimal client for EnriProxy HTTP endpoints.
91
+ */
92
+ export declare class EnriProxyClient {
93
+ /**
94
+ * EnriProxy base URL.
95
+ */
96
+ private readonly baseUrl;
97
+ /**
98
+ * API key for Authorization header.
99
+ */
100
+ private readonly apiKey;
101
+ /**
102
+ * Default timeout for requests.
103
+ */
104
+ private readonly timeoutMs;
105
+ /**
106
+ * Creates a new {@link EnriProxyClient}.
107
+ *
108
+ * @param config - Client configuration
109
+ */
110
+ constructor(config: EnriProxyClientConfig);
111
+ /**
112
+ * Creates an upload session on the server.
113
+ *
114
+ * @param params - Session parameters
115
+ * @returns Session response
116
+ */
117
+ createUploadSession(params: {
118
+ /**
119
+ * Original filename.
120
+ */
121
+ readonly filename: string;
122
+ /**
123
+ * Total file size in bytes.
124
+ */
125
+ readonly sizeBytes: number;
126
+ /**
127
+ * MIME type.
128
+ */
129
+ readonly contentType: string;
130
+ /**
131
+ * Optional client trace id.
132
+ */
133
+ readonly clientTraceId?: string;
134
+ }): Promise<CreateUploadSessionResponse>;
135
+ /**
136
+ * Queries the current upload offset for a session.
137
+ *
138
+ * @param uploadId - Upload id
139
+ * @returns Offset in bytes
140
+ */
141
+ getUploadOffset(uploadId: string): Promise<number>;
142
+ /**
143
+ * Appends a chunk to an upload session.
144
+ *
145
+ * @param params - Chunk parameters
146
+ * @returns New upload offset in bytes
147
+ */
148
+ appendUploadChunk(params: {
149
+ /**
150
+ * Upload session id.
151
+ */
152
+ readonly uploadId: string;
153
+ /**
154
+ * Expected offset in bytes.
155
+ */
156
+ readonly offset: number;
157
+ /**
158
+ * Chunk bytes.
159
+ */
160
+ readonly chunk: Buffer;
161
+ /**
162
+ * Optional timeout override in milliseconds.
163
+ */
164
+ readonly timeoutMs?: number;
165
+ }): Promise<number>;
166
+ /**
167
+ * Triggers server-side vision analysis for an uploaded file.
168
+ *
169
+ * @param params - Analysis parameters
170
+ * @returns Analysis response
171
+ */
172
+ analyze(params: {
173
+ /**
174
+ * Upload session id.
175
+ */
176
+ readonly uploadId: string;
177
+ /**
178
+ * Optional analysis context hint.
179
+ */
180
+ readonly context?: string;
181
+ /**
182
+ * Optional explicit question.
183
+ */
184
+ readonly question?: string;
185
+ /**
186
+ * Preferred response language.
187
+ */
188
+ readonly language?: string;
189
+ /**
190
+ * Optional max frames override for videos.
191
+ */
192
+ readonly maxFrames?: number;
193
+ /**
194
+ * Optional override for transcription on videos.
195
+ */
196
+ readonly transcribe?: boolean;
197
+ /**
198
+ * Optional transcription language hint.
199
+ */
200
+ readonly transcriptionLanguage?: string;
201
+ /**
202
+ * Optional analysis mode selector.
203
+ */
204
+ readonly analysisMode?: "auto" | "single" | "multipass";
205
+ /**
206
+ * Optional video multipass tuning.
207
+ */
208
+ readonly video?: {
209
+ /**
210
+ * Clip start offset in seconds for targeted analysis.
211
+ */
212
+ readonly clipStartSeconds?: number;
213
+ /**
214
+ * Clip duration in seconds for targeted analysis.
215
+ */
216
+ readonly clipDurationSeconds?: number;
217
+ /**
218
+ * Segment duration in seconds.
219
+ */
220
+ readonly segmentSeconds?: number;
221
+ /**
222
+ * Maximum number of segments to analyze.
223
+ */
224
+ readonly maxSegments?: number;
225
+ /**
226
+ * Maximum frames per segment.
227
+ */
228
+ readonly maxFramesPerSegment?: number;
229
+ };
230
+ /**
231
+ * Optional document multipass tuning (PDF).
232
+ */
233
+ readonly document?: {
234
+ /**
235
+ * Maximum pages to analyze in total.
236
+ */
237
+ readonly maxPagesTotal?: number;
238
+ /**
239
+ * Pages per batch.
240
+ */
241
+ readonly pagesPerBatch?: number;
242
+ /**
243
+ * Maximum rendered pages per batch.
244
+ */
245
+ readonly maxImagesPerBatch?: number;
246
+ /**
247
+ * Minimum extracted text length to treat a page as textual.
248
+ */
249
+ readonly scannedTextThresholdChars?: number;
250
+ };
251
+ /**
252
+ * Optional audio multipass tuning.
253
+ */
254
+ readonly audio?: {
255
+ /**
256
+ * Whether to include timestamped segments in the extracted transcript.
257
+ */
258
+ readonly timestamps?: boolean;
259
+ /**
260
+ * Segment duration in seconds for audio multipass.
261
+ */
262
+ readonly segmentSeconds?: number;
263
+ /**
264
+ * Maximum number of audio segments to analyze.
265
+ */
266
+ readonly maxSegments?: number;
267
+ };
268
+ /**
269
+ * Optional image-set multipass tuning.
270
+ */
271
+ readonly images?: {
272
+ /**
273
+ * Maximum number of images to analyze in total.
274
+ */
275
+ readonly maxImagesTotal?: number;
276
+ /**
277
+ * Images per batch for multipass map calls.
278
+ */
279
+ readonly imagesPerBatch?: number;
280
+ /**
281
+ * Maximum dimension for images (width/height).
282
+ */
283
+ readonly maxDimension?: number;
284
+ };
285
+ }): Promise<AnalyzeVisionResponse>;
286
+ /**
287
+ * Builds an absolute URL relative to the configured base URL.
288
+ *
289
+ * @param pathname - Pathname to append
290
+ * @returns URL instance
291
+ */
292
+ private buildUrl;
293
+ /**
294
+ * Extracts a response header as a single string.
295
+ *
296
+ * @param headers - Response headers
297
+ * @param name - Header name (case-insensitive)
298
+ * @returns Header value when present, otherwise undefined
299
+ */
300
+ private getHeaderValue;
301
+ /**
302
+ * Sends a JSON request and returns the response.
303
+ *
304
+ * @param method - HTTP method
305
+ * @param url - Target URL
306
+ * @param jsonBody - JSON payload
307
+ * @param timeoutMs - Timeout in milliseconds
308
+ * @returns HTTP result
309
+ */
310
+ private requestJson;
311
+ /**
312
+ * Sends an HTTP request with optional headers and body.
313
+ *
314
+ * @param method - HTTP method
315
+ * @param url - Target URL
316
+ * @param headers - Request headers
317
+ * @param body - Request body
318
+ * @param timeoutMs - Timeout in milliseconds
319
+ * @returns HTTP result
320
+ */
321
+ private requestRaw;
322
+ }
323
+ //# sourceMappingURL=EnriProxyClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnriProxyClient.d.ts","sourceRoot":"","sources":["../../src/client/EnriProxyClient.ts"],"names":[],"mappings":"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"}