@tinify-ai/mcp-server 1.2.0 → 1.3.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 +59 -10
- package/dist/api/process.d.ts +2 -1
- 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/index.js +31 -8
- package/dist/index.js.map +1 -1
- package/dist/tools/optimize.d.ts +4 -1
- package/dist/tools/optimize.d.ts.map +1 -1
- package/dist/tools/optimize.js +65 -12
- package/dist/tools/optimize.js.map +1 -1
- package/dist/tools/status.d.ts.map +1 -1
- package/dist/tools/status.js +6 -0
- package/dist/tools/status.js.map +1 -1
- package/dist/utils/output.d.ts +1 -0
- package/dist/utils/output.d.ts.map +1 -1
- package/dist/utils/output.js +13 -0
- package/dist/utils/output.js.map +1 -1
- 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 +6 -2
package/README.md
CHANGED
|
@@ -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.
|
|
@@ -191,17 +237,18 @@ Alt text: Modern office workspace with laptop and coffee cup on wooden desk
|
|
|
191
237
|
|
|
192
238
|
## Supported Formats
|
|
193
239
|
|
|
194
|
-
| Format | Input | Output |
|
|
195
|
-
|
|
196
|
-
| JPG | Yes | Yes |
|
|
197
|
-
| PNG | Yes | Yes |
|
|
198
|
-
| WebP | Yes | Yes |
|
|
199
|
-
| AVIF | Yes | Yes |
|
|
200
|
-
|
|
|
201
|
-
|
|
|
202
|
-
|
|
|
240
|
+
| Format | Input | Output | Notes |
|
|
241
|
+
|--------|-------|--------|-------|
|
|
242
|
+
| JPG | Yes | Yes | |
|
|
243
|
+
| PNG | Yes | Yes | |
|
|
244
|
+
| WebP | Yes | Yes | |
|
|
245
|
+
| AVIF | Yes | Yes | |
|
|
246
|
+
| GIF | Yes | Yes | Animated GIFs preserved when output is GIF |
|
|
247
|
+
| HEIC/HEIF | Yes* | No | Auto-converted to JPG at upload |
|
|
248
|
+
| TIFF | Yes* | No | Auto-converted to JPG at upload |
|
|
249
|
+
| BMP | Yes* | No | Auto-converted to JPG at upload |
|
|
203
250
|
|
|
204
|
-
|
|
251
|
+
Tinify supports high-quality conversion between any input and output format combination. Converting an animated GIF to a non-GIF format (JPG, PNG, WebP, AVIF) preserves only the first frame.
|
|
205
252
|
|
|
206
253
|
Max file size: 50 MB.
|
|
207
254
|
|
|
@@ -284,6 +331,8 @@ Tools: optimize_image, login, logout, status, upgrade
|
|
|
284
331
|
- When both dimensions are set, use output_resize_behavior: "crop" for photos, "pad" for logos/icons.
|
|
285
332
|
- output_seo_tag_gen (default true) renames the file to an SEO slug and generates alt text + keywords.
|
|
286
333
|
- Set output_seo_tag_gen: false to save 1 credit when SEO metadata is not needed.
|
|
334
|
+
- GIF is supported for both input and output; animated GIFs stay animated when output_format is "gif".
|
|
335
|
+
- Converting an animated GIF to jpg/png/webp/avif preserves only the first frame.
|
|
287
336
|
- HEIC, TIFF, BMP inputs are auto-converted to JPG.
|
|
288
337
|
- For batch processing, call optimize_image once per file.
|
|
289
338
|
- If credits run out, use login to sign in or upgrade to open pricing.
|
package/dist/api/process.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export interface ProcessingSettings {
|
|
2
|
-
output_format?: "original" | "jpg" | "png" | "webp" | "avif";
|
|
2
|
+
output_format?: "original" | "jpg" | "png" | "webp" | "avif" | "gif";
|
|
3
3
|
output_upscale_factor?: number;
|
|
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
|
+
gif_frame_limit?: number;
|
|
9
10
|
}
|
|
10
11
|
interface ProcessParams {
|
|
11
12
|
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,CAAC;IACrE,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;IAC5B,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"}
|
package/dist/index.js
CHANGED
|
@@ -10,27 +10,28 @@ import { upgradeTool } from "./tools/upgrade.js";
|
|
|
10
10
|
import { formatErrorForMcp } from "./errors.js";
|
|
11
11
|
const server = new McpServer({
|
|
12
12
|
name: "tinify",
|
|
13
|
-
version: "1.
|
|
13
|
+
version: "1.3.0",
|
|
14
14
|
});
|
|
15
15
|
server.registerTool("optimize_image", {
|
|
16
16
|
title: "Optimize Image",
|
|
17
17
|
description: "Optimize an image: smart lossy compression (typically 60-80% size reduction), optional resize/upscale/format conversion, and AI-generated SEO metadata. " +
|
|
18
|
-
"Accepts absolute local file paths or remote URLs. Supported formats: JPG, PNG, WebP, AVIF, HEIC, TIFF, BMP (max 50 MB). " +
|
|
19
|
-
"Each call costs 3 credits + 1 if SEO tags enabled.
|
|
20
|
-
"
|
|
18
|
+
"Accepts absolute local file paths or remote URLs. Supported input formats: JPG, PNG, WebP, AVIF, GIF, HEIC, TIFF, BMP (max 50 MB). Supported output formats: JPG, PNG, WebP, AVIF, GIF. " +
|
|
19
|
+
"Each call costs 3 credits + 1 if SEO tags enabled. Animated GIFs are processed frame-by-frame (each frame optimized individually). " +
|
|
20
|
+
"Cost = frames × per-frame operations. Use confirm_gif_cost: true after reviewing the cost warning. " +
|
|
21
|
+
"Free tier: 20 credits/day, no signup. Log in with the login tool for more credits. Use status tool to check remaining credits before batch processing.",
|
|
21
22
|
inputSchema: {
|
|
22
23
|
input: z
|
|
23
24
|
.string()
|
|
24
|
-
.describe("Absolute local file path or remote URL of the image to optimize. Supported: JPG, PNG, WebP, AVIF, HEIC, TIFF, BMP (max 50 MB)."),
|
|
25
|
+
.describe("Absolute local file path or remote URL of the image to optimize. Supported inputs: JPG, PNG, WebP, AVIF, GIF (animated supported), HEIC, TIFF, BMP (max 50 MB). Tinify supports high-quality conversion between any input and output format."),
|
|
25
26
|
output_path: z
|
|
26
27
|
.string()
|
|
27
28
|
.optional()
|
|
28
29
|
.describe("Where to save. Accepts a file path (/tmp/out.webp) or directory ending in / (/tmp/images/). " +
|
|
29
30
|
"If omitted: saves next to original, named with SEO slug when SEO is enabled or .tinified suffix otherwise. URLs save to current working directory."),
|
|
30
31
|
output_format: z
|
|
31
|
-
.enum(["original", "
|
|
32
|
+
.enum(["original", "jpg", "png", "webp", "avif", "gif"])
|
|
32
33
|
.optional()
|
|
33
|
-
.describe("Output format. Defaults to 'original' (keep input format)."),
|
|
34
|
+
.describe("Output format. Defaults to 'original' (keep input format). Animated GIFs stay animated when output is 'gif'; converting to other formats preserves only the first frame."),
|
|
34
35
|
output_width_px: z
|
|
35
36
|
.number()
|
|
36
37
|
.int()
|
|
@@ -58,13 +59,28 @@ server.registerTool("optimize_image", {
|
|
|
58
59
|
.boolean()
|
|
59
60
|
.optional()
|
|
60
61
|
.describe("Generate SEO metadata (alt text, keywords, filename) and rename output file to SEO slug. Costs 1 extra credit. Default: true."),
|
|
62
|
+
confirm_gif_cost: z
|
|
63
|
+
.boolean()
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("Set to true to proceed with animated GIF processing after seeing cost warning. Required for animated GIFs to prevent unexpected credit consumption."),
|
|
66
|
+
gif_frame_limit: z
|
|
67
|
+
.number()
|
|
68
|
+
.int()
|
|
69
|
+
.min(1)
|
|
70
|
+
.max(100)
|
|
71
|
+
.optional()
|
|
72
|
+
.describe("Maximum frames to process for animated GIFs (1-100, default 100). Reduces cost by sampling fewer frames while preserving animation."),
|
|
73
|
+
_gif_temp_file_id: z
|
|
74
|
+
.string()
|
|
75
|
+
.optional()
|
|
76
|
+
.describe("Internal: temp file ID from a previous GIF cost warning. Skips re-upload."),
|
|
61
77
|
},
|
|
62
78
|
outputSchema: {
|
|
63
79
|
output_path: z.string().describe("Absolute path where the optimized file was saved"),
|
|
64
80
|
output_size_bytes: z.number().describe("File size of the optimized image in bytes"),
|
|
65
81
|
output_width_px: z.number().nullable().describe("Width of the output image in pixels"),
|
|
66
82
|
output_height_px: z.number().nullable().describe("Height of the output image in pixels"),
|
|
67
|
-
output_format: z.string().nullable().describe("Output format: jpg, png, webp, or
|
|
83
|
+
output_format: z.string().nullable().describe("Output format: jpg, png, webp, avif, or gif"),
|
|
68
84
|
compression_ratio: z.number().nullable().describe("Output-to-input size ratio, e.g. 0.35 means 65% smaller"),
|
|
69
85
|
seo_alt_text: z.string().nullable().describe("AI-generated image alt text for accessibility and SEO"),
|
|
70
86
|
seo_keywords: z.array(z.string()).nullable().describe("AI-generated keywords describing the image"),
|
|
@@ -81,7 +97,14 @@ server.registerTool("optimize_image", {
|
|
|
81
97
|
output_upscale_factor: params.output_upscale_factor,
|
|
82
98
|
output_resize_behavior: params.output_resize_behavior,
|
|
83
99
|
output_seo_tag_gen: params.output_seo_tag_gen,
|
|
100
|
+
confirm_gif_cost: params.confirm_gif_cost,
|
|
101
|
+
gif_frame_limit: params.gif_frame_limit,
|
|
102
|
+
_gif_temp_file_id: params._gif_temp_file_id,
|
|
84
103
|
});
|
|
104
|
+
// Handle GIF cost warning (not a real result)
|
|
105
|
+
if (result._gif_warning) {
|
|
106
|
+
return { content: [{ type: "text", text: result._gif_warning }] };
|
|
107
|
+
}
|
|
85
108
|
const summary = [
|
|
86
109
|
`Optimized: ${result.output_path}`,
|
|
87
110
|
`Size: ${(result.output_size_bytes / 1024).toFixed(1)} KB`,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,CAAC,YAAY,CACjB,gBAAgB,EAChB;IACE,KAAK,EAAE,gBAAgB;IACvB,WAAW,EACT,0JAA0J;QAC1J,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/optimize.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
export interface OptimizeImageParams {
|
|
2
2
|
input: string;
|
|
3
3
|
output_path?: string;
|
|
4
|
-
output_format?: "original" | "jpg" | "png" | "webp" | "avif";
|
|
4
|
+
output_format?: "original" | "jpg" | "png" | "webp" | "avif" | "gif";
|
|
5
5
|
output_width_px?: number;
|
|
6
6
|
output_height_px?: number;
|
|
7
7
|
output_upscale_factor?: number;
|
|
8
8
|
output_resize_behavior?: "pad" | "crop";
|
|
9
9
|
output_seo_tag_gen?: boolean;
|
|
10
|
+
confirm_gif_cost?: boolean;
|
|
11
|
+
gif_frame_limit?: number;
|
|
12
|
+
_gif_temp_file_id?: string;
|
|
10
13
|
baseUrl?: string;
|
|
11
14
|
timeoutMs?: number;
|
|
12
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize.d.ts","sourceRoot":"","sources":["../../src/tools/optimize.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"optimize.d.ts","sourceRoot":"","sources":["../../src/tools/optimize.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,UAAU,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IACrE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sBAAsB,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC9B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,mBAAmB,CAAC,CAoJ9B"}
|
package/dist/tools/optimize.js
CHANGED
|
@@ -5,7 +5,7 @@ import { triggerProcessing } from "../api/process.js";
|
|
|
5
5
|
import { waitForCompletion } from "../api/status.js";
|
|
6
6
|
import { downloadFile } from "../api/download.js";
|
|
7
7
|
import { resolveInput } from "../utils/input.js";
|
|
8
|
-
import {
|
|
8
|
+
import { resolveUniqueOutputPath } from "../utils/output.js";
|
|
9
9
|
import { SessionManager } from "../session/manager.js";
|
|
10
10
|
import { DEFAULT_BASE_URL } from "../api/client.js";
|
|
11
11
|
export async function optimizeImage(params) {
|
|
@@ -13,17 +13,67 @@ export async function optimizeImage(params) {
|
|
|
13
13
|
const sessionManager = new SessionManager();
|
|
14
14
|
// 1. Resolve input (read file or fetch URL)
|
|
15
15
|
const input = await resolveInput(params.input);
|
|
16
|
-
// 2. Upload to backend
|
|
16
|
+
// 2. Upload to backend (skip if reusing from GIF cost warning)
|
|
17
17
|
const authHeaders = sessionManager.getAuthHeaders();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
let uploadResult;
|
|
19
|
+
if (params._gif_temp_file_id && params.confirm_gif_cost) {
|
|
20
|
+
// Reuse the upload from a previous GIF cost warning — no re-upload needed
|
|
21
|
+
uploadResult = {
|
|
22
|
+
temp_file_id: params._gif_temp_file_id,
|
|
23
|
+
original_filename: input.filename,
|
|
24
|
+
file_size: input.buffer.length,
|
|
25
|
+
mime_type: "image/gif",
|
|
26
|
+
session_token: null,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
uploadResult = await uploadFile({
|
|
31
|
+
baseUrl,
|
|
32
|
+
fileBuffer: input.buffer,
|
|
33
|
+
filename: input.filename,
|
|
34
|
+
authHeaders,
|
|
35
|
+
});
|
|
36
|
+
// Persist new session token if returned (for guest sessions)
|
|
37
|
+
if (uploadResult.session_token) {
|
|
38
|
+
sessionManager.saveToken(uploadResult.session_token);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Check if animated GIF needs cost confirmation
|
|
42
|
+
const isAnimatedGif = uploadResult.gif_frame_count && uploadResult.gif_frame_count > 1;
|
|
43
|
+
if (isAnimatedGif && !params.confirm_gif_cost) {
|
|
44
|
+
const frameLimit = params.gif_frame_limit ?? 100;
|
|
45
|
+
const framesToProcess = Math.min(uploadResult.gif_frame_count, frameLimit);
|
|
46
|
+
let perFrameCost = 3; // compress always runs
|
|
47
|
+
if (params.output_width_px || params.output_height_px)
|
|
48
|
+
perFrameCost += 1;
|
|
49
|
+
if (params.output_upscale_factor)
|
|
50
|
+
perFrameCost += 2;
|
|
51
|
+
const tagCost = params.output_seo_tag_gen !== false ? 1 : 0;
|
|
52
|
+
const totalCost = framesToProcess * perFrameCost + tagCost;
|
|
53
|
+
const warning = [
|
|
54
|
+
`Animated GIF detected: ${input.filename}`,
|
|
55
|
+
` ${uploadResult.gif_frame_count} frames, ${uploadResult.gif_fps ?? "?"} fps`,
|
|
56
|
+
` ${framesToProcess} frames × ${perFrameCost} credits = ${totalCost} credits`,
|
|
57
|
+
``,
|
|
58
|
+
` Animated GIFs are processed frame-by-frame for highest quality.`,
|
|
59
|
+
` To proceed, call optimize_image again with:`,
|
|
60
|
+
` confirm_gif_cost: true`,
|
|
61
|
+
` _gif_temp_file_id: "${uploadResult.temp_file_id}"`,
|
|
62
|
+
` To reduce cost, set gif_frame_limit (1-100, default 100).`,
|
|
63
|
+
].join("\n");
|
|
64
|
+
return {
|
|
65
|
+
output_path: "",
|
|
66
|
+
output_size_bytes: 0,
|
|
67
|
+
output_width_px: null,
|
|
68
|
+
output_height_px: null,
|
|
69
|
+
output_format: null,
|
|
70
|
+
compression_ratio: null,
|
|
71
|
+
seo_alt_text: null,
|
|
72
|
+
seo_keywords: null,
|
|
73
|
+
seo_filename: null,
|
|
74
|
+
_gif_warning: warning,
|
|
75
|
+
_gif_temp_file_id: uploadResult.temp_file_id,
|
|
76
|
+
};
|
|
27
77
|
}
|
|
28
78
|
// 3. Build settings (smart defaults: compress always, SEO tags on)
|
|
29
79
|
const settings = {
|
|
@@ -44,6 +94,9 @@ export async function optimizeImage(params) {
|
|
|
44
94
|
if (params.output_width_px !== undefined || params.output_height_px !== undefined) {
|
|
45
95
|
settings.output_resize_behavior = params.output_resize_behavior ?? "pad";
|
|
46
96
|
}
|
|
97
|
+
if (params.gif_frame_limit !== undefined) {
|
|
98
|
+
settings.gif_frame_limit = params.gif_frame_limit;
|
|
99
|
+
}
|
|
47
100
|
// 4. Trigger processing
|
|
48
101
|
const processResult = await triggerProcessing({
|
|
49
102
|
baseUrl,
|
|
@@ -64,7 +117,7 @@ export async function optimizeImage(params) {
|
|
|
64
117
|
// 6. Download processed file
|
|
65
118
|
const downloadResult = await downloadFile({ baseUrl, jobId: job.id });
|
|
66
119
|
// 7. Resolve output path and save
|
|
67
|
-
const outputPath =
|
|
120
|
+
const outputPath = resolveUniqueOutputPath({
|
|
68
121
|
inputPath: params.input,
|
|
69
122
|
isUrl: input.isUrl,
|
|
70
123
|
filename: input.filename,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../src/tools/optimize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAA2B,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../src/tools/optimize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAA2B,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AA+BpD,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAA2B;IAE3B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACnD,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAE5C,4CAA4C;IAC5C,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE/C,+DAA+D;IAC/D,MAAM,WAAW,GAAG,cAAc,CAAC,cAAc,EAAE,CAAC;IACpD,IAAI,YAAoD,CAAC;IAEzD,IAAI,MAAM,CAAC,iBAAiB,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;QACxD,0EAA0E;QAC1E,YAAY,GAAG;YACb,YAAY,EAAE,MAAM,CAAC,iBAAiB;YACtC,iBAAiB,EAAE,KAAK,CAAC,QAAQ;YACjC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;YAC9B,SAAS,EAAE,WAAW;YACtB,aAAa,EAAE,IAAI;SACpB,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,MAAM,UAAU,CAAC;YAC9B,OAAO;YACP,UAAU,EAAE,KAAK,CAAC,MAAM;YACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,WAAW;SACZ,CAAC,CAAC;QAEH,6DAA6D;QAC7D,IAAI,YAAY,CAAC,aAAa,EAAE,CAAC;YAC/B,cAAc,CAAC,SAAS,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,gDAAgD;IAChD,MAAM,aAAa,GAAG,YAAY,CAAC,eAAe,IAAI,YAAY,CAAC,eAAe,GAAG,CAAC,CAAC;IACvF,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC9C,MAAM,UAAU,GAAG,MAAM,CAAC,eAAe,IAAI,GAAG,CAAC;QACjD,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,eAAgB,EAAE,UAAU,CAAC,CAAC;QAC5E,IAAI,YAAY,GAAG,CAAC,CAAC,CAAC,uBAAuB;QAC7C,IAAI,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,gBAAgB;YAAE,YAAY,IAAI,CAAC,CAAC;QACzE,IAAI,MAAM,CAAC,qBAAqB;YAAE,YAAY,IAAI,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,MAAM,CAAC,kBAAkB,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,eAAe,GAAG,YAAY,GAAG,OAAO,CAAC;QAE3D,MAAM,OAAO,GAAG;YACd,0BAA0B,KAAK,CAAC,QAAQ,EAAE;YAC1C,KAAK,YAAY,CAAC,eAAe,YAAY,YAAY,CAAC,OAAO,IAAI,GAAG,MAAM;YAC9E,KAAK,eAAe,aAAa,YAAY,cAAc,SAAS,UAAU;YAC9E,EAAE;YACF,mEAAmE;YACnE,+CAA+C;YAC/C,4BAA4B;YAC5B,2BAA2B,YAAY,CAAC,YAAY,GAAG;YACvD,6DAA6D;SAC9D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEb,OAAO;YACL,WAAW,EAAE,EAAE;YACf,iBAAiB,EAAE,CAAC;YACpB,eAAe,EAAE,IAAI;YACrB,gBAAgB,EAAE,IAAI;YACtB,aAAa,EAAE,IAAI;YACnB,iBAAiB,EAAE,IAAI;YACvB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,IAAI;YAClB,YAAY,EAAE,OAAO;YACrB,iBAAiB,EAAE,YAAY,CAAC,YAAY;SAC7C,CAAC;IACJ,CAAC;IAED,mEAAmE;IACnE,MAAM,QAAQ,GAAuB;QACnC,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,UAAU;QACjD,kBAAkB,EAAE,MAAM,CAAC,kBAAkB,IAAI,IAAI;QACrD,iBAAiB,EAAE,KAAK;KACzB,CAAC;IACF,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QACzC,QAAQ,CAAC,YAAY,GAAG,MAAM,CAAC,eAAe,CAAC;IACjD,CAAC;IACD,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAC1C,QAAQ,CAAC,aAAa,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACnD,CAAC;IACD,IAAI,MAAM,CAAC,qBAAqB,KAAK,SAAS,EAAE,CAAC;QAC/C,QAAQ,CAAC,qBAAqB,GAAG,MAAM,CAAC,qBAAqB,CAAC;IAChE,CAAC;IACD,2EAA2E;IAC3E,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,MAAM,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QAClF,QAAQ,CAAC,sBAAsB,GAAG,MAAM,CAAC,sBAAsB,IAAI,KAAK,CAAC;IAC3E,CAAC;IACD,IAAI,MAAM,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QACzC,QAAQ,CAAC,eAAe,GAAG,MAAM,CAAC,eAAe,CAAC;IACpD,CAAC;IAED,wBAAwB;IACxB,MAAM,aAAa,GAAG,MAAM,iBAAiB,CAAC;QAC5C,OAAO;QACP,WAAW,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC;QACxC,QAAQ;QACR,WAAW;KACZ,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,iCAAiC;IACjC,MAAM,YAAY,GAAG,MAAM,iBAAiB,CAAC;QAC3C,OAAO;QACP,KAAK,EAAE,GAAG,CAAC,EAAE;QACb,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,KAAK;KACrC,CAAC,CAAC;IAEH,6BAA6B;IAC7B,MAAM,cAAc,GAAG,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAEtE,kCAAkC;IAClC,MAAM,UAAU,GAAG,uBAAuB,CAAC;QACzC,SAAS,EAAE,MAAM,CAAC,KAAK;QACvB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,UAAU,EAAE,MAAM,CAAC,WAAW;QAC9B,YAAY,EACV,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa,KAAK,UAAU;YACzD,CAAC,CAAC,MAAM,CAAC,aAAa;YACtB,CAAC,CAAC,YAAY,CAAC,gBAAgB,IAAI,SAAS;QAChD,WAAW,EACT,MAAM,CAAC,kBAAkB,KAAK,KAAK;YACjC,CAAC,CAAC,CAAC,YAAY,CAAC,YAAY,IAAI,SAAS,CAAC;YAC1C,CAAC,CAAC,SAAS;KAChB,CAAC,CAAC;IAEH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAEpD,OAAO;QACL,WAAW,EAAE,UAAU;QACvB,iBAAiB,EAAE,YAAY,CAAC,cAAc,IAAI,cAAc,CAAC,MAAM,CAAC,MAAM;QAC9E,eAAe,EAAE,YAAY,CAAC,eAAe,IAAI,IAAI;QACrD,gBAAgB,EAAE,YAAY,CAAC,gBAAgB,IAAI,IAAI;QACvD,aAAa,EAAE,YAAY,CAAC,gBAAgB,IAAI,IAAI;QACpD,iBAAiB,EAAE,YAAY,CAAC,2BAA2B,IAAI,IAAI;QACnE,YAAY,EAAE,YAAY,CAAC,YAAY,IAAI,IAAI;QAC/C,YAAY,EAAE,YAAY,CAAC,YAAY,IAAI,IAAI;QAC/C,YAAY,EAAE,YAAY,CAAC,YAAY,IAAI,IAAI;KAChD,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CA+BlD"}
|
package/dist/tools/status.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { SessionManager } from "../session/manager.js";
|
|
2
2
|
import { DEFAULT_BASE_URL } from "../api/client.js";
|
|
3
3
|
import { getAccountStatus } from "../api/auth.js";
|
|
4
|
+
import { isX402Configured, getWalletAddress } from "../x402/client.js";
|
|
4
5
|
export async function statusTool() {
|
|
5
6
|
const sessionManager = new SessionManager();
|
|
6
7
|
const baseUrl = process.env.TINIFY_API_URL ?? DEFAULT_BASE_URL;
|
|
7
8
|
const mcpToken = sessionManager.getMcpToken();
|
|
8
9
|
const sessionToken = sessionManager.getToken();
|
|
9
10
|
const status = await getAccountStatus(baseUrl, mcpToken, sessionToken);
|
|
11
|
+
const x402Status = isX402Configured()
|
|
12
|
+
? `Pay As You Go: Enabled (wallet: ${await getWalletAddress()})`
|
|
13
|
+
: "Pay As You Go: Not configured (set TINIFY_X402_PRIVATE_KEY)";
|
|
10
14
|
if (status.logged_in) {
|
|
11
15
|
const resetInfo = status.credits_reset_at
|
|
12
16
|
? `Resets: ${formatResetTime(status.credits_reset_at)}`
|
|
@@ -15,11 +19,13 @@ export async function statusTool() {
|
|
|
15
19
|
`Logged in as ${status.email} (${capitalize(status.tier)} tier)`,
|
|
16
20
|
`Credits: ${status.credits_remaining.toLocaleString()} of ${status.credits_limit.toLocaleString()} remaining`,
|
|
17
21
|
resetInfo,
|
|
22
|
+
x402Status,
|
|
18
23
|
].filter(Boolean).join("\n");
|
|
19
24
|
}
|
|
20
25
|
return [
|
|
21
26
|
"Not logged in. Using guest session.",
|
|
22
27
|
`Credits: ${status.credits_remaining} of ${status.credits_limit} remaining (resets daily)`,
|
|
28
|
+
x402Status,
|
|
23
29
|
"Tip: Log in for more credits \u2014 free accounts get 50/day.",
|
|
24
30
|
].join("\n");
|
|
25
31
|
}
|
package/dist/tools/status.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/tools/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAEvE,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,cAAc,GAAG,IAAI,cAAc,EAAE,CAAC;IAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,gBAAgB,CAAC;IAE/D,MAAM,QAAQ,GAAG,cAAc,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,YAAY,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;IAE/C,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;IAEvE,MAAM,UAAU,GAAG,gBAAgB,EAAE;QACnC,CAAC,CAAC,mCAAmC,MAAM,gBAAgB,EAAE,GAAG;QAChE,CAAC,CAAC,6DAA6D,CAAC;IAElE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,MAAM,CAAC,gBAAgB;YACvC,CAAC,CAAC,WAAW,eAAe,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE;YACvD,CAAC,CAAC,EAAE,CAAC;QACP,OAAO;YACL,gBAAgB,MAAM,CAAC,KAAK,KAAK,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ;YAChE,YAAY,MAAM,CAAC,iBAAiB,CAAC,cAAc,EAAE,OAAO,MAAM,CAAC,aAAa,CAAC,cAAc,EAAE,YAAY;YAC7G,SAAS;YACT,UAAU;SACX,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO;QACL,qCAAqC;QACrC,YAAY,MAAM,CAAC,iBAAiB,OAAO,MAAM,CAAC,aAAa,2BAA2B;QAC1F,UAAU;QACV,+DAA+D;KAChE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB;IACxC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAClC,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,OAAO;QACrB,KAAK,EAAE,SAAS;QAChB,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;KAChB,CAAC,CAAC;AACL,CAAC"}
|
package/dist/utils/output.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"AAGA,UAAU,gBAAgB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AA4BD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAoBlE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAWxE"}
|
package/dist/utils/output.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
1
2
|
import * as path from "node:path";
|
|
2
3
|
function getTinifiedFilename(filename, outputFormat, seoFilename) {
|
|
3
4
|
const ext = path.extname(filename);
|
|
@@ -33,4 +34,16 @@ export function resolveOutputPath(params) {
|
|
|
33
34
|
const inputDir = path.dirname(path.resolve(inputPath));
|
|
34
35
|
return path.join(inputDir, tinifiedName);
|
|
35
36
|
}
|
|
37
|
+
export function resolveUniqueOutputPath(params) {
|
|
38
|
+
let outputPath = resolveOutputPath(params);
|
|
39
|
+
if (!fs.existsSync(outputPath))
|
|
40
|
+
return outputPath;
|
|
41
|
+
const ext = path.extname(outputPath);
|
|
42
|
+
const base = outputPath.slice(0, -ext.length || undefined);
|
|
43
|
+
let counter = 2;
|
|
44
|
+
while (fs.existsSync(`${base}-${counter}${ext}`)) {
|
|
45
|
+
counter++;
|
|
46
|
+
}
|
|
47
|
+
return `${base}-${counter}${ext}`;
|
|
48
|
+
}
|
|
36
49
|
//# sourceMappingURL=output.js.map
|
package/dist/utils/output.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAYlC,SAAS,mBAAmB,CAC1B,QAAgB,EAChB,YAAgC,EAChC,WAAoB;IAEpB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC,YAAY,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,GAAG,WAAW,GAAG,MAAM,EAAE,CAAC;IACnC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC1C,OAAO,GAAG,IAAI,YAAY,MAAM,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,eAAe,CAAC,CAAS;IAChC,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAwB;IACxD,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;IAE1F,IAAI,UAAU,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAE9E,IAAI,UAAU,IAAI,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,OAAO,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC"}
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/utils/output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAYlC,SAAS,mBAAmB,CAC1B,QAAgB,EAChB,YAAgC,EAChC,WAAoB;IAEpB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEnC,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC,YAAY,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;QACjD,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,GAAG,WAAW,GAAG,MAAM,EAAE,CAAC;IACnC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC1C,OAAO,GAAG,IAAI,YAAY,MAAM,EAAE,CAAC;AACrC,CAAC;AAED,SAAS,eAAe,CAAC,CAAS;IAChC,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAwB;IACxD,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;IAE1F,IAAI,UAAU,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAE9E,IAAI,UAAU,IAAI,eAAe,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,OAAO,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC1C,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IACvD,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAwB;IAC9D,IAAI,UAAU,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,UAAU,CAAC;IAElD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC;IAC3D,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,OAAO,EAAE,CAAC,UAAU,CAAC,GAAG,IAAI,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC;QACjD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,GAAG,IAAI,IAAI,OAAO,GAAG,GAAG,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 payment client for MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Wraps fetch with x402 payment handling. When the backend returns 402,
|
|
5
|
+
* automatically signs a USDC payment on Base and retries the request.
|
|
6
|
+
*
|
|
7
|
+
* Wallet private key is read from TINIFY_X402_PRIVATE_KEY env var.
|
|
8
|
+
* The key never leaves this process.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Check if x402 payments are configured (private key env var is set).
|
|
12
|
+
*/
|
|
13
|
+
export declare function isX402Configured(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Get the wallet address (public, safe to display).
|
|
16
|
+
* Returns null if no private key is configured or if derivation fails.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getWalletAddress(): Promise<string | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Get a fetch function wrapped with x402 payment handling.
|
|
21
|
+
*
|
|
22
|
+
* On first call, initializes the signer from TINIFY_X402_PRIVATE_KEY.
|
|
23
|
+
* Returns null if no private key is configured.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getX402Fetch(): Promise<typeof fetch | null>;
|
|
26
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/x402/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgB/D;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,OAAO,KAAK,GAAG,IAAI,CAAC,CAsCjE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 payment client for MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Wraps fetch with x402 payment handling. When the backend returns 402,
|
|
5
|
+
* automatically signs a USDC payment on Base and retries the request.
|
|
6
|
+
*
|
|
7
|
+
* Wallet private key is read from TINIFY_X402_PRIVATE_KEY env var.
|
|
8
|
+
* The key never leaves this process.
|
|
9
|
+
*/
|
|
10
|
+
let _wrappedFetch = null;
|
|
11
|
+
let _walletAddress = null;
|
|
12
|
+
/**
|
|
13
|
+
* Check if x402 payments are configured (private key env var is set).
|
|
14
|
+
*/
|
|
15
|
+
export function isX402Configured() {
|
|
16
|
+
return !!process.env.TINIFY_X402_PRIVATE_KEY;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get the wallet address (public, safe to display).
|
|
20
|
+
* Returns null if no private key is configured or if derivation fails.
|
|
21
|
+
*/
|
|
22
|
+
export async function getWalletAddress() {
|
|
23
|
+
if (!process.env.TINIFY_X402_PRIVATE_KEY)
|
|
24
|
+
return null;
|
|
25
|
+
if (!_walletAddress) {
|
|
26
|
+
try {
|
|
27
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
28
|
+
const account = privateKeyToAccount(process.env.TINIFY_X402_PRIVATE_KEY);
|
|
29
|
+
_walletAddress = account.address;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return _walletAddress;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get a fetch function wrapped with x402 payment handling.
|
|
39
|
+
*
|
|
40
|
+
* On first call, initializes the signer from TINIFY_X402_PRIVATE_KEY.
|
|
41
|
+
* Returns null if no private key is configured.
|
|
42
|
+
*/
|
|
43
|
+
export async function getX402Fetch() {
|
|
44
|
+
if (!process.env.TINIFY_X402_PRIVATE_KEY)
|
|
45
|
+
return null;
|
|
46
|
+
if (!_wrappedFetch) {
|
|
47
|
+
try {
|
|
48
|
+
const { wrapFetchWithPayment, x402Client } = await import("@x402/fetch");
|
|
49
|
+
const { registerExactEvmScheme } = await import("@x402/evm/exact/client");
|
|
50
|
+
const { toClientEvmSigner } = await import("@x402/evm");
|
|
51
|
+
const { privateKeyToAccount } = await import("viem/accounts");
|
|
52
|
+
const { createPublicClient, http } = await import("viem");
|
|
53
|
+
const { base } = await import("viem/chains");
|
|
54
|
+
const account = privateKeyToAccount(process.env.TINIFY_X402_PRIVATE_KEY);
|
|
55
|
+
// Create a public client for readContract capability
|
|
56
|
+
const publicClient = createPublicClient({
|
|
57
|
+
chain: base,
|
|
58
|
+
transport: http(),
|
|
59
|
+
});
|
|
60
|
+
// Compose a full ClientEvmSigner with readContract from publicClient
|
|
61
|
+
const signer = toClientEvmSigner(account, publicClient);
|
|
62
|
+
const client = new x402Client();
|
|
63
|
+
registerExactEvmScheme(client, { signer });
|
|
64
|
+
_wrappedFetch = wrapFetchWithPayment(fetch, client);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.error("Failed to initialize x402 client:", error);
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return _wrappedFetch;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/x402/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,IAAI,aAAa,GAAwB,IAAI,CAAC;AAC9C,IAAI,cAAc,GAAkB,IAAI,CAAC;AAEzC;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB;QAAE,OAAO,IAAI,CAAC;IAEtD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;YAC9D,MAAM,OAAO,GAAG,mBAAmB,CACjC,OAAO,CAAC,GAAG,CAAC,uBAAwC,CACrD,CAAC;YACF,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,cAAc,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB;QAAE,OAAO,IAAI,CAAC;IAEtD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,EAAE,oBAAoB,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;YACzE,MAAM,EAAE,sBAAsB,EAAE,GAAG,MAAM,MAAM,CAC7C,wBAAwB,CACzB,CAAC;YACF,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;YACxD,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;YAC9D,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAC;YAE7C,MAAM,OAAO,GAAG,mBAAmB,CACjC,OAAO,CAAC,GAAG,CAAC,uBAAwC,CACrD,CAAC;YAEF,qDAAqD;YACrD,MAAM,YAAY,GAAG,kBAAkB,CAAC;gBACtC,KAAK,EAAE,IAAI;gBACX,SAAS,EAAE,IAAI,EAAE;aAClB,CAAC,CAAC;YAEH,qEAAqE;YACrE,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YAExD,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;YAChC,sBAAsB,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAE3C,aAAa,GAAG,oBAAoB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,aAAa,CAAC;AACvB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinify-ai/mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "MCP server for Tinify image optimization — one tool, max optimization",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"claude",
|
|
37
37
|
"tinify"
|
|
38
38
|
],
|
|
39
|
+
"mcpName": "io.github.onepunchtechnology/tinify-ai",
|
|
39
40
|
"license": "MIT",
|
|
40
41
|
"repository": {
|
|
41
42
|
"type": "git",
|
|
@@ -47,7 +48,10 @@
|
|
|
47
48
|
"dependencies": {
|
|
48
49
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
49
50
|
"eventsource": "^3.0.6",
|
|
50
|
-
"zod": "^3.25.0"
|
|
51
|
+
"zod": "^3.25.0",
|
|
52
|
+
"@x402/fetch": "^2.6.0",
|
|
53
|
+
"@x402/evm": "^2.6.0",
|
|
54
|
+
"viem": "^2.0.0"
|
|
51
55
|
},
|
|
52
56
|
"devDependencies": {
|
|
53
57
|
"@types/node": "^22.0.0",
|