@tinify-ai/mcp-server 1.2.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +95 -17
  2. package/dist/api/auth.d.ts +1 -1
  3. package/dist/api/auth.d.ts.map +1 -1
  4. package/dist/api/auth.js +2 -9
  5. package/dist/api/auth.js.map +1 -1
  6. package/dist/api/client.d.ts +6 -0
  7. package/dist/api/client.d.ts.map +1 -1
  8. package/dist/api/client.js +15 -0
  9. package/dist/api/client.js.map +1 -1
  10. package/dist/api/process.d.ts +4 -2
  11. package/dist/api/process.d.ts.map +1 -1
  12. package/dist/api/process.js +21 -1
  13. package/dist/api/process.js.map +1 -1
  14. package/dist/api/status.d.ts.map +1 -1
  15. package/dist/api/status.js +19 -4
  16. package/dist/api/status.js.map +1 -1
  17. package/dist/api/upload.d.ts +2 -0
  18. package/dist/api/upload.d.ts.map +1 -1
  19. package/dist/api/upload.js +1 -1
  20. package/dist/api/upload.js.map +1 -1
  21. package/dist/auth/anonymous.d.ts +10 -0
  22. package/dist/auth/anonymous.d.ts.map +1 -0
  23. package/dist/auth/anonymous.js +37 -0
  24. package/dist/auth/anonymous.js.map +1 -0
  25. package/dist/auth/context.d.ts +13 -0
  26. package/dist/auth/context.d.ts.map +1 -0
  27. package/dist/auth/context.js +10 -0
  28. package/dist/auth/context.js.map +1 -0
  29. package/dist/auth/jwt.d.ts +7 -0
  30. package/dist/auth/jwt.d.ts.map +1 -0
  31. package/dist/auth/jwt.js +35 -0
  32. package/dist/auth/jwt.js.map +1 -0
  33. package/dist/auth/resolver.d.ts +11 -0
  34. package/dist/auth/resolver.d.ts.map +1 -0
  35. package/dist/auth/resolver.js +35 -0
  36. package/dist/auth/resolver.js.map +1 -0
  37. package/dist/index.js +195 -155
  38. package/dist/index.js.map +1 -1
  39. package/dist/tools/login.js +1 -1
  40. package/dist/tools/login.js.map +1 -1
  41. package/dist/tools/optimize.d.ts +12 -2
  42. package/dist/tools/optimize.d.ts.map +1 -1
  43. package/dist/tools/optimize.js +95 -15
  44. package/dist/tools/optimize.js.map +1 -1
  45. package/dist/tools/status.d.ts.map +1 -1
  46. package/dist/tools/status.js +9 -6
  47. package/dist/tools/status.js.map +1 -1
  48. package/dist/transport/http.d.ts +8 -0
  49. package/dist/transport/http.d.ts.map +1 -0
  50. package/dist/transport/http.js +151 -0
  51. package/dist/transport/http.js.map +1 -0
  52. package/dist/x402/client.d.ts +26 -0
  53. package/dist/x402/client.d.ts.map +1 -0
  54. package/dist/x402/client.js +73 -0
  55. package/dist/x402/client.js.map +1 -0
  56. package/package.json +10 -1
