mcp-image-uploader 1.0.1

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 (64) hide show
  1. package/AGENTS.md +33 -0
  2. package/README.md +173 -0
  3. package/dist/config.d.ts +21 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +89 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +59 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/services/compressor.d.ts +10 -0
  12. package/dist/services/compressor.d.ts.map +1 -0
  13. package/dist/services/compressor.js +64 -0
  14. package/dist/services/compressor.js.map +1 -0
  15. package/dist/services/image-loader.d.ts +6 -0
  16. package/dist/services/image-loader.d.ts.map +1 -0
  17. package/dist/services/image-loader.js +47 -0
  18. package/dist/services/image-loader.js.map +1 -0
  19. package/dist/services/uploader.d.ts +6 -0
  20. package/dist/services/uploader.d.ts.map +1 -0
  21. package/dist/services/uploader.js +65 -0
  22. package/dist/services/uploader.js.map +1 -0
  23. package/dist/strategies/avif.d.ts +9 -0
  24. package/dist/strategies/avif.d.ts.map +1 -0
  25. package/dist/strategies/avif.js +29 -0
  26. package/dist/strategies/avif.js.map +1 -0
  27. package/dist/strategies/jpeg.d.ts +13 -0
  28. package/dist/strategies/jpeg.d.ts.map +1 -0
  29. package/dist/strategies/jpeg.js +40 -0
  30. package/dist/strategies/jpeg.js.map +1 -0
  31. package/dist/strategies/png.d.ts +12 -0
  32. package/dist/strategies/png.d.ts.map +1 -0
  33. package/dist/strategies/png.js +51 -0
  34. package/dist/strategies/png.js.map +1 -0
  35. package/dist/strategies/webp.d.ts +9 -0
  36. package/dist/strategies/webp.d.ts.map +1 -0
  37. package/dist/strategies/webp.js +19 -0
  38. package/dist/strategies/webp.js.map +1 -0
  39. package/dist/tools/upload-image.d.ts +30 -0
  40. package/dist/tools/upload-image.d.ts.map +1 -0
  41. package/dist/tools/upload-image.js +81 -0
  42. package/dist/tools/upload-image.js.map +1 -0
  43. package/dist/types/index.d.ts +43 -0
  44. package/dist/types/index.d.ts.map +1 -0
  45. package/dist/types/index.js +2 -0
  46. package/dist/types/index.js.map +1 -0
  47. package/dist/utils/index.d.ts +13 -0
  48. package/dist/utils/index.d.ts.map +1 -0
  49. package/dist/utils/index.js +32 -0
  50. package/dist/utils/index.js.map +1 -0
  51. package/package.json +37 -0
  52. package/src/config.ts +106 -0
  53. package/src/index.ts +69 -0
  54. package/src/services/compressor.ts +75 -0
  55. package/src/services/image-loader.ts +49 -0
  56. package/src/services/uploader.ts +85 -0
  57. package/src/strategies/avif.ts +32 -0
  58. package/src/strategies/jpeg.ts +44 -0
  59. package/src/strategies/png.ts +55 -0
  60. package/src/strategies/webp.ts +24 -0
  61. package/src/tools/upload-image.ts +100 -0
  62. package/src/types/index.ts +46 -0
  63. package/src/utils/index.ts +30 -0
  64. package/tsconfig.json +27 -0
