@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.
- package/README.md +95 -17
- package/dist/api/auth.d.ts +1 -1
- package/dist/api/auth.d.ts.map +1 -1
- package/dist/api/auth.js +2 -9
- package/dist/api/auth.js.map +1 -1
- package/dist/api/client.d.ts +6 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +15 -0
- package/dist/api/client.js.map +1 -1
- package/dist/api/process.d.ts +4 -2
- package/dist/api/process.d.ts.map +1 -1
- package/dist/api/process.js +21 -1
- package/dist/api/process.js.map +1 -1
- package/dist/api/status.d.ts.map +1 -1
- package/dist/api/status.js +19 -4
- package/dist/api/status.js.map +1 -1
- package/dist/api/upload.d.ts +2 -0
- package/dist/api/upload.d.ts.map +1 -1
- package/dist/api/upload.js +1 -1
- package/dist/api/upload.js.map +1 -1
- package/dist/auth/anonymous.d.ts +10 -0
- package/dist/auth/anonymous.d.ts.map +1 -0
- package/dist/auth/anonymous.js +37 -0
- package/dist/auth/anonymous.js.map +1 -0
- package/dist/auth/context.d.ts +13 -0
- package/dist/auth/context.d.ts.map +1 -0
- package/dist/auth/context.js +10 -0
- package/dist/auth/context.js.map +1 -0
- package/dist/auth/jwt.d.ts +7 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/jwt.js +35 -0
- package/dist/auth/jwt.js.map +1 -0
- package/dist/auth/resolver.d.ts +11 -0
- package/dist/auth/resolver.d.ts.map +1 -0
- package/dist/auth/resolver.js +35 -0
- package/dist/auth/resolver.js.map +1 -0
- package/dist/index.js +195 -155
- package/dist/index.js.map +1 -1
- package/dist/tools/login.js +1 -1
- package/dist/tools/login.js.map +1 -1
- package/dist/tools/optimize.d.ts +12 -2
- package/dist/tools/optimize.d.ts.map +1 -1
- package/dist/tools/optimize.js +95 -15
- package/dist/tools/optimize.js.map +1 -1
- package/dist/tools/status.d.ts.map +1 -1
- package/dist/tools/status.js +9 -6
- package/dist/tools/status.js.map +1 -1
- package/dist/transport/http.d.ts +8 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +151 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/x402/client.d.ts +26 -0
- package/dist/x402/client.d.ts.map +1 -0
- package/dist/x402/client.js +73 -0
- package/dist/x402/client.js.map +1 -0
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://modelcontextprotocol.io)
|
|
6
6
|
|
|
7
|
-
MCP server for [tinify.ai](https://tinify.ai) image optimization. AI-powered upscaling, resizing/cropping, compression, and SEO
|
|
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 | `
|
|
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` |
|
|
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
|
-
|
|
|
201
|
-
|
|
|
202
|
-
|
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
package/dist/api/auth.d.ts
CHANGED
|
@@ -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,
|
|
28
|
+
export declare function getAccountStatus(baseUrl: string, authHeaders: Record<string, string>): Promise<AccountStatus>;
|
|
29
29
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/api/auth.d.ts.map
CHANGED
|
@@ -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,
|
|
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,
|
|
29
|
-
const
|
|
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);
|
package/dist/api/auth.js.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/api/client.d.ts
CHANGED
|
@@ -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
|
package/dist/api/client.d.ts.map
CHANGED
|
@@ -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"}
|
package/dist/api/client.js
CHANGED
|
@@ -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
|
package/dist/api/client.js.map
CHANGED
|
@@ -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"}
|
package/dist/api/process.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export interface ProcessingSettings {
|
|
2
|
-
output_format?: "original" | "jpg" | "png" | "webp" | "avif";
|
|
3
|
-
output_upscale_factor?:
|
|
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":"
|
|
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"}
|
package/dist/api/process.js
CHANGED
|
@@ -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
|
-
|
|
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. ` +
|
package/dist/api/process.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/api/process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"process.js","sourceRoot":"","sources":["../../src/api/process.ts"],"names":[],"mappings":"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"}
|
package/dist/api/status.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/api/status.js
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
47
|
+
reject(new ApiError(`Processing timed out after ${timeoutSecs} seconds.`, 504));
|
|
33
48
|
});
|
|
34
49
|
});
|
|
35
50
|
}
|
package/dist/api/status.js.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/api/upload.d.ts
CHANGED
package/dist/api/upload.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/api/upload.js
CHANGED
|
@@ -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
|
}
|
package/dist/api/upload.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../src/api/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,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"}
|
package/dist/auth/jwt.js
ADDED
|
@@ -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"}
|