@@ -0,0 +1,35 @@
1
+ import { verifySupabaseJwt } from "./jwt.js";
2
+ import { AnonymousSessionStore } from "./anonymous.js";
3
+ // Module-level store — shared across all requests in this process.
4
+ const anonStore = new AnonymousSessionStore();
5
+ /**
6
+ * Given an Authorization header value and session ID from an HTTP request,
7
+ * returns the auth headers to forward to api.tinify.ai.
8
+ *
9
+ * Priority:
10
+ * 1. Bearer mcp_... → pass through as-is (existing mcp_tokens)
11
+ * 2. Bearer eyJ... → validate Supabase JWT → pass through if valid
12
+ * 3. No/invalid auth → anonymous Supabase session JWT
13
+ */
14
+ export async function resolveAuthHeaders(authorizationHeader, sessionId) {
15
+ if (authorizationHeader) {
16
+ const token = authorizationHeader.replace(/^Bearer\s+/i, "");
17
+ // mcp_ tokens: forward as-is, no validation needed here
18
+ if (token.startsWith("mcp_")) {
19
+ return { Authorization: `Bearer ${token}` };
20
+ }
21
+ // Supabase JWT: validate, then forward
22
+ if (token.startsWith("eyJ")) {
23
+ const payload = await verifySupabaseJwt(token);
24
+ if (payload)
25
+ return { Authorization: `Bearer ${token}` };
26
+ // Invalid JWT — fall through to anonymous
27
+ }
28
+ }
29
+ // No auth or invalid JWT — create/reuse anonymous session
30
+ const anonJwt = await anonStore.getOrCreate(sessionId);
31
+ if (!anonJwt)
32
+ return {};
33
+ return { Authorization: `Bearer ${anonJwt}` };
34
+ }
35
+ //# sourceMappingURL=resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/auth/resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,mEAAmE;AACnE,MAAM,SAAS,GAAG,IAAI,qBAAqB,EAAE,CAAC;AAE9C;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,mBAAkC,EAClC,SAAiB;IAEjB,IAAI,mBAAmB,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QAE7D,wDAAwD;QACxD,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;QAC9C,CAAC;QAED,uCAAuC;QACvC,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAC/C,IAAI,OAAO;gBAAE,OAAO,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,CAAC;YACzD,0CAA0C;QAC5C,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,OAAO,EAAE,aAAa,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC;AAChD,CAAC"}
package/dist/index.js CHANGED
@@ -8,161 +8,201 @@ import { logoutTool } from "./tools/logout.js";
8
8
  import { statusTool } from "./tools/status.js";
9
9
  import { upgradeTool } from "./tools/upgrade.js";
10
10
  import { formatErrorForMcp } from "./errors.js";
11
- const server = new McpServer({
12
- name: "tinify",
13
- version: "1.2.0",
14
- });
15
- server.registerTool("optimize_image", {
16
- title: "Optimize Image",
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. Free tier: 20 credits/day, no signup. " +
20
- "Log in with the login tool for more credits. Use status tool to check remaining credits before batch processing.",
21
- inputSchema: {
22
- input: z
23
- .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
- output_path: z
26
- .string()
27
- .optional()
28
- .describe("Where to save. Accepts a file path (/tmp/out.webp) or directory ending in / (/tmp/images/). " +
29
- "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
- output_format: z
31
- .enum(["original", "jpeg", "png", "webp"])
32
- .optional()
33
- .describe("Output format. Defaults to 'original' (keep input format)."),
34
- output_width_px: z
35
- .number()
36
- .int()
37
- .positive()
38
- .optional()
39
- .describe("Target width in pixels. Set only width for proportional resize. Set both width and height for exact output dimensions (see output_resize_behavior)."),
40
- output_height_px: z
41
- .number()
42
- .int()
43
- .positive()
44
- .optional()
45
- .describe("Target height in pixels. Set only height for proportional resize. Set both width and height for exact output dimensions (see output_resize_behavior)."),
46
- output_upscale_factor: z
47
- .number()
48
- .min(0.1)
49
- .max(10)
50
- .optional()
51
- .describe("Upscale factor (e.g., 2.0 for 2x, 4.0 for 4x). Triggers AI upscaling."),
52
- output_resize_behavior: z
53
- .enum(["pad", "crop"])
54
- .optional()
55
- .describe("When both width and height are set and aspect ratio differs: " +
56
- "'pad' adds white padding (default), 'crop' smart-crops to fill exact dimensions"),
57
- output_seo_tag_gen: z
58
- .boolean()
59
- .optional()
60
- .describe("Generate SEO metadata (alt text, keywords, filename) and rename output file to SEO slug. Costs 1 extra credit. Default: true."),
61
- },
62
- outputSchema: {
63
- output_path: z.string().describe("Absolute path where the optimized file was saved"),
64
- output_size_bytes: z.number().describe("File size of the optimized image in bytes"),
65
- output_width_px: z.number().nullable().describe("Width of the output image in pixels"),
66
- 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 avif"),
68
- compression_ratio: z.number().nullable().describe("Output-to-input size ratio, e.g. 0.35 means 65% smaller"),
69
- seo_alt_text: z.string().nullable().describe("AI-generated image alt text for accessibility and SEO"),
70
- seo_keywords: z.array(z.string()).nullable().describe("AI-generated keywords describing the image"),
71
- seo_filename: z.string().nullable().describe("AI-generated SEO filename slug without extension"),
72
- },
73
- }, async (params) => {
74
- try {
75
- const result = await optimizeImage({
76
- input: params.input,
77
- output_path: params.output_path,
78
- output_format: params.output_format,
79
- output_width_px: params.output_width_px,
80
- output_height_px: params.output_height_px,
81
- output_upscale_factor: params.output_upscale_factor,
82
- output_resize_behavior: params.output_resize_behavior,
83
- output_seo_tag_gen: params.output_seo_tag_gen,
11
+ function createServer() {
12
+ const server = new McpServer({
13
+ name: "tinify",
14
+ version: "1.3.0",
15
+ });
16
+ server.registerTool("optimize_image", {
17
+ title: "Optimize Image",
18
+ description: "Optimize an image: smart lossy compression (typically 60-80% size reduction), optional resize/upscale/format conversion, and AI-generated SEO metadata. " +
19
+ "Accepts absolute local file paths or remote URLs. In remote/API mode, only remote URLs are supported. Supported input formats: JPG, PNG, WebP, AVIF, GIF, SVG, ICO, HEIC, TIFF, BMP (max 50 MB). Supported output formats: JPG, PNG, WebP, AVIF, GIF, SVG, ICO. " +
20
+ "Each call costs 3 credits + 1 if SEO tags enabled. Animated GIFs are processed frame-by-frame (each frame optimized individually). " +
21
+ "Cost = frames × per-frame operations. Use confirm_gif_cost: true after reviewing the cost warning. " +
22
+ "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.",
23
+ inputSchema: {
24
+ input: z
25
+ .string()
26
+ .describe("Absolute local file path or remote URL of the image to optimize. Note: in remote/API mode, only remote URLs are supported (no local file paths). 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."),
27
+ output_path: z
28
+ .string()
29
+ .optional()
30
+ .describe("Where to save. Accepts a file path (/tmp/out.webp) or directory ending in / (/tmp/images/). " +
31
+ "If omitted: saves next to original, named with SEO slug when SEO is enabled or .tinified suffix otherwise. URLs save to current working directory."),
32
+ output_format: z
33
+ .enum(["original", "jpg", "png", "webp", "avif", "gif", "svg", "ico"])
34
+ .optional()
35
+ .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. SVG output from raster input uses vector tracing. ICO output generates a favicon set (16, 24, 32, 48, 256px) unless a specific size is given."),
36
+ output_width_px: z
37
+ .number()
38
+ .int()
39
+ .positive()
40
+ .optional()
41
+ .describe("Target width in pixels. Set only width for proportional resize. Set both width and height for exact output dimensions (see output_resize_behavior)."),
42
+ output_height_px: z
43
+ .number()
44
+ .int()
45
+ .positive()
46
+ .optional()
47
+ .describe("Target height in pixels. Set only height for proportional resize. Set both width and height for exact output dimensions (see output_resize_behavior)."),
48
+ output_upscale_factor: z
49
+ .union([z.literal(2), z.literal(4)])
50
+ .optional()
51
+ .describe("AI upscale factor: 2 (2×) or 4 (4×). Uses Real-ESRGAN for high-quality upscaling."),
52
+ output_resize_behavior: z
53
+ .enum(["pad", "crop"])
54
+ .optional()
55
+ .describe("When both width and height are set and aspect ratio differs: " +
56
+ "'pad' adds white padding (default), 'crop' smart-crops to fill exact dimensions"),
57
+ output_seo_tag_gen: z
58
+ .boolean()
59
+ .optional()
60
+ .describe("Generate SEO metadata (alt text, keywords, filename) and rename output file to SEO slug. Costs 1 extra credit. Default: true."),
61
+ output_file_size_limit: z
62
+ .number()
63
+ .int()
64
+ .positive()
65
+ .optional()
66
+ .describe("Target maximum output file size in bytes. The server will attempt to meet this limit through additional compression. Not guaranteed."),
67
+ confirm_gif_cost: z
68
+ .boolean()
69
+ .optional()
70
+ .describe("Set to true to proceed with animated GIF processing after seeing cost warning. Required for animated GIFs to prevent unexpected credit consumption."),
71
+ gif_frame_limit: z
72
+ .number()
73
+ .int()
74
+ .min(1)
75
+ .max(100)
76
+ .optional()
77
+ .describe("Maximum frames to process for animated GIFs (1-100, default 100). Reduces cost by sampling fewer frames while preserving animation."),
78
+ _gif_temp_file_id: z
79
+ .string()
80
+ .optional()
81
+ .describe("Internal: temp file ID from a previous GIF cost warning. Skips re-upload."),
82
+ },
83
+ outputSchema: {
84
+ output_path: z.string().describe("Absolute path where the optimized file was saved"),
85
+ output_size_bytes: z.number().describe("File size of the optimized image in bytes"),
86
+ output_width_px: z.number().nullable().describe("Width of the output image in pixels"),
87
+ output_height_px: z.number().nullable().describe("Height of the output image in pixels"),
88
+ output_format: z.string().nullable().describe("Output format: jpg, png, webp, avif, or gif"),
89
+ compression_ratio: z.number().nullable().describe("Output-to-input size ratio, e.g. 0.35 means 65% smaller"),
90
+ seo_alt_text: z.string().nullable().describe("AI-generated image alt text for accessibility and SEO"),
91
+ seo_keywords: z.array(z.string()).nullable().describe("AI-generated keywords describing the image"),
92
+ seo_filename: z.string().nullable().describe("AI-generated SEO filename slug without extension"),
93
+ },
94
+ }, async (params) => {
95
+ try {
96
+ const result = await optimizeImage({
97
+ input: params.input,
98
+ output_path: params.output_path,
99
+ output_format: params.output_format,
100
+ output_width_px: params.output_width_px,
101
+ output_height_px: params.output_height_px,
102
+ output_upscale_factor: params.output_upscale_factor,
103
+ output_resize_behavior: params.output_resize_behavior,
104
+ output_seo_tag_gen: params.output_seo_tag_gen,
105
+ output_file_size_limit: params.output_file_size_limit,
106
+ confirm_gif_cost: params.confirm_gif_cost,
107
+ gif_frame_limit: params.gif_frame_limit,
108
+ _gif_temp_file_id: params._gif_temp_file_id,
109
+ });
110
+ // Handle GIF cost warning (not a real result)
111
+ if (result._gif_warning) {
112
+ return { content: [{ type: "text", text: result._gif_warning }] };
113
+ }
114
+ const summary = [
115
+ `Optimized: ${result.output_path}`,
116
+ `Size: ${(result.output_size_bytes / 1024).toFixed(1)} KB`,
117
+ result.compression_ratio !== null
118
+ ? `Compression: ${(result.compression_ratio * 100).toFixed(0)}%`
119
+ : null,
120
+ result.output_format ? `Format: ${result.output_format}` : null,
121
+ result.output_width_px && result.output_height_px
122
+ ? `Dimensions: ${result.output_width_px}x${result.output_height_px}`
123
+ : null,
124
+ result.seo_alt_text ? `Alt text: ${result.seo_alt_text}` : null,
125
+ ]
126
+ .filter(Boolean)
127
+ .join("\n");
128
+ return {
129
+ content: [{ type: "text", text: summary }],
130
+ structuredContent: result,
131
+ };
132
+ }
133
+ catch (error) {
134
+ return formatErrorForMcp(error);
135
+ }
136
+ });
137
+ if (process.env.MCP_TRANSPORT !== "http") {
138
+ server.registerTool("login", {
139
+ title: "Log In",
140
+ description: "Log in to your Tinify account via browser to unlock more credits. " +
141
+ "Opens a browser window where you complete login (Google, Facebook, or email). " +
142
+ "After login, MCP automatically picks up your account with shared credits across web and MCP. " +
143
+ "Free: 50 credits/day. Pro: 3,000/month. Max: 10,000/month.",
144
+ inputSchema: {},
145
+ }, async () => {
146
+ try {
147
+ const message = await loginTool();
148
+ return { content: [{ type: "text", text: message }] };
149
+ }
150
+ catch (error) {
151
+ return formatErrorForMcp(error);
152
+ }
153
+ });
154
+ server.registerTool("logout", {
155
+ title: "Log Out",
156
+ description: "Log out of your Tinify account. Reverts to guest session (20 free credits/day). " +
157
+ "Your web app account is not affected.",
158
+ inputSchema: {},
159
+ }, async () => {
160
+ try {
161
+ const message = await logoutTool();
162
+ return { content: [{ type: "text", text: message }] };
163
+ }
164
+ catch (error) {
165
+ return formatErrorForMcp(error);
166
+ }
84
167
  });
85
- const summary = [
86
- `Optimized: ${result.output_path}`,
87
- `Size: ${(result.output_size_bytes / 1024).toFixed(1)} KB`,
88
- result.compression_ratio !== null
89
- ? `Compression: ${(result.compression_ratio * 100).toFixed(0)}%`
90
- : null,
91
- result.output_format ? `Format: ${result.output_format}` : null,
92
- result.output_width_px && result.output_height_px
93
- ? `Dimensions: ${result.output_width_px}x${result.output_height_px}`
94
- : null,
95
- result.seo_alt_text ? `Alt text: ${result.seo_alt_text}` : null,
96
- ]
97
- .filter(Boolean)
98
- .join("\n");
99
- return {
100
- content: [{ type: "text", text: summary }],
101
- structuredContent: result,
102
- };
103
- }
104
- catch (error) {
105
- return formatErrorForMcp(error);
106
- }
107
- });
108
- server.registerTool("login", {
109
- title: "Log In",
110
- description: "Log in to your Tinify account via browser to unlock more credits. " +
111
- "Opens a browser window where you complete login (Google, Facebook, or email). " +
112
- "After login, MCP automatically picks up your account with shared credits across web and MCP. " +
113
- "Free: 50 credits/day. Pro: 3,000/month. Max: 10,000/month.",
114
- inputSchema: {},
115
- }, async () => {
116
- try {
117
- const message = await loginTool();
118
- return { content: [{ type: "text", text: message }] };
119
- }
120
- catch (error) {
121
- return formatErrorForMcp(error);
122
- }
123
- });
124
- server.registerTool("logout", {
125
- title: "Log Out",
126
- description: "Log out of your Tinify account. Reverts to guest session (20 free credits/day). " +
127
- "Your web app account is not affected.",
128
- inputSchema: {},
129
- }, async () => {
130
- try {
131
- const message = await logoutTool();
132
- return { content: [{ type: "text", text: message }] };
133
- }
134
- catch (error) {
135
- return formatErrorForMcp(error);
136
- }
137
- });
138
- server.registerTool("status", {
139
- title: "Account Status",
140
- description: "Check your Tinify account status: login state, tier, credits remaining, and credit reset time. " +
141
- "Use this before batch processing to verify sufficient credits.",
142
- inputSchema: {},
143
- }, async () => {
144
- try {
145
- const message = await statusTool();
146
- return { content: [{ type: "text", text: message }] };
147
- }
148
- catch (error) {
149
- return formatErrorForMcp(error);
150
- }
151
- });
152
- server.registerTool("upgrade", {
153
- title: "Upgrade Plan",
154
- description: "Open the Tinify pricing page in your browser to upgrade your plan for more credits. " +
155
- "Plans: Free (50/day), Pro (3,000/month), Max (10,000/month).",
156
- inputSchema: {},
157
- }, async () => {
158
- try {
159
- const message = await upgradeTool();
160
- return { content: [{ type: "text", text: message }] };
161
- }
162
- catch (error) {
163
- return formatErrorForMcp(error);
164
168
  }
165
- });
166
- const transport = new StdioServerTransport();
167
- await server.connect(transport);
169
+ server.registerTool("status", {
170
+ title: "Account Status",
171
+ description: "Check your Tinify account status: login state, tier, credits remaining, and credit reset time. " +
172
+ "Use this before batch processing to verify sufficient credits.",
173
+ inputSchema: {},
174
+ }, async () => {
175
+ try {
176
+ const message = await statusTool();
177
+ return { content: [{ type: "text", text: message }] };
178
+ }
179
+ catch (error) {
180
+ return formatErrorForMcp(error);
181
+ }
182
+ });
183
+ server.registerTool("upgrade", {
184
+ title: "Upgrade Plan",
185
+ description: "Open the Tinify pricing page in your browser to upgrade your plan for more credits. " +
186
+ "Plans: Free (50/day), Pro (3,000/month), Max (10,000/month).",
187
+ inputSchema: {},
188
+ }, async () => {
189
+ try {
190
+ const message = await upgradeTool();
191
+ return { content: [{ type: "text", text: message }] };
192
+ }
193
+ catch (error) {
194
+ return formatErrorForMcp(error);
195
+ }
196
+ });
197
+ return server;
198
+ }
199
+ if (process.env.MCP_TRANSPORT === "http") {
200
+ const { startHttpServer } = await import("./transport/http.js");
201
+ await startHttpServer(createServer);
202
+ }
203
+ else {
204
+ const server = createServer();
205
+ const transport = new StdioServerTransport();
206
+ await server.connect(transport);
207
+ }
168
208
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@ export async function loginTool() {
10
10
  // If already logged in, return current status
11
11
  const existingToken = sessionManager.getMcpToken();
12
12
  if (existingToken) {
13
- const status = await getAccountStatus(baseUrl, existingToken, null);
13
+ const status = await getAccountStatus(baseUrl, { Authorization: `Bearer ${existingToken}` });
14
14
  if (status.logged_in) {
15
15
  return `Already logged in as ${status.email} (${status.tier} tier, ${status.credits_remaining.toLocaleString()} credits remaining).`;
16
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/tools/login.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/tools/login.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,22 @@
1
+ import { resolveInput as resolveInputUtil } from "../utils/input.js";
2
+ /**
3
+ * Resolves the input path/URL, with a guard for HTTP mode (remote URLs only).
4
+ * Exported for testing.
5
+ */
6
+ export declare function resolveInput(input: string): ReturnType<typeof resolveInputUtil>;
1
7
  export interface OptimizeImageParams {
2
8
  input: string;
3
9
  output_path?: string;
4
- output_format?: "original" | "jpg" | "png" | "webp" | "avif";
10
+ output_format?: "original" | "jpg" | "png" | "webp" | "avif" | "gif" | "svg" | "ico";
5
11
  output_width_px?: number;
6
12
  output_height_px?: number;
7
- output_upscale_factor?: number;
13
+ output_upscale_factor?: 2 | 4;
8
14
  output_resize_behavior?: "pad" | "crop";
9
15
  output_seo_tag_gen?: boolean;
16
+ output_file_size_limit?: number;
17
+ confirm_gif_cost?: boolean;
18
+ gif_frame_limit?: number;
19
+ _gif_temp_file_id?: string;
10
20
  baseUrl?: string;
11
21
  timeoutMs?: number;
12
22
  }
@@ -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;IAC7D,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,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,CA8F9B"}
1
+ {"version":3,"file":"optimize.d.ts","sourceRoot":"","sources":["../../src/tools/optimize.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErE;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAK/E;AAKD,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,GAAG,KAAK,GAAG,KAAK,CAAC;IACrF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9B,sBAAsB,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,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,CAsK9B"}
@@ -4,26 +4,85 @@ import { uploadFile } from "../api/upload.js";
4
4
  import { triggerProcessing } from "../api/process.js";
5
5
  import { waitForCompletion } from "../api/status.js";
6
6
  import { downloadFile } from "../api/download.js";
7
- import { resolveInput } from "../utils/input.js";
7
+ import { resolveInput as resolveInputUtil } from "../utils/input.js";
8
+ /**
9
+ * Resolves the input path/URL, with a guard for HTTP mode (remote URLs only).
10
+ * Exported for testing.
11
+ */
12
+ export function resolveInput(input) {
13
+ if (process.env.MCP_TRANSPORT === "http" && !input.startsWith("http://") && !input.startsWith("https://")) {
14
+ throw new Error("Local file paths are not supported in remote mode. Please provide a URL (https://...).");
15
+ }
16
+ return resolveInputUtil(input);
17
+ }
8
18
  import { resolveUniqueOutputPath } from "../utils/output.js";
19
+ import { DEFAULT_BASE_URL, getAuthHeaders } from "../api/client.js";
9
20
  import { SessionManager } from "../session/manager.js";
10
- import { DEFAULT_BASE_URL } from "../api/client.js";
11
21
  export async function optimizeImage(params) {
12
22
  const baseUrl = params.baseUrl ?? DEFAULT_BASE_URL;
13
- const sessionManager = new SessionManager();
14
23
  // 1. Resolve input (read file or fetch URL)
15
24
  const input = await resolveInput(params.input);
16
- // 2. Upload to backend
17
- const authHeaders = sessionManager.getAuthHeaders();
18
- const uploadResult = await uploadFile({
19
- baseUrl,
20
- fileBuffer: input.buffer,
21
- filename: input.filename,
22
- authHeaders,
23
- });
24
- // Persist new session token if returned (for guest sessions)
25
- if (uploadResult.session_token) {
26
- sessionManager.saveToken(uploadResult.session_token);
25
+ // 2. Upload to backend (skip if reusing from GIF cost warning)
26
+ const authHeaders = getAuthHeaders();
27
+ let uploadResult;
28
+ if (params._gif_temp_file_id && params.confirm_gif_cost) {
29
+ // Reuse the upload from a previous GIF cost warning — no re-upload needed
30
+ uploadResult = {
31
+ temp_file_id: params._gif_temp_file_id,
32
+ original_filename: input.filename,
33
+ file_size: input.buffer.length,
34
+ mime_type: "image/gif",
35
+ session_token: null,
36
+ };
37
+ }
38
+ else {
39
+ uploadResult = await uploadFile({
40
+ baseUrl,
41
+ fileBuffer: input.buffer,
42
+ filename: input.filename,
43
+ authHeaders,
44
+ });
45
+ // Persist new session token if returned (for guest sessions, stdio mode only)
46
+ if (uploadResult.session_token && process.env.MCP_TRANSPORT !== "http") {
47
+ new SessionManager().saveToken(uploadResult.session_token);
48
+ }
49
+ }
50
+ // Check if animated GIF needs cost confirmation
51
+ const isAnimatedGif = uploadResult.gif_frame_count && uploadResult.gif_frame_count > 1;
52
+ if (isAnimatedGif && !params.confirm_gif_cost) {
53
+ const frameLimit = params.gif_frame_limit ?? 100;
54
+ const framesToProcess = Math.min(uploadResult.gif_frame_count, frameLimit);
55
+ let perFrameCost = 3; // compress always runs
56
+ if (params.output_width_px || params.output_height_px)
57
+ perFrameCost += 1;
58
+ if (params.output_upscale_factor)
59
+ perFrameCost += 2;
60
+ const tagCost = params.output_seo_tag_gen !== false ? 1 : 0;
61
+ const totalCost = framesToProcess * perFrameCost + tagCost;
62
+ const warning = [
63
+ `Animated GIF detected: ${input.filename}`,
64
+ ` ${uploadResult.gif_frame_count} frames, ${uploadResult.gif_fps ?? "?"} fps`,
65
+ ` ${framesToProcess} frames × ${perFrameCost} credits = ${totalCost} credits`,
66
+ ``,
67
+ ` Animated GIFs are processed frame-by-frame for highest quality.`,
68
+ ` To proceed, call optimize_image again with:`,
69
+ ` confirm_gif_cost: true`,
70
+ ` _gif_temp_file_id: "${uploadResult.temp_file_id}"`,
71
+ ` To reduce cost, set gif_frame_limit (1-100, default 100).`,
72
+ ].join("\n");
73
+ return {
74
+ output_path: "",
75
+ output_size_bytes: 0,
76
+ output_width_px: null,
77
+ output_height_px: null,
78
+ output_format: null,
79
+ compression_ratio: null,
80
+ seo_alt_text: null,
81
+ seo_keywords: null,
82
+ seo_filename: null,
83
+ _gif_warning: warning,
84
+ _gif_temp_file_id: uploadResult.temp_file_id,
85
+ };
27
86
  }
28
87
  // 3. Build settings (smart defaults: compress always, SEO tags on)
29
88
  const settings = {
@@ -44,6 +103,12 @@ export async function optimizeImage(params) {
44
103
  if (params.output_width_px !== undefined || params.output_height_px !== undefined) {
45
104
  settings.output_resize_behavior = params.output_resize_behavior ?? "pad";
46
105
  }
106
+ if (params.output_file_size_limit !== undefined) {
107
+ settings.output_file_size_limit = params.output_file_size_limit;
108
+ }
109
+ if (params.gif_frame_limit !== undefined) {
110
+ settings.gif_frame_limit = params.gif_frame_limit;
111
+ }
47
112
  // 4. Trigger processing
48
113
  const processResult = await triggerProcessing({
49
114
  baseUrl,
@@ -61,7 +126,22 @@ export async function optimizeImage(params) {
61
126
  jobId: job.id,
62
127
  timeoutMs: params.timeoutMs ?? 60000,
63
128
  });
64
- // 6. Download processed file
129
+ // 6. In HTTP mode: return download URL (no local disk write)
130
+ if (process.env.MCP_TRANSPORT === "http") {
131
+ const downloadUrl = `${baseUrl}/download/${job.id}`;
132
+ return {
133
+ output_path: downloadUrl,
134
+ output_size_bytes: completedJob.processed_size ?? 0,
135
+ output_width_px: completedJob.processed_width ?? null,
136
+ output_height_px: completedJob.processed_height ?? null,
137
+ output_format: completedJob.processed_format ?? null,
138
+ compression_ratio: completedJob.processed_compression_ratio ?? null,
139
+ seo_alt_text: completedJob.seo_alt_text ?? null,
140
+ seo_keywords: completedJob.seo_keywords ?? null,
141
+ seo_filename: completedJob.seo_filename ?? null,
142
+ };
143
+ }
144
+ // stdio mode: download to local disk (existing code)
65
145
  const downloadResult = await downloadFile({ baseUrl, jobId: job.id });
66
146
  // 7. Resolve output path and save
67
147
  const outputPath = resolveUniqueOutputPath({