@tinify-ai/mcp-server 1.2.1 → 1.4.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.
Files changed (56) hide show
  1. package/README.md +95 -17
  2. package/dist/api/auth.d.ts +1 -1
  3. package/dist/api/auth.d.ts.map +1 -1
  4. package/dist/api/auth.js +2 -9
  5. package/dist/api/auth.js.map +1 -1
  6. package/dist/api/client.d.ts +6 -0
  7. package/dist/api/client.d.ts.map +1 -1
  8. package/dist/api/client.js +15 -0
  9. package/dist/api/client.js.map +1 -1
  10. package/dist/api/process.d.ts +4 -2
  11. package/dist/api/process.d.ts.map +1 -1
  12. package/dist/api/process.js +21 -1
  13. package/dist/api/process.js.map +1 -1
  14. package/dist/api/status.d.ts.map +1 -1
  15. package/dist/api/status.js +19 -4
  16. package/dist/api/status.js.map +1 -1
  17. package/dist/api/upload.d.ts +2 -0
  18. package/dist/api/upload.d.ts.map +1 -1
  19. package/dist/api/upload.js +1 -1
  20. package/dist/api/upload.js.map +1 -1
  21. package/dist/auth/anonymous.d.ts +10 -0
  22. package/dist/auth/anonymous.d.ts.map +1 -0
  23. package/dist/auth/anonymous.js +37 -0
  24. package/dist/auth/anonymous.js.map +1 -0
  25. package/dist/auth/context.d.ts +13 -0
  26. package/dist/auth/context.d.ts.map +1 -0
  27. package/dist/auth/context.js +10 -0
  28. package/dist/auth/context.js.map +1 -0
  29. package/dist/auth/jwt.d.ts +7 -0
  30. package/dist/auth/jwt.d.ts.map +1 -0
  31. package/dist/auth/jwt.js +35 -0
  32. package/dist/auth/jwt.js.map +1 -0
  33. package/dist/auth/resolver.d.ts +11 -0
  34. package/dist/auth/resolver.d.ts.map +1 -0
  35. package/dist/auth/resolver.js +35 -0
  36. package/dist/auth/resolver.js.map +1 -0
  37. package/dist/index.js +195 -155
  38. package/dist/index.js.map +1 -1
  39. package/dist/tools/login.js +1 -1
  40. package/dist/tools/login.js.map +1 -1
  41. package/dist/tools/optimize.d.ts +12 -2
  42. package/dist/tools/optimize.d.ts.map +1 -1
  43. package/dist/tools/optimize.js +95 -15
  44. package/dist/tools/optimize.js.map +1 -1
  45. package/dist/tools/status.d.ts.map +1 -1
  46. package/dist/tools/status.js +9 -6
  47. package/dist/tools/status.js.map +1 -1
  48. package/dist/transport/http.d.ts +8 -0
  49. package/dist/transport/http.d.ts.map +1 -0
  50. package/dist/transport/http.js +151 -0
  51. package/dist/transport/http.js.map +1 -0
  52. package/dist/x402/client.d.ts +26 -0
  53. package/dist/x402/client.d.ts.map +1 -0
  54. package/dist/x402/client.js +73 -0
  55. package/dist/x402/client.js.map +1 -0
  56. package/package.json +10 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
5
  [![MCP](https://img.shields.io/badge/MCP-Compatible-brightgreen.svg)](https://modelcontextprotocol.io)
6
6
 
7
- MCP server for [tinify.ai](https://tinify.ai) image optimization. AI-powered upscaling, resizing/cropping, compression, and SEO tag generation — all in one tool.
7
+ MCP server for [tinify.ai](https://tinify.ai) image optimization. AI-powered upscaling, resizing/cropping, compression, and SEO filename & alt text generation — all in one tool.
8
8
 
9
9
  ## Quick Start
10
10
 
@@ -84,6 +84,52 @@ Edit `~/.codeium/windsurf/mcp_config.json`:
84
84
  ```
85
85
  </details>
86
86
 
87
+ <details>
88
+ <summary><strong>Cline</strong></summary>
89
+
90
+ Open Cline settings → MCP Servers → Add, then paste:
91
+
92
+ ```json
93
+ {
94
+ "mcpServers": {
95
+ "tinify": {
96
+ "command": "npx",
97
+ "args": ["-y", "@tinify-ai/mcp-server@latest"]
98
+ }
99
+ }
100
+ }
101
+ ```
102
+ </details>
103
+
104
+ <details>
105
+ <summary><strong>Gemini CLI</strong></summary>
106
+
107
+ Edit `~/.gemini/settings.json` (global) or `.gemini/settings.json` in your project root:
108
+
109
+ ```json
110
+ {
111
+ "mcpServers": {
112
+ "tinify": {
113
+ "command": "npx",
114
+ "args": ["-y", "@tinify-ai/mcp-server@latest"]
115
+ }
116
+ }
117
+ }
118
+ ```
119
+ </details>
120
+
121
+ <details>
122
+ <summary><strong>OpenAI Codex CLI</strong></summary>
123
+
124
+ Edit `~/.codex/config.toml`:
125
+
126
+ ```toml
127
+ [mcp_servers.tinify]
128
+ command = "npx"
129
+ args = ["-y", "@tinify-ai/mcp-server@latest"]
130
+ ```
131
+ </details>
132
+
87
133
  ## Tool: `optimize_image`
88
134
 
89
135
  Optimizes an image with smart lossy compression (typically 60-80% size reduction), optional resize/upscale/format conversion, and AI-generated SEO metadata. Accepts absolute local file paths or remote URLs.
@@ -94,12 +140,15 @@ Optimizes an image with smart lossy compression (typically 60-80% size reduction
94
140
  |-----------|------|----------|---------|-------------|
95
141
  | `input` | string | Yes | — | Absolute local file path or remote URL |
96
142
  | `output_path` | string | No | auto | File path or directory (ending in `/`). If omitted: saves next to original with SEO slug or `.tinified` suffix |
97
- | `output_format` | string | No | original | `jpeg`, `png`, `webp`, or `original` |
143
+ | `output_format` | string | No | original | `jpg`, `png`, `webp`, `avif`, `gif`, or `original` |
98
144
  | `output_width_px` | int | No | — | Target width in pixels |
99
145
  | `output_height_px` | int | No | — | Target height in pixels |
100
- | `output_upscale_factor` | float | No | — | AI upscale factor (e.g. 2.0, 4.0) |
146
+ | `output_upscale_factor` | int | No | — | AI upscale factor: `2` (2×) or `4` (4×) |
101
147
  | `output_resize_behavior` | string | No | pad | `pad` (white padding) or `crop` (smart crop). Only used when both width and height are set |
102
148
  | `output_seo_tag_gen` | bool | No | true | Generate SEO metadata and rename file to SEO slug. Costs 1 extra credit |
149
+ | `output_file_size_limit` | int | No | — | Target maximum output file size in bytes. Server attempts to meet this via additional compression. Not guaranteed |
150
+ | `gif_frame_limit` | int | No | 100 | Max frames to process for animated GIFs (1–100). Reduces credit cost by sampling fewer frames |
151
+ | `confirm_gif_cost` | bool | No | — | Set to `true` to proceed after reviewing the animated GIF cost warning. Required for animated GIFs |
103
152
 
104
153
  ### Resize Behavior
105
154
 
@@ -191,25 +240,52 @@ Alt text: Modern office workspace with laptop and coffee cup on wooden desk
191
240
 
192
241
  ## Supported Formats
193
242
 
194
- | Format | Input | Output |
195
- |--------|-------|--------|
196
- | JPG | Yes | Yes |
197
- | PNG | Yes | Yes |
198
- | WebP | Yes | Yes |
199
- | AVIF | Yes | Yes |
200
- | HEIC/HEIF | Yes* | No |
201
- | TIFF | Yes* | No |
202
- | BMP | Yes* | No |
243
+ | Format | Input | Output | Notes |
244
+ |--------|-------|--------|-------|
245
+ | JPG | Yes | Yes | |
246
+ | PNG | Yes | Yes | |
247
+ | WebP | Yes | Yes | |
248
+ | AVIF | Yes | Yes | |
249
+ | GIF | Yes | Yes | Animated GIFs preserved when output is GIF |
250
+ | SVG | Yes | Yes | SVG→SVG optimized via SVGO; raster↔SVG conversion supported |
251
+ | ICO | Yes | Yes | Smart rebuild: generates 16, 24, 32, 48, 256px favicon set |
252
+ | HEIC/HEIF | Yes* | No | Auto-converted to JPG at upload |
253
+ | TIFF | Yes* | No | Auto-converted to JPG at upload |
254
+ | BMP | Yes* | No | Auto-converted to JPG at upload |
255
+
256
+ tinify.ai supports high-quality conversion between any input and output format combination.
257
+ Converting an animated GIF to a non-GIF format (JPG, PNG, WebP, AVIF) preserves only the first frame.
258
+ Converting an animated GIF to a GIF format supports upscaling/resizing while preserving the animation and quality. You may also reduce animated GIF file size by decreasing the number of output frames.
203
259
 
204
- *Automatically converted to JPG at upload time.
260
+ Max upload file size: 50 MB.
261
+
262
+ ### SVG & ICO Examples
263
+
264
+ ```
265
+ # Optimize an SVG file (keeps as vector)
266
+ Optimize logo.svg and keep it as SVG
205
267
 
206
- Max file size: 50 MB.
268
+ # Convert SVG to raster
269
+ Convert icon.svg to a 512x512 PNG
270
+
271
+ # Trace raster to vector SVG
272
+ Convert my logo.png to a vector SVG
273
+
274
+ # Generate favicon set from any image
275
+ Convert logo.png to an ICO favicon
276
+
277
+ # Generate single-size ICO
278
+ Convert logo.png to a 32x32 ICO
279
+
280
+ # Extract largest icon from ICO
281
+ Convert favicon.ico to PNG
282
+ ```
207
283
 
208
284
  ## How It Works
209
285
 
210
286
  ```
211
287
  Local file or URL
212
- → Upload to Tinify API
288
+ → Upload to Tinify.ai API
213
289
  → Smart compression (lossy, typically 60-80% reduction)
214
290
  → AI SEO tag generation (alt text, keywords, filename)
215
291
  → Optional: resize, upscale, format conversion
@@ -217,7 +293,7 @@ Local file or URL
217
293
  → Save with SEO filename slug (or .tinified suffix if SEO disabled)
218
294
  ```
219
295
 
220
- All processing happens server-side via the [Tinify API](https://tinify.ai). The MCP server is a thin client that orchestrates the pipeline.
296
+ All processing happens server-side via the [Tinify.ai API](https://api.tinify.ai). The MCP server is a thin client that orchestrates the pipeline.
221
297
 
222
298
  ## Credits
223
299
 
@@ -272,7 +348,7 @@ Opens [tinify.ai/pricing](https://tinify.ai/pricing) in your browser.
272
348
  Paste this into your `CLAUDE.md` or system prompt to help agents use the tool effectively:
273
349
 
274
350
  ```
275
- ## Tinify MCP
351
+ ## Tinify.ai MCP
276
352
 
277
353
  Tools: optimize_image, login, logout, status, upgrade
278
354
 
@@ -284,6 +360,8 @@ Tools: optimize_image, login, logout, status, upgrade
284
360
  - When both dimensions are set, use output_resize_behavior: "crop" for photos, "pad" for logos/icons.
285
361
  - output_seo_tag_gen (default true) renames the file to an SEO slug and generates alt text + keywords.
286
362
  - Set output_seo_tag_gen: false to save 1 credit when SEO metadata is not needed.
363
+ - GIF is supported for both input and output; animated GIFs stay animated when output_format is "gif".
364
+ - Converting an animated GIF to jpg/png/webp/avif preserves only the first frame.
287
365
  - HEIC, TIFF, BMP inputs are auto-converted to JPG.
288
366
  - For batch processing, call optimize_image once per file.
289
367
  - If credits run out, use login to sign in or upgrade to open pricing.
@@ -25,5 +25,5 @@ export interface AccountStatus {
25
25
  export declare function requestDeviceCode(baseUrl: string): Promise<DeviceCodeResponse>;
26
26
  export declare function pollForToken(baseUrl: string, deviceCode: string): Promise<TokenPollResponse>;
27
27
  export declare function revokeToken(baseUrl: string, mcpToken: string): Promise<void>;
28
- export declare function getAccountStatus(baseUrl: string, mcpToken: string | null, sessionToken: string | null): Promise<AccountStatus>;
28
+ export declare function getAccountStatus(baseUrl: string, authHeaders: Record<string, string>): Promise<AccountStatus>;
29
29
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAOpF;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAOlG;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASlF;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,OAAO,CAAC,aAAa,CAAC,CAaxB"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,iBAAiB,EAAE,MAAM,CAAC;QAC1B,aAAa,EAAE,MAAM,CAAC;QACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAOpF;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAOlG;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASlF;AAED,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,OAAO,CAAC,aAAa,CAAC,CAOxB"}
package/dist/api/auth.js CHANGED
@@ -25,15 +25,8 @@ export async function revokeToken(baseUrl, mcpToken) {
25
25
  throw new ApiError(body.detail || "Token revocation failed", response.status);
26
26
  }
27
27
  }
28
- export async function getAccountStatus(baseUrl, mcpToken, sessionToken) {
29
- const headers = {};
30
- if (mcpToken) {
31
- headers.Authorization = `Bearer ${mcpToken}`;
32
- }
33
- else if (sessionToken) {
34
- headers["X-Session-Token"] = sessionToken;
35
- }
36
- const response = await fetch(`${baseUrl}/mcp/auth/status`, { headers });
28
+ export async function getAccountStatus(baseUrl, authHeaders) {
29
+ const response = await fetch(`${baseUrl}/mcp/auth/status`, { headers: authHeaders });
37
30
  if (!response.ok) {
38
31
  const body = await response.json().catch(() => ({}));
39
32
  throw new ApiError(body.detail || "Status check failed", response.status);
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA6BvC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAe;IACrD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,uBAAuB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,8BAA8B,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe,EAAE,UAAkB;IACpE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,+BAA+B,UAAU,EAAE,CAAC,CAAC;IACpF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,QAAgB;IACjE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,kBAAkB,EAAE;QACzD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,QAAQ,EAAE,EAAE;KACjD,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,QAAuB,EACvB,YAA2B;IAE3B,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,aAAa,GAAG,UAAU,QAAQ,EAAE,CAAC;IAC/C,CAAC;SAAM,IAAI,YAAY,EAAE,CAAC;QACxB,OAAO,CAAC,iBAAiB,CAAC,GAAG,YAAY,CAAC;IAC5C,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,kBAAkB,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACxE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA6BvC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAe;IACrD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,uBAAuB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACpF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,8BAA8B,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe,EAAE,UAAkB;IACpE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,+BAA+B,UAAU,EAAE,CAAC,CAAC;IACpF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,QAAgB;IACjE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,kBAAkB,EAAE;QACzD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,QAAQ,EAAE,EAAE;KACjD,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,WAAmC;IAEnC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,kBAAkB,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IACrF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -8,4 +8,10 @@ export declare class ApiError extends Error {
8
8
  readonly detail?: string | undefined;
9
9
  constructor(message: string, status: number, detail?: string | undefined);
10
10
  }
11
+ /**
12
+ * Returns auth headers for an API call.
13
+ * In HTTP mode (request context present): uses per-request auth from context.
14
+ * In stdio mode (no context): reads from ~/.tinify/session.json via SessionManager.
15
+ */
16
+ export declare function getAuthHeaders(): Record<string, string>;
11
17
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD,qBAAa,QAAS,SAAQ,KAAK;aAGf,MAAM,EAAE,MAAM;aACd,MAAM,CAAC,EAAE,MAAM;gBAF/B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,YAAA;CAKlC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AAExD,qBAAa,QAAS,SAAQ,KAAK;aAGf,MAAM,EAAE,MAAM;aACd,MAAM,CAAC,EAAE,MAAM;gBAF/B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,YAAA;CAKlC;AAKD;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOvD"}
@@ -9,4 +9,19 @@ export class ApiError extends Error {
9
9
  this.name = "ApiError";
10
10
  }
11
11
  }
12
+ import { getRequestAuthHeaders } from "../auth/context.js";
13
+ import { SessionManager } from "../session/manager.js";
14
+ /**
15
+ * Returns auth headers for an API call.
16
+ * In HTTP mode (request context present): uses per-request auth from context.
17
+ * In stdio mode (no context): reads from ~/.tinify/session.json via SessionManager.
18
+ */
19
+ export function getAuthHeaders() {
20
+ // HTTP mode: context is set by the transport per request
21
+ const contextHeaders = getRequestAuthHeaders();
22
+ if (Object.keys(contextHeaders).length > 0)
23
+ return contextHeaders;
24
+ // stdio mode: read from local session file
25
+ return new SessionManager().getAuthHeaders();
26
+ }
12
27
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGf;IACA;IAHlB,YACE,OAAe,EACC,MAAc,EACd,MAAe;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAS;QAG/B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD,MAAM,OAAO,QAAS,SAAQ,KAAK;IAGf;IACA;IAHlB,YACE,OAAe,EACC,MAAc,EACd,MAAe;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,WAAM,GAAN,MAAM,CAAQ;QACd,WAAM,GAAN,MAAM,CAAS;QAG/B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC5B,yDAAyD;IACzD,MAAM,cAAc,GAAG,qBAAqB,EAAE,CAAC;IAC/C,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,cAAc,CAAC;IAElE,2CAA2C;IAC3C,OAAO,IAAI,cAAc,EAAE,CAAC,cAAc,EAAE,CAAC;AAC/C,CAAC"}
@@ -1,11 +1,13 @@
1
1
  export interface ProcessingSettings {
2
- output_format?: "original" | "jpg" | "png" | "webp" | "avif";
3
- output_upscale_factor?: number;
2
+ output_format?: "original" | "jpg" | "png" | "webp" | "avif" | "gif" | "svg" | "ico";
3
+ output_upscale_factor?: 2 | 4;
4
4
  output_width?: number;
5
5
  output_height?: number;
6
6
  output_resize_behavior?: "pad" | "crop";
7
7
  output_seo_tag_gen?: boolean;
8
8
  output_seo_rename?: boolean;
9
+ output_file_size_limit?: number;
10
+ gif_frame_limit?: number;
9
11
  }
10
12
  interface ProcessParams {
11
13
  baseUrl: string;
@@ -1 +1 @@
1
- {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/api/process.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7D,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,UAAU,OAAO;IACf,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAiDrF"}
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../src/api/process.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IACrF,qBAAqB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,UAAU,OAAO;IACf,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAiFrF"}
@@ -1,11 +1,15 @@
1
1
  import { ApiError } from "./client.js";
2
+ import { getX402Fetch, isX402Configured, getWalletAddress } from "../x402/client.js";
2
3
  export async function triggerProcessing(params) {
3
4
  const { baseUrl, tempFileIds, settings, authHeaders } = params;
4
5
  const headers = {
5
6
  "Content-Type": "application/json",
6
7
  ...authHeaders,
7
8
  };
8
- const response = await fetch(`${baseUrl}/auto`, {
9
+ // Use x402-wrapped fetch if available (auto-handles 402 payment signing)
10
+ const x402Fetch = await getX402Fetch();
11
+ const fetchFn = x402Fetch ?? fetch;
12
+ const response = await fetchFn(`${baseUrl}/auto`, {
9
13
  method: "POST",
10
14
  headers,
11
15
  body: JSON.stringify({
@@ -15,6 +19,22 @@ export async function triggerProcessing(params) {
15
19
  });
16
20
  if (!response.ok) {
17
21
  const body = await response.json().catch(() => ({}));
22
+ // Handle 402 Payment Required (x402 not configured or payment failed)
23
+ if (response.status === 402) {
24
+ const priceUsdc = body.x402?.price_usdc ?? "unknown";
25
+ const creditsNeeded = body.x402?.credits_needed ?? "unknown";
26
+ if (!isX402Configured()) {
27
+ throw new ApiError(`Insufficient credits. This operation costs $${priceUsdc} USDC (${creditsNeeded} credits).\n\n` +
28
+ `To enable Pay As You Go:\n` +
29
+ `1. Set TINIFY_X402_PRIVATE_KEY environment variable with a Base wallet private key\n` +
30
+ `2. Fund the wallet with USDC on Base network\n\n` +
31
+ `Or use \`login\` to access subscription credits.`, 402, body.detail);
32
+ }
33
+ // x402 IS configured but payment still failed
34
+ const walletAddr = await getWalletAddress();
35
+ throw new ApiError(`Payment failed for $${priceUsdc} USDC. Check your wallet has sufficient USDC on Base.\n` +
36
+ `Wallet: ${walletAddr}`, 402, body.detail);
37
+ }
18
38
  if (response.status === 429) {
19
39
  if (body.is_guest) {
20
40
  throw new ApiError(`You've used all ${body.credits_limit || 20} free daily credits. ` +
@@ -1 +1 @@
1
- {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/api/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAgCvC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAqB;IAC3D,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAE/D,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAG,WAAW;KACf,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE;QAC9C,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,aAAa,EAAE,WAAW;YAC1B,QAAQ;SACT,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,MAAM,IAAI,QAAQ,CAChB,mBAAmB,IAAI,CAAC,aAAa,IAAI,EAAE,uBAAuB;oBAClE,8DAA8D;oBAC9D,6DAA6D,EAC7D,GAAG,EACH,IAAI,CAAC,MAAM,CACZ,CAAC;YACJ,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACrB,MAAM,IAAI,QAAQ,CAChB,mBAAmB,IAAI,CAAC,aAAa,6BAA6B,IAAI,CAAC,IAAI,UAAU;oBACrF,qDAAqD,EACrD,GAAG,EACH,IAAI,CAAC,MAAM,CACZ,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,kCAAkC;gBAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,GAAG,CAAC;gBACvE,MAAM,IAAI,QAAQ,CAChB,yBAAyB,SAAS,qBAAqB,EACvD,GAAG,EACH,IAAI,CAAC,MAAM,CACZ,CAAC;YACJ,CAAC;QACH,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,IAAI,mBAAmB,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACvF,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/api/process.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/api/status.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC3C,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAmD7E"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/api/status.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC3C,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,2BAA2B,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAgE7E"}
@@ -2,17 +2,25 @@ import { ApiError } from "./client.js";
2
2
  import { EventSource as EventSourcePoly } from "eventsource";
3
3
  export function waitForCompletion(params) {
4
4
  const { baseUrl, jobId, timeoutMs = 60000 } = params;
5
+ const timeoutSecs = Math.round(timeoutMs / 1000);
5
6
  return new Promise((resolve, reject) => {
6
7
  const ESConstructor = typeof EventSource !== "undefined" ? EventSource : EventSourcePoly;
7
8
  const es = new ESConstructor(`${baseUrl}/status/${jobId}/stream`);
8
9
  const timeout = setTimeout(() => {
9
10
  es.close();
10
- reject(new ApiError("Processing timed out after 60 seconds.", 504));
11
+ reject(new ApiError(`Processing timed out after ${timeoutSecs} seconds.`, 504));
11
12
  }, timeoutMs);
12
13
  es.addEventListener("complete", (event) => {
13
14
  clearTimeout(timeout);
14
15
  es.close();
15
- const data = JSON.parse(event.data);
16
+ let data;
17
+ try {
18
+ data = JSON.parse(event.data);
19
+ }
20
+ catch {
21
+ reject(new ApiError("Invalid response from server.", 500));
22
+ return;
23
+ }
16
24
  if (data.status === "completed") {
17
25
  resolve(data);
18
26
  }
@@ -23,13 +31,20 @@ export function waitForCompletion(params) {
23
31
  es.addEventListener("error", (event) => {
24
32
  clearTimeout(timeout);
25
33
  es.close();
26
- const data = event.data ? JSON.parse(event.data) : {};
34
+ let data = {};
35
+ try {
36
+ if (event.data)
37
+ data = JSON.parse(event.data);
38
+ }
39
+ catch {
40
+ // ignore parse errors, use fallback message
41
+ }
27
42
  reject(new ApiError(`Processing error: ${data.message ?? "Connection lost"}`, 500, data.message));
28
43
  });
29
44
  es.addEventListener("timeout", () => {
30
45
  clearTimeout(timeout);
31
46
  es.close();
32
- reject(new ApiError("Processing timed out after 60 seconds.", 504));
47
+ reject(new ApiError(`Processing timed out after ${timeoutSecs} seconds.`, 504));
33
48
  });
34
49
  });
35
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/api/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC;AAuB7D,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,GAAG,MAAM,CAAC;IAErD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,aAAa,GACjB,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAE,eAAuB,CAAC;QAC9E,MAAM,EAAE,GAAG,IAAI,aAAa,CAAC,GAAG,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC;QAElE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,QAAQ,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC,CAAC;QACtE,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,EAAE,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,KAAU,EAAE,EAAE;YAC7C,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,EAAE,CAAC,KAAK,EAAE,CAAC;YAEX,MAAM,IAAI,GAAiB,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAElD,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACN,MAAM,CACJ,IAAI,QAAQ,CACV,sBAAsB,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,EACrD,GAAG,EACH,IAAI,CAAC,KAAK,IAAI,SAAS,CACxB,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAU,EAAE,EAAE;YAC1C,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACtD,MAAM,CACJ,IAAI,QAAQ,CACV,qBAAqB,IAAI,CAAC,OAAO,IAAI,iBAAiB,EAAE,EACxD,GAAG,EACH,IAAI,CAAC,OAAO,CACb,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE;YAClC,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,QAAQ,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/api/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,aAAa,CAAC;AAuB7D,MAAM,UAAU,iBAAiB,CAAC,MAAoB;IACpD,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,GAAG,MAAM,CAAC;IAErD,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAEjD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,aAAa,GACjB,OAAO,WAAW,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAE,eAAuB,CAAC;QAC9E,MAAM,EAAE,GAAG,IAAI,aAAa,CAAC,GAAG,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC;QAElE,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,QAAQ,CAAC,8BAA8B,WAAW,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;QAClF,CAAC,EAAE,SAAS,CAAC,CAAC;QAEd,EAAE,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,KAAU,EAAE,EAAE;YAC7C,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,EAAE,CAAC,KAAK,EAAE,CAAC;YAEX,IAAI,IAAkB,CAAC;YACvB,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,CAAC,IAAI,QAAQ,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC3D,OAAO;YACT,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAChC,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACN,MAAM,CACJ,IAAI,QAAQ,CACV,sBAAsB,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,EACrD,GAAG,EACH,IAAI,CAAC,KAAK,IAAI,SAAS,CACxB,CACF,CAAC;YACJ,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAU,EAAE,EAAE;YAC1C,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,IAAI,GAAyB,EAAE,CAAC;YACpC,IAAI,CAAC;gBACH,IAAI,KAAK,CAAC,IAAI;oBAAE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAChD,CAAC;YAAC,MAAM,CAAC;gBACP,4CAA4C;YAC9C,CAAC;YACD,MAAM,CACJ,IAAI,QAAQ,CACV,qBAAqB,IAAI,CAAC,OAAO,IAAI,iBAAiB,EAAE,EACxD,GAAG,EACH,IAAI,CAAC,OAAO,CACb,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,GAAG,EAAE;YAClC,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,QAAQ,CAAC,8BAA8B,WAAW,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -10,6 +10,8 @@ interface UploadResult {
10
10
  file_size: number;
11
11
  mime_type: string;
12
12
  session_token: string | null;
13
+ gif_frame_count?: number;
14
+ gif_fps?: number;
13
15
  }
14
16
  export declare function uploadFile(params: UploadParams): Promise<UploadResult>;
15
17
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/api/upload.ts"],"names":[],"mappings":"AAEA,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,UAAU,YAAY;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAsC5E"}
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../src/api/upload.ts"],"names":[],"mappings":"AAEA,UAAU,YAAY;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,UAAU,YAAY;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAsC5E"}
@@ -15,7 +15,7 @@ export async function uploadFile(params) {
15
15
  throw new ApiError("File exceeds maximum size limit.", response.status, body.detail);
16
16
  }
17
17
  if (response.status === 415 || body.detail?.includes("Unsupported")) {
18
- throw new ApiError("Unsupported image format. Supported: JPEG, PNG, WebP, HEIC.", response.status, body.detail);
18
+ throw new ApiError("Unsupported image format. Supported: JPEG, PNG, WebP, AVIF, GIF, HEIC, TIFF, BMP.", response.status, body.detail);
19
19
  }
20
20
  throw new ApiError(body.detail || "Upload failed", response.status, body.detail);
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/api/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiBvC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAoB;IACnD,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAE9D,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,QAAQ,CAAC,MAAM,CACb,MAAM,EACN,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU,CAAgB,CAAC,CAAC,EACxH,QAAQ,CACT,CAAC;IAEF,MAAM,OAAO,GAA2B,EAAE,GAAG,WAAW,EAAE,CAAC;IAE3D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,SAAS,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,QAAQ;KACf,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,QAAQ,CAAC,kCAAkC,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,QAAQ,CAChB,6DAA6D,EAC7D,QAAQ,CAAC,MAAM,EACf,IAAI,CAAC,MAAM,CACZ,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,QAAQ,CAChB,IAAI,CAAC,MAAM,IAAI,eAAe,EAC9B,QAAQ,CAAC,MAAM,EACf,IAAI,CAAC,MAAM,CACZ,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
1
+ {"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/api/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAmBvC,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAoB;IACnD,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;IAE9D,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,QAAQ,CAAC,MAAM,CACb,MAAM,EACN,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,GAAG,UAAU,CAAC,UAAU,CAAgB,CAAC,CAAC,EACxH,QAAQ,CACT,CAAC;IAEF,MAAM,OAAO,GAA2B,EAAE,GAAG,WAAW,EAAE,CAAC;IAE3D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,SAAS,EAAE;QAChD,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,QAAQ;KACf,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC5B,MAAM,IAAI,QAAQ,CAAC,kCAAkC,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACpE,MAAM,IAAI,QAAQ,CAChB,mFAAmF,EACnF,QAAQ,CAAC,MAAM,EACf,IAAI,CAAC,MAAM,CACZ,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,QAAQ,CAChB,IAAI,CAAC,MAAM,IAAI,eAAe,EAC9B,QAAQ,CAAC,MAAM,EACf,IAAI,CAAC,MAAM,CACZ,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Manages anonymous Supabase sessions for unauthenticated MCP clients.
3
+ * Each unique Mcp-Session-Id gets its own anonymous Supabase user.
4
+ * JWTs are cached in memory with bounded LRU eviction and TTL.
5
+ */
6
+ export declare class AnonymousSessionStore {
7
+ private readonly cache;
8
+ getOrCreate(sessionId: string): Promise<string | null>;
9
+ }
10
+ //# sourceMappingURL=anonymous.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymous.d.ts","sourceRoot":"","sources":["../../src/auth/anonymous.ts"],"names":[],"mappings":"AASA;;;;GAIG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoC;IAEpD,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CA4B7D"}
@@ -0,0 +1,37 @@
1
+ import { createClient } from "@supabase/supabase-js";
2
+ const MAX_CACHE_SIZE = 10_000;
3
+ /**
4
+ * Manages anonymous Supabase sessions for unauthenticated MCP clients.
5
+ * Each unique Mcp-Session-Id gets its own anonymous Supabase user.
6
+ * JWTs are cached in memory with bounded LRU eviction and TTL.
7
+ */
8
+ export class AnonymousSessionStore {
9
+ cache = new Map(); // sessionId → { jwt, expiresAt }
10
+ async getOrCreate(sessionId) {
11
+ if (!process.env.SUPABASE_URL || !process.env.SUPABASE_ANON_KEY)
12
+ return null;
13
+ const cached = this.cache.get(sessionId);
14
+ if (cached && cached.expiresAt > Date.now()) {
15
+ // LRU: delete and re-insert to move to end
16
+ this.cache.delete(sessionId);
17
+ this.cache.set(sessionId, cached);
18
+ return cached.jwt;
19
+ }
20
+ // Fresh client per call to avoid race conditions between concurrent requests
21
+ const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY);
22
+ const { data, error } = await supabase.auth.signInAnonymously();
23
+ if (error || !data.session)
24
+ return null;
25
+ const jwt = data.session.access_token;
26
+ const expiresAt = Date.now() + (data.session.expires_in ?? 3600) * 1000;
27
+ // Evict oldest entry if at capacity (LRU — Map preserves insertion order)
28
+ if (this.cache.size >= MAX_CACHE_SIZE) {
29
+ const oldestKey = this.cache.keys().next().value;
30
+ if (oldestKey !== undefined)
31
+ this.cache.delete(oldestKey);
32
+ }
33
+ this.cache.set(sessionId, { jwt, expiresAt });
34
+ return jwt;
35
+ }
36
+ }
37
+ //# sourceMappingURL=anonymous.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anonymous.js","sourceRoot":"","sources":["../../src/auth/anonymous.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAOrD,MAAM,cAAc,GAAG,MAAM,CAAC;AAE9B;;;;GAIG;AACH,MAAM,OAAO,qBAAqB;IACf,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC,CAAC,iCAAiC;IAE5F,KAAK,CAAC,WAAW,CAAC,SAAiB;QACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB;YAAE,OAAO,IAAI,CAAC;QAE7E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC5C,2CAA2C;YAC3C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC7B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAClC,OAAO,MAAM,CAAC,GAAG,CAAC;QACpB,CAAC;QAED,6EAA6E;QAC7E,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACvF,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAChE,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAExC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;QACtC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC;QAExE,0EAA0E;QAC1E,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,cAAc,EAAE,CAAC;YACtC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YACjD,IAAI,SAAS,KAAK,SAAS;gBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5D,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC9C,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ interface RequestContext {
3
+ authHeaders: Record<string, string>;
4
+ sessionId: string;
5
+ }
6
+ export declare const requestContext: AsyncLocalStorage<RequestContext>;
7
+ /**
8
+ * Returns the auth headers for the currently executing MCP request.
9
+ * Returns an empty object when called outside of an HTTP request context (e.g., stdio mode).
10
+ */
11
+ export declare function getRequestAuthHeaders(): Record<string, string>;
12
+ export {};
13
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAErD,UAAU,cAAc;IACtB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,cAAc,mCAA0C,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAE9D"}
@@ -0,0 +1,10 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ export const requestContext = new AsyncLocalStorage();
3
+ /**
4
+ * Returns the auth headers for the currently executing MCP request.
5
+ * Returns an empty object when called outside of an HTTP request context (e.g., stdio mode).
6
+ */
7
+ export function getRequestAuthHeaders() {
8
+ return requestContext.getStore()?.authHeaders ?? {};
9
+ }
10
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/auth/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAOrD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,iBAAiB,EAAkB,CAAC;AAEtE;;;GAGG;AACH,MAAM,UAAU,qBAAqB;IACnC,OAAO,cAAc,CAAC,QAAQ,EAAE,EAAE,WAAW,IAAI,EAAE,CAAC;AACtD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type JWTPayload } from "jose";
2
+ /**
3
+ * Validates a Supabase-issued JWT using JWKS.
4
+ * Returns the payload if valid, null if invalid or not a Supabase JWT.
5
+ */
6
+ export declare function verifySupabaseJwt(token: string): Promise<JWTPayload | null>;
7
+ //# sourceMappingURL=jwt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/auth/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AActE;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAiBjF"}
@@ -0,0 +1,35 @@
1
+ import { createRemoteJWKSet, jwtVerify } from "jose";
2
+ let _jwks = null;
3
+ function getJwks() {
4
+ if (!process.env.SUPABASE_URL)
5
+ return null;
6
+ if (!_jwks) {
7
+ _jwks = createRemoteJWKSet(new URL(`${process.env.SUPABASE_URL}/auth/v1/.well-known/jwks.json`));
8
+ }
9
+ return _jwks;
10
+ }
11
+ /**
12
+ * Validates a Supabase-issued JWT using JWKS.
13
+ * Returns the payload if valid, null if invalid or not a Supabase JWT.
14
+ */
15
+ export async function verifySupabaseJwt(token) {
16
+ if (!process.env.SUPABASE_URL)
17
+ return null;
18
+ // mcp_ tokens are not JWTs; skip JWKS validation
19
+ if (!token.startsWith("eyJ"))
20
+ return null;
21
+ const jwks = getJwks();
22
+ if (!jwks)
23
+ return null;
24
+ try {
25
+ const { payload } = await jwtVerify(token, jwks, {
26
+ issuer: `${process.env.SUPABASE_URL}/auth/v1`,
27
+ audience: "authenticated",
28
+ });
29
+ return payload;
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ //# sourceMappingURL=jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/auth/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAmB,MAAM,MAAM,CAAC;AAEtE,IAAI,KAAK,GAAiD,IAAI,CAAC;AAE/D,SAAS,OAAO;IACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,kBAAkB,CACxB,IAAI,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,gCAAgC,CAAC,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa;IACnD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAC3C,iDAAiD;IACjD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE;YAC/C,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,UAAU;YAC7C,QAAQ,EAAE,eAAe;SAC1B,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Given an Authorization header value and session ID from an HTTP request,
3
+ * returns the auth headers to forward to api.tinify.ai.
4
+ *
5
+ * Priority:
6
+ * 1. Bearer mcp_... → pass through as-is (existing mcp_tokens)
7
+ * 2. Bearer eyJ... → validate Supabase JWT → pass through if valid
8
+ * 3. No/invalid auth → anonymous Supabase session JWT
9
+ */
10
+ export declare function resolveAuthHeaders(authorizationHeader: string | null, sessionId: string): Promise<Record<string, string>>;
11
+ //# sourceMappingURL=resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/auth/resolver.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,mBAAmB,EAAE,MAAM,GAAG,IAAI,EAClC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAqBjC"}