package/AGENTS.md ADDED
@@ -0,0 +1,33 @@
1
+ # AGENTS.md
2
+
3
+ ## 🤖 智能体辅助指南
4
+
5
+ 本文件旨在为使用该项目的 AI 智能体(如 Claude, ChatGPT, Gemini 等)提供上下文、最佳实践和任务执行建议。
6
+
7
+ ### 1. 项目核心定位
8
+ `mcp-image-uploader` 是一个基于 Model Context Protocol (MCP) 的工具服务器,主要职责是:
9
+ - **图片处理**: 智能压缩图片以减少存储和传输成本。
10
+ - **图床上传**: 将本地或远程图片转换为可访问的静态 URL。
11
+
12
+ ### 2. 关键工具:`upload_image`
13
+ AI 智能体在需要处理图片上传任务时,应优先使用此工具。
14
+
15
+ #### 最佳实践建议:
16
+ - **自动压缩(默认)**: 在大多数场景下,保持 `autoCompress: true`。这会根据图片类型和大小自动平衡清晰度与体积。
17
+ - **格式转换**: 如果目标平台对图片格式有严格要求(如微信公众号建议使用 JPEG),请指定 `format` 参数。
18
+ - **批量处理**: 如果用户提供了多个路径或 URL,应串行或并行调用多次 `upload_image`。
19
+
20
+ ### 3. 给 AI 智能体的交互规范
21
+ 当您(智能体)作为编码助手或自动化脚本使用此项目时,请遵循以下原则:
22
+
23
+ - **链接返回**: 上传成功后,请始终以 Markdown 链接或图片语法返回给用户,方便直观预览:`![图片说明](URL)`。
24
+ - **错误透明**: 如果上传失败,请务必返回具体的错误信息(如文件不存在、网络连接超时等),不要仅返回“上传失败”。
25
+ - **统计信息**: 主动告知用户压缩的效果(原始大小 vs 压缩后大小),提升用户对工具价值的感知。
26
+
27
+ ### 4. 常见任务流
28
+ - **“帮我上传这张图”**: 识别输入源(路径或链接) -> 调用 `upload_image` -> 返回预览链接。
29
+ - **“图片太大发不出去”**: 解释可以使用此工具进行压缩 -> 调用 `upload_image` -> 返回压缩后的链接及比例。
30
+ - **“把这个文件夹里的所有截图都上传”**: 扫描目录 -> 过滤图片文件 -> 循环上传。
31
+
32
+ ---
33
+ *注:此文件是智能体与项目之间的协作桥梁,建议根据新功能的迭代持续更新。*
package/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # MCP Image Uploader
2
+
3
+ 一个用于图片智能压缩和上传的 Model Context Protocol (MCP) 服务器。
4
+
5
+ ## 功能特性
6
+
7
+ - **多源输入**: 支持本地文件路径和远程 URL
8
+ - **智能压缩**: 根据图片格式和大小自动应用最优压缩策略
9
+ - **多格式支持**: JPEG、PNG、WebP、AVIF
10
+ - **双运行时**: 支持 Node.js 和 Bun
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ # 使用 pnpm
16
+ pnpm install
17
+
18
+ # 构建
19
+ pnpm build
20
+ ```
21
+
22
+ ## 使用方式
23
+
24
+ ### Claude Desktop 配置
25
+
26
+ 在 `~/Library/Application Support/Claude/claude_desktop_config.json` 中添加:
27
+
28
+ ```json
29
+ {
30
+ "mcpServers": {
31
+ "image-uploader": {
32
+ "command": "node",
33
+ "args": [
34
+ "/path/to/mcp-image-uploader/dist/index.js",
35
+ "UPLOAD_ENDPOINT=https://your-api.com/upload"
36
+ ]
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ 或使用开发模式:
43
+
44
+ ```json
45
+ {
46
+ "mcpServers": {
47
+ "image-uploader": {
48
+ "command": "npx",
49
+ "args": [
50
+ "tsx",
51
+ "/path/to/mcp-image-uploader/src/index.ts",
52
+ "UPLOAD_ENDPOINT=https://your-api.com/upload"
53
+ ]
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ### Bun 运行时
60
+
61
+ ```json
62
+ {
63
+ "mcpServers": {
64
+ "image-uploader": {
65
+ "command": "bun",
66
+ "args": [
67
+ "/path/to/mcp-image-uploader/src/index.ts",
68
+ "UPLOAD_ENDPOINT=https://your-api.com/upload"
69
+ ]
70
+ }
71
+ }
72
+ }
73
+ ```
74
+
75
+ ### 配置参数
76
+
77
+ | 参数 | 必填 | 说明 |
78
+ |------|------|------|
79
+ | `UPLOAD_ENDPOINT` | ✅ | 图片上传接口地址 |
80
+
81
+ 也可以通过环境变量配置:
82
+
83
+ ```bash
84
+ UPLOAD_ENDPOINT=https://your-api.com/upload node dist/index.js
85
+ ```
86
+
87
+ ### 上传接口要求
88
+
89
+ 上传接口需要支持以下格式:
90
+
91
+ **请求:**
92
+ - Method: `POST`
93
+ - Body: 图片文件 (File 对象)
94
+
95
+ **响应:**
96
+ ```json
97
+ {
98
+ "url": "https://cdn.example.com/path/to/image.jpg"
99
+ }
100
+ ```
101
+
102
+ **错误响应:**
103
+ ```json
104
+ {
105
+ "dm_error": 10001,
106
+ "error_msg": "错误信息"
107
+ }
108
+ ```
109
+
110
+ ## 工具说明
111
+
112
+ ### `upload_image`
113
+
114
+ 压缩并上传图片到图床。
115
+
116
+ **参数:**
117
+
118
+ | 参数 | 类型 | 默认值 | 说明 |
119
+ |------|------|--------|------|
120
+ | `source` | string | (必填) | 图片来源:本地路径或远程 URL |
121
+ | `skipCompress` | boolean | `false` | 是否跳过压缩,直接上传原图 |
122
+ | `autoCompress` | boolean | `true` | 是否启用智能自动压缩(仅 skipCompress=false 时生效) |
123
+ | `quality` | number | - | 手动压缩质量 (1-100),仅 skipCompress=false 且 autoCompress=false 时生效 |
124
+ | `format` | string | - | 输出格式:jpeg/png/webp/avif(默认保持原格式) |
125
+
126
+ **返回:**
127
+
128
+ ```json
129
+ {
130
+ "success": true,
131
+ "url": "https://...",
132
+ "stats": {
133
+ "originalSize": "1.5 MB",
134
+ "compressedSize": "320 KB",
135
+ "compressionRatio": "78%"
136
+ }
137
+ }
138
+ ```
139
+
140
+ ## 压缩策略
141
+
142
+ ### JPEG
143
+ - **自动**: < 500KB → quality=78 | > 2MB → quality=65 | 常规 → quality=72
144
+ - **手动**: quality=85 (默认)
145
+
146
+ ### PNG
147
+ - **自动**: 有损量化 + 动态压缩等级
148
+ - **手动**: 无损压缩
149
+
150
+ ### WebP
151
+ - **自动**: quality=75, alphaQuality=100
152
+ - **手动**: 自定义 quality (默认 75)
153
+
154
+ ### AVIF
155
+ - **自动**: 无损压缩
156
+ - **手动**: quality=50 (默认)
157
+
158
+ ## 开发
159
+
160
+ ```bash
161
+ # 开发模式
162
+ pnpm dev
163
+
164
+ # 构建
165
+ pnpm build
166
+
167
+ # 启动
168
+ pnpm start
169
+ ```
170
+
171
+ ## License
172
+
173
+ MIT
@@ -0,0 +1,21 @@
1
+ /**
2
+ * MCP Image Uploader 配置模块
3
+ *
4
+ * 支持通过命令行参数配置上传接口地址,实现业务解耦
5
+ *
6
+ * 使用方式(命令行参数):
7
+ * node dist/index.js UPLOAD_ENDPOINT=https://your-api.com/upload
8
+ *
9
+ * 使用方式(环境变量):
10
+ * UPLOAD_ENDPOINT=https://your-api.com/upload node dist/index.js
11
+ */
12
+ export interface Config {
13
+ /** 上传接口地址 */
14
+ uploadUrl: string;
15
+ }
16
+ export declare function getConfig(): Config;
17
+ /**
18
+ * 重置配置(仅用于测试)
19
+ */
20
+ export declare function resetConfig(): void;
21
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,MAAM;IACnB,aAAa;IACb,SAAS,EAAE,MAAM,CAAC;CACrB;AAmED,wBAAgB,SAAS,IAAI,MAAM,CAgBlC;AAED;;GAEG;AACH,wBAAgB,WAAW,IAAI,IAAI,CAElC"}
package/dist/config.js ADDED
@@ -0,0 +1,89 @@
1
+ /**
2
+ * MCP Image Uploader 配置模块
3
+ *
4
+ * 支持通过命令行参数配置上传接口地址,实现业务解耦
5
+ *
6
+ * 使用方式(命令行参数):
7
+ * node dist/index.js UPLOAD_ENDPOINT=https://your-api.com/upload
8
+ *
9
+ * 使用方式(环境变量):
10
+ * UPLOAD_ENDPOINT=https://your-api.com/upload node dist/index.js
11
+ */
12
+ /**
13
+ * 默认配置
14
+ */
15
+ const DEFAULT_CONFIG = {
16
+ uploadUrl: '',
17
+ };
18
+ /**
19
+ * 解析命令行参数获取配置
20
+ */
21
+ function parseArgs() {
22
+ const args = process.argv.slice(2);
23
+ const config = {};
24
+ for (const arg of args) {
25
+ // 支持 UPLOAD_ENDPOINT=xxx 格式
26
+ if (arg.startsWith('UPLOAD_ENDPOINT=')) {
27
+ config.uploadUrl = arg.split('=').slice(1).join('=');
28
+ continue;
29
+ }
30
+ }
31
+ // 同时支持环境变量
32
+ if (!config.uploadUrl && process.env.UPLOAD_ENDPOINT) {
33
+ config.uploadUrl = process.env.UPLOAD_ENDPOINT;
34
+ }
35
+ return config;
36
+ }
37
+ /**
38
+ * 验证配置
39
+ */
40
+ function validateConfig(config) {
41
+ if (!config.uploadUrl) {
42
+ console.error('[MCP] 错误: 必须配置上传接口地址 UPLOAD_ENDPOINT');
43
+ console.error('[MCP] 使用方式:');
44
+ console.error(' node dist/index.js UPLOAD_ENDPOINT=https://your-api.com/upload');
45
+ console.error('');
46
+ console.error('[MCP] MCP 配置示例:');
47
+ console.error(' {');
48
+ console.error(' "mcpServers": {');
49
+ console.error(' "image-uploader": {');
50
+ console.error(' "command": "node",');
51
+ console.error(' "args": ["/path/to/dist/index.js", "UPLOAD_ENDPOINT=https://your-api.com/upload"]');
52
+ console.error(' }');
53
+ console.error(' }');
54
+ console.error(' }');
55
+ process.exit(1);
56
+ }
57
+ // 验证 URL 格式
58
+ try {
59
+ new URL(config.uploadUrl);
60
+ }
61
+ catch {
62
+ console.error(`[MCP] 错误: 无效的上传接口地址: ${config.uploadUrl}`);
63
+ process.exit(1);
64
+ }
65
+ }
66
+ /**
67
+ * 获取配置(单例)
68
+ */
69
+ let cachedConfig = null;
70
+ export function getConfig() {
71
+ if (cachedConfig) {
72
+ return cachedConfig;
73
+ }
74
+ const parsedArgs = parseArgs();
75
+ cachedConfig = {
76
+ ...DEFAULT_CONFIG,
77
+ ...parsedArgs,
78
+ };
79
+ validateConfig(cachedConfig);
80
+ console.error(`[MCP] 配置已加载: UPLOAD_ENDPOINT=${cachedConfig.uploadUrl}`);
81
+ return cachedConfig;
82
+ }
83
+ /**
84
+ * 重置配置(仅用于测试)
85
+ */
86
+ export function resetConfig() {
87
+ cachedConfig = null;
88
+ }
89
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH;;GAEG;AACH,MAAM,cAAc,GAAW;IAC3B,SAAS,EAAE,EAAE;CAChB,CAAC;AAEF;;GAEG;AACH,SAAS,SAAS;IACd,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAoB,EAAE,CAAC;IAEnC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACrB,4BAA4B;QAC5B,IAAI,GAAG,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACrC,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACrD,SAAS;QACb,CAAC;IACL,CAAC;IAED,WAAW;IACX,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QACnD,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACnD,CAAC;IAED,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,MAAc;IAClC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACrC,OAAO,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC3C,OAAO,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,2FAA2F,CAAC,CAAC;QAC3G,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,YAAY;IACZ,IAAI,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,KAAK,CAAC,wBAAwB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACL,CAAC;AAED;;GAEG;AACH,IAAI,YAAY,GAAkB,IAAI,CAAC;AAEvC,MAAM,UAAU,SAAS;IACrB,IAAI,YAAY,EAAE,CAAC;QACf,OAAO,YAAY,CAAC;IACxB,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,EAAE,CAAC;IAC/B,YAAY,GAAG;QACX,GAAG,cAAc;QACjB,GAAG,UAAU;KAChB,CAAC;IAEF,cAAc,CAAC,YAAY,CAAC,CAAC;IAE7B,OAAO,CAAC,KAAK,CAAC,gCAAgC,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;IAExE,OAAO,YAAY,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW;IACvB,YAAY,GAAG,IAAI,CAAC;AACxB,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { uploadImageSchema, executeUploadImage } from './tools/upload-image.js';
5
+ import { formatBytes } from './utils/index.js';
6
+ // 创建 MCP 服务器
7
+ const server = new McpServer({
8
+ name: 'mcp-image-uploader',
9
+ version: '1.0.0',
10
+ });
11
+ // 注册 upload_image 工具
12
+ server.tool('upload_image', '压缩并上传图片到图床。支持本地文件路径或远程 URL 作为输入,智能压缩后返回图床 URL。', uploadImageSchema.shape, async (params) => {
13
+ try {
14
+ const result = await executeUploadImage(params);
15
+ return {
16
+ content: [
17
+ {
18
+ type: 'text',
19
+ text: JSON.stringify({
20
+ success: true,
21
+ url: result.url,
22
+ stats: {
23
+ originalSize: formatBytes(result.originalSize),
24
+ compressedSize: formatBytes(result.compressedSize),
25
+ compressionRatio: `${result.compressionRatio}%`,
26
+ },
27
+ }, null, 2),
28
+ },
29
+ ],
30
+ };
31
+ }
32
+ catch (error) {
33
+ const message = error instanceof Error ? error.message : String(error);
34
+ console.error(`[MCP] 错误: ${message}`);
35
+ return {
36
+ content: [
37
+ {
38
+ type: 'text',
39
+ text: JSON.stringify({
40
+ success: false,
41
+ error: message,
42
+ }, null, 2),
43
+ },
44
+ ],
45
+ isError: true,
46
+ };
47
+ }
48
+ });
49
+ // 启动服务器
50
+ async function main() {
51
+ const transport = new StdioServerTransport();
52
+ await server.connect(transport);
53
+ console.error('[MCP] Image Uploader Server 已启动');
54
+ }
55
+ main().catch((error) => {
56
+ console.error('[MCP] 服务器启动失败:', error);
57
+ process.exit(1);
58
+ });
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,aAAa;AACb,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IACzB,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,OAAO;CACnB,CAAC,CAAC;AAEH,qBAAqB;AACrB,MAAM,CAAC,IAAI,CACP,cAAc,EACd,gDAAgD,EAChD,iBAAiB,CAAC,KAAK,EACvB,KAAK,EAAE,MAAM,EAAE,EAAE;IACb,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAEhD,OAAO;YACH,OAAO,EAAE;gBACL;oBACI,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACjB,OAAO,EAAE,IAAI;wBACb,GAAG,EAAE,MAAM,CAAC,GAAG;wBACf,KAAK,EAAE;4BACH,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,YAAY,CAAC;4BAC9C,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,cAAc,CAAC;4BAClD,gBAAgB,EAAE,GAAG,MAAM,CAAC,gBAAgB,GAAG;yBAClD;qBACJ,EAAE,IAAI,EAAE,CAAC,CAAC;iBACd;aACJ;SACJ,CAAC;IACN,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,aAAa,OAAO,EAAE,CAAC,CAAC;QAEtC,OAAO;YACH,OAAO,EAAE;gBACL;oBACI,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACjB,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,OAAO;qBACjB,EAAE,IAAI,EAAE,CAAC,CAAC;iBACd;aACJ;YACD,OAAO,EAAE,IAAI;SAChB,CAAC;IACN,CAAC;AACL,CAAC,CACJ,CAAC;AAEF,QAAQ;AACR,KAAK,UAAU,IAAI;IACf,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;AACrD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { CompressionResult, CompressionOptions, ImageMetadata } from '../types/index.js';
2
+ /**
3
+ * 获取图片元数据
4
+ */
5
+ export declare function getImageMetadata(buffer: Buffer): Promise<ImageMetadata>;
6
+ /**
7
+ * 压缩图片
8
+ */
9
+ export declare function compressImage(buffer: Buffer, options: CompressionOptions): Promise<CompressionResult>;
10
+ //# sourceMappingURL=compressor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compressor.d.ts","sourceRoot":"","sources":["../../src/services/compressor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,EAAe,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAM3G;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAS7E;AAmBD;;GAEG;AACH,wBAAsB,aAAa,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,GAC5B,OAAO,CAAC,iBAAiB,CAAC,CA8B5B"}
@@ -0,0 +1,64 @@
1
+ import sharp from 'sharp';
2
+ import { compressJpeg } from '../strategies/jpeg.js';
3
+ import { compressPng } from '../strategies/png.js';
4
+ import { compressWebp } from '../strategies/webp.js';
5
+ import { compressAvif } from '../strategies/avif.js';
6
+ /**
7
+ * 获取图片元数据
8
+ */
9
+ export async function getImageMetadata(buffer) {
10
+ const metadata = await sharp(buffer).metadata();
11
+ return {
12
+ format: normalizeFormat(metadata.format),
13
+ width: metadata.width ?? 0,
14
+ height: metadata.height ?? 0,
15
+ size: buffer.length,
16
+ };
17
+ }
18
+ /**
19
+ * 标准化格式名称
20
+ */
21
+ function normalizeFormat(format) {
22
+ const formatMap = {
23
+ 'jpeg': 'jpeg',
24
+ 'jpg': 'jpeg',
25
+ 'png': 'png',
26
+ 'webp': 'webp',
27
+ 'avif': 'avif',
28
+ 'gif': 'gif',
29
+ 'tiff': 'tiff',
30
+ };
31
+ return formatMap[format?.toLowerCase() ?? ''] ?? 'jpeg';
32
+ }
33
+ /**
34
+ * 压缩图片
35
+ */
36
+ export async function compressImage(buffer, options) {
37
+ const metadata = await getImageMetadata(buffer);
38
+ const targetFormat = options.format ?? metadata.format;
39
+ let compressedBuffer;
40
+ switch (targetFormat) {
41
+ case 'jpeg':
42
+ compressedBuffer = await compressJpeg(buffer, metadata.size, options);
43
+ break;
44
+ case 'png':
45
+ compressedBuffer = await compressPng(buffer, metadata.size, options);
46
+ break;
47
+ case 'webp':
48
+ compressedBuffer = await compressWebp(buffer, options);
49
+ break;
50
+ case 'avif':
51
+ compressedBuffer = await compressAvif(buffer, options);
52
+ break;
53
+ default:
54
+ // 对于不支持的格式,直接返回原始 buffer
55
+ compressedBuffer = buffer;
56
+ }
57
+ return {
58
+ buffer: compressedBuffer,
59
+ originalSize: metadata.size,
60
+ compressedSize: compressedBuffer.length,
61
+ format: targetFormat,
62
+ };
63
+ }
64
+ //# sourceMappingURL=compressor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compressor.js","sourceRoot":"","sources":["../../src/services/compressor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,MAAc;IACjD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;IAEhD,OAAO;QACH,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC;QACxC,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,CAAC;QAC1B,MAAM,EAAE,QAAQ,CAAC,MAAM,IAAI,CAAC;QAC5B,IAAI,EAAE,MAAM,CAAC,MAAM;KACtB,CAAC;AACN,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,MAA0B;IAC/C,MAAM,SAAS,GAAgC;QAC3C,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,MAAM;KACjB,CAAC;IAEF,OAAO,SAAS,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,IAAI,MAAM,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAC/B,MAAc,EACd,OAA2B;IAE3B,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC;IAEvD,IAAI,gBAAwB,CAAC;IAE7B,QAAQ,YAAY,EAAE,CAAC;QACnB,KAAK,MAAM;YACP,gBAAgB,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACtE,MAAM;QACV,KAAK,KAAK;YACN,gBAAgB,GAAG,MAAM,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACrE,MAAM;QACV,KAAK,MAAM;YACP,gBAAgB,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACvD,MAAM;QACV,KAAK,MAAM;YACP,gBAAgB,GAAG,MAAM,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACvD,MAAM;QACV;YACI,yBAAyB;YACzB,gBAAgB,GAAG,MAAM,CAAC;IAClC,CAAC;IAED,OAAO;QACH,MAAM,EAAE,gBAAgB;QACxB,YAAY,EAAE,QAAQ,CAAC,IAAI;QAC3B,cAAc,EAAE,gBAAgB,CAAC,MAAM;QACvC,MAAM,EAAE,YAAY;KACvB,CAAC;AACN,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * 加载图片
3
+ * 支持本地文件路径和远程 URL
4
+ */
5
+ export declare function loadImage(source: string): Promise<Buffer>;
6
+ //# sourceMappingURL=image-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-loader.d.ts","sourceRoot":"","sources":["../../src/services/image-loader.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM/D"}
@@ -0,0 +1,47 @@
1
+ import * as fs from 'node:fs/promises';
2
+ import * as path from 'node:path';
3
+ import { isUrl } from '../utils/index.js';
4
+ /**
5
+ * 加载图片
6
+ * 支持本地文件路径和远程 URL
7
+ */
8
+ export async function loadImage(source) {
9
+ if (isUrl(source)) {
10
+ return loadFromUrl(source);
11
+ }
12
+ else {
13
+ return loadFromFile(source);
14
+ }
15
+ }
16
+ /**
17
+ * 从本地文件加载
18
+ */
19
+ async function loadFromFile(filePath) {
20
+ const absolutePath = path.isAbsolute(filePath)
21
+ ? filePath
22
+ : path.resolve(process.cwd(), filePath);
23
+ try {
24
+ const buffer = await fs.readFile(absolutePath);
25
+ return buffer;
26
+ }
27
+ catch (error) {
28
+ throw new Error(`无法读取文件: ${absolutePath} - ${error instanceof Error ? error.message : String(error)}`);
29
+ }
30
+ }
31
+ /**
32
+ * 从远程 URL 加载
33
+ */
34
+ async function loadFromUrl(url) {
35
+ try {
36
+ const response = await fetch(url);
37
+ if (!response.ok) {
38
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
39
+ }
40
+ const arrayBuffer = await response.arrayBuffer();
41
+ return Buffer.from(arrayBuffer);
42
+ }
43
+ catch (error) {
44
+ throw new Error(`无法下载图片: ${url} - ${error instanceof Error ? error.message : String(error)}`);
45
+ }
46
+ }
47
+ //# sourceMappingURL=image-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-loader.js","sourceRoot":"","sources":["../../src/services/image-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAc;IAC1C,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QAChB,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;SAAM,CAAC;QACJ,OAAO,YAAY,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,YAAY,CAAC,QAAgB;IACxC,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QAC1C,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;IAE5C,IAAI,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC/C,OAAO,MAAM,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,WAAW,YAAY,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC3G,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,WAAW,CAAC,GAAW;IAClC,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAElC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,QAAQ,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;QACvE,CAAC;QAED,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;QACjD,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClG,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { ImageFormat } from '../types/index.js';
2
+ /**
3
+ * 上传图片到图床
4
+ */
5
+ export declare function uploadImage(buffer: Buffer, format: ImageFormat): Promise<string>;
6
+ //# sourceMappingURL=uploader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploader.d.ts","sourceRoot":"","sources":["../../src/services/uploader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAmCrD;;GAEG;AACH,wBAAsB,WAAW,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,GACpB,OAAO,CAAC,MAAM,CAAC,CA2CjB"}
@@ -0,0 +1,65 @@
1
+ import { getConfig } from '../config.js';
2
+ /**
3
+ * 获取 MIME 类型
4
+ */
5
+ function getMimeType(format) {
6
+ const mimeTypes = {
7
+ 'jpeg': 'image/jpeg',
8
+ 'png': 'image/png',
9
+ 'webp': 'image/webp',
10
+ 'avif': 'image/avif',
11
+ 'gif': 'image/gif',
12
+ 'tiff': 'image/tiff',
13
+ };
14
+ return mimeTypes[format] ?? 'application/octet-stream';
15
+ }
16
+ /**
17
+ * 生成文件名
18
+ */
19
+ function generateFilename(format) {
20
+ const timestamp = Date.now();
21
+ const random = Math.random().toString(36).substring(2, 8);
22
+ const extension = format === 'jpeg' ? 'jpg' : format;
23
+ return `image_${timestamp}_${random}.${extension}`;
24
+ }
25
+ /**
26
+ * 上传图片到图床
27
+ */
28
+ export async function uploadImage(buffer, format) {
29
+ const filename = generateFilename(format);
30
+ const mimeType = getMimeType(format);
31
+ console.error(`[MCP] 准备上传: ${filename}, MIME: ${mimeType}, 大小: ${buffer.length} bytes`);
32
+ // 创建 FormData - 使用 File 对象确保正确的 MIME 类型
33
+ // 在 Node.js/Bun 中使用 File 对象
34
+ const file = new File([buffer], filename, { type: mimeType });
35
+ try {
36
+ const { uploadUrl } = getConfig();
37
+ const response = await fetch(uploadUrl, {
38
+ method: 'POST',
39
+ body: file,
40
+ });
41
+ const responseText = await response.text();
42
+ console.error(`[MCP] 上传响应: ${responseText}`);
43
+ let result;
44
+ try {
45
+ result = JSON.parse(responseText);
46
+ }
47
+ catch {
48
+ throw new Error(`上传响应解析失败: ${responseText}`);
49
+ }
50
+ if (result.dm_error) {
51
+ throw new Error(`上传失败 (${result.dm_error}): ${result.error_msg ?? '未知错误'}`);
52
+ }
53
+ if (!result.url) {
54
+ throw new Error(`上传响应缺少 url 字段: ${responseText}`);
55
+ }
56
+ return result.url;
57
+ }
58
+ catch (error) {
59
+ if (error instanceof Error && (error.message.startsWith('上传') || error.message.includes('dm_error'))) {
60
+ throw error;
61
+ }
62
+ throw new Error(`上传请求失败: ${error instanceof Error ? error.message : String(error)}`);
63
+ }
64
+ }
65
+ //# sourceMappingURL=uploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uploader.js","sourceRoot":"","sources":["../../src/services/uploader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { CompressionOptions } from '../types/index.js';
2
+ /**
3
+ * AVIF 压缩策略
4
+ *
5
+ * 自动模式:lossless=true (无损)
6
+ * 手动模式:使用指定 quality(默认 50)
7
+ */
8
+ export declare function compressAvif(buffer: Buffer, options: CompressionOptions): Promise<Buffer>;
9
+ //# sourceMappingURL=avif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"avif.d.ts","sourceRoot":"","sources":["../../src/strategies/avif.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D;;;;;GAKG;AACH,wBAAsB,YAAY,CAC9B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAmBjB"}