@zzp123/mcp-zentao 1.6.0 → 1.7.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/CHANGELOG.md +36 -0
- package/README.md +4 -5
- package/dist/api/zentaoApi.d.ts +1 -0
- package/dist/api/zentaoApi.js +4 -0
- package/dist/index.js +51 -25
- package/package.json +1 -1
- package/scripts/get_clipboard.ps1 +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.7.0] - 2025-11-06
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **图片上传自动生成 HTML 格式**
|
|
12
|
+
- `uploadFile` 工具现在返回 `imageHtml` 字段,包含禅道所需的完整 HTML 代码
|
|
13
|
+
- `uploadImageFromClipboard` 工具同样返回 `imageHtml` 字段
|
|
14
|
+
- 新增 `imageUrl` 字段,提供完整的图片访问地址
|
|
15
|
+
- 新增 `fileId` 字段,方便后续引用
|
|
16
|
+
- 新增使用提示 `tip` 字段,帮助用户正确使用
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
- ZentaoAPI 类新增 `getConfig()` 方法,允许获取配置信息以生成图片 URL
|
|
20
|
+
- 图片上传返回格式优化,Claude Code 现在能自动识别并使用正确的 HTML 格式
|
|
21
|
+
|
|
22
|
+
### Technical
|
|
23
|
+
- 图片 HTML 格式:`<img onload="setImageSize(this,0)" src="..." alt="..." />`
|
|
24
|
+
- 自动包含 `onload="setImageSize(this,0)"` 以确保图片在禅道中正确显示
|
|
25
|
+
|
|
26
|
+
### Benefits
|
|
27
|
+
- **提升用户体验**:Claude Code 无需手动构造 HTML 代码
|
|
28
|
+
- **减少错误**:避免手动拼接 HTML 时的格式错误
|
|
29
|
+
- **更直观**:返回结果中直接包含可用的 HTML 代码
|
|
30
|
+
|
|
31
|
+
## [1.6.1] - 2025-11-05
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- **修复 Windows 剪贴板图片读取问题**
|
|
35
|
+
- 替换为新的 PowerShell 脚本 `scripts/get_clipboard.ps1`
|
|
36
|
+
- 使用 `Add-Type` 加载 `System.Drawing` 程序集,确保正确处理图片
|
|
37
|
+
- 改进错误处理,提供更详细的错误信息
|
|
38
|
+
- 使用 `-ExecutionPolicy Bypass` 确保脚本可以执行
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
- Windows 平台现在使用外部 PowerShell 脚本文件而非内联脚本
|
|
42
|
+
- 优化了 base64 转换流程,确保内存流正确关闭
|
|
43
|
+
|
|
8
44
|
## [1.6.0] - 2025-11-05
|
|
9
45
|
|
|
10
46
|
### Changed - 重大更新
|
package/README.md
CHANGED
|
@@ -15,11 +15,10 @@ npm install @zzp123/mcp-zentao -g
|
|
|
15
15
|
|
|
16
16
|
查看完整的版本更新历史,请访问 [CHANGELOG.md](./CHANGELOG.md)
|
|
17
17
|
|
|
18
|
-
**最新版本**: v1.6.
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- ⚠️ Breaking Change: getModules 返回类型变更
|
|
18
|
+
**最新版本**: v1.6.1
|
|
19
|
+
- 修复 Windows 剪贴板图片读取问题
|
|
20
|
+
- 使用新的 PowerShell 脚本确保正确读取剪贴板图片
|
|
21
|
+
- 改进错误处理和日志输出
|
|
23
22
|
|
|
24
23
|
**主要版本**:
|
|
25
24
|
- v1.4.1 - 修复 uploadImageFromClipboard 返回值问题
|
package/dist/api/zentaoApi.d.ts
CHANGED
|
@@ -158,4 +158,5 @@ export declare class ZentaoAPI {
|
|
|
158
158
|
getModules(type: ModuleType, id: number, fields?: string): Promise<ModulesResponse>;
|
|
159
159
|
uploadFile(uploadRequest: UploadFileRequest): Promise<FileUploadResponse>;
|
|
160
160
|
downloadFile(fileId: number): Promise<Buffer>;
|
|
161
|
+
getConfig(): ZentaoConfig;
|
|
161
162
|
}
|
package/dist/api/zentaoApi.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -988,8 +988,17 @@ server.tool("uploadFile", {
|
|
|
988
988
|
filename: finalFilename,
|
|
989
989
|
uid
|
|
990
990
|
});
|
|
991
|
+
// 生成禅道需要的 HTML 格式
|
|
992
|
+
const fileId = result.id;
|
|
993
|
+
const baseUrl = zentaoApi.getConfig().url;
|
|
994
|
+
const imageUrl = `${baseUrl}/zentao/entao/api.php?m=file&f=read&t=png&fileID=${fileId}`;
|
|
995
|
+
const imageHtml = `<img onload="setImageSize(this,0)" src="${imageUrl}" alt="${finalFilename}" />`;
|
|
991
996
|
const response = {
|
|
992
997
|
upload: result,
|
|
998
|
+
fileId: fileId,
|
|
999
|
+
imageUrl: imageUrl,
|
|
1000
|
+
imageHtml: imageHtml,
|
|
1001
|
+
tip: `更新 Bug 描述时,请使用 imageHtml 字段中的 HTML 代码`
|
|
993
1002
|
};
|
|
994
1003
|
if (savedPath) {
|
|
995
1004
|
response.savedPath = savedPath;
|
|
@@ -1017,41 +1026,49 @@ server.tool("uploadImageFromClipboard", {
|
|
|
1017
1026
|
// 读取系统剪贴板图片
|
|
1018
1027
|
let fileBuffer;
|
|
1019
1028
|
let finalFilename;
|
|
1020
|
-
// Windows: 使用 PowerShell
|
|
1029
|
+
// Windows: 使用 PowerShell 脚本读取剪贴板
|
|
1021
1030
|
if (process.platform === 'win32') {
|
|
1022
|
-
console.log('[uploadImageFromClipboard] Windows平台,使用PowerShell
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1031
|
+
console.log('[uploadImageFromClipboard] Windows平台,使用PowerShell脚本读取剪贴板...');
|
|
1032
|
+
// 使用外部 PowerShell 脚本
|
|
1033
|
+
const scriptPath = path.join(process.cwd(), 'scripts', 'get_clipboard.ps1');
|
|
1034
|
+
console.log(`[uploadImageFromClipboard] 脚本路径: ${scriptPath}`);
|
|
1035
|
+
try {
|
|
1036
|
+
const result = execSync(`powershell -ExecutionPolicy Bypass -File "${scriptPath}"`, {
|
|
1037
|
+
encoding: 'utf8',
|
|
1038
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
1039
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
1040
|
+
}).trim();
|
|
1041
|
+
if (!result || result.includes('NoImage') || result.includes('Error')) {
|
|
1042
|
+
console.error('[uploadImageFromClipboard] 剪贴板中没有图片');
|
|
1043
|
+
return {
|
|
1044
|
+
content: [{
|
|
1045
|
+
type: "text",
|
|
1046
|
+
text: JSON.stringify({
|
|
1047
|
+
error: "剪贴板中没有图片",
|
|
1048
|
+
tip: "请先复制图片,不要粘贴到输入框,直接告诉我'上传'"
|
|
1049
|
+
}, null, 2)
|
|
1050
|
+
}],
|
|
1051
|
+
isError: true
|
|
1052
|
+
};
|
|
1032
1053
|
}
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
if (!result || result.includes('NoImage') || result.includes('Error')) {
|
|
1040
|
-
console.error('[uploadImageFromClipboard] 剪贴板中没有图片');
|
|
1054
|
+
fileBuffer = Buffer.from(result, 'base64');
|
|
1055
|
+
finalFilename = filename || `clipboard_${Date.now()}.png`;
|
|
1056
|
+
console.log(`[uploadImageFromClipboard] 已读取剪贴板图片,大小: ${fileBuffer.length} bytes`);
|
|
1057
|
+
}
|
|
1058
|
+
catch (err) {
|
|
1059
|
+
console.error('[uploadImageFromClipboard] Windows读取剪贴板失败:', err);
|
|
1041
1060
|
return {
|
|
1042
1061
|
content: [{
|
|
1043
1062
|
type: "text",
|
|
1044
1063
|
text: JSON.stringify({
|
|
1045
|
-
error: "
|
|
1046
|
-
|
|
1064
|
+
error: "读取剪贴板失败",
|
|
1065
|
+
details: err.message,
|
|
1066
|
+
tip: "请确保已复制图片到剪贴板,并且 PowerShell 脚本存在于 scripts/get_clipboard.ps1"
|
|
1047
1067
|
}, null, 2)
|
|
1048
1068
|
}],
|
|
1049
1069
|
isError: true
|
|
1050
1070
|
};
|
|
1051
1071
|
}
|
|
1052
|
-
fileBuffer = Buffer.from(result, 'base64');
|
|
1053
|
-
finalFilename = filename || `clipboard_${Date.now()}.png`;
|
|
1054
|
-
console.log(`[uploadImageFromClipboard] 已读取剪贴板图片,大小: ${fileBuffer.length} bytes`);
|
|
1055
1072
|
}
|
|
1056
1073
|
// macOS: 使用 pngpaste
|
|
1057
1074
|
else if (process.platform === 'darwin') {
|
|
@@ -1121,13 +1138,22 @@ server.tool("uploadImageFromClipboard", {
|
|
|
1121
1138
|
uid
|
|
1122
1139
|
});
|
|
1123
1140
|
console.log('[uploadImageFromClipboard] 上传成功,结果:', uploadResult);
|
|
1141
|
+
// 生成禅道需要的 HTML 格式
|
|
1142
|
+
const fileId = uploadResult.id;
|
|
1143
|
+
const baseUrl = zentaoApi.getConfig().url;
|
|
1144
|
+
const imageUrl = `${baseUrl}/zentao/entao/api.php?m=file&f=read&t=png&fileID=${fileId}`;
|
|
1145
|
+
const imageHtml = `<img onload="setImageSize(this,0)" src="${imageUrl}" alt="${finalFilename}" />`;
|
|
1124
1146
|
const response = {
|
|
1125
1147
|
success: true,
|
|
1126
1148
|
upload: uploadResult,
|
|
1127
1149
|
savedPath: savedPath,
|
|
1128
1150
|
filename: finalFilename,
|
|
1129
1151
|
fileSize: fileBuffer.length,
|
|
1130
|
-
|
|
1152
|
+
fileId: fileId,
|
|
1153
|
+
imageUrl: imageUrl,
|
|
1154
|
+
imageHtml: imageHtml,
|
|
1155
|
+
message: `图片已保存到本地并上传到禅道`,
|
|
1156
|
+
tip: `更新 Bug 描述时,请使用 imageHtml 字段中的 HTML 代码`
|
|
1131
1157
|
};
|
|
1132
1158
|
console.log('[uploadImageFromClipboard] 返回结果:', response);
|
|
1133
1159
|
return {
|
package/package.json
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
2
|
+
Add-Type -AssemblyName System.Drawing
|
|
3
|
+
$img = [System.Windows.Forms.Clipboard]::GetImage()
|
|
4
|
+
if ($img) {
|
|
5
|
+
$ms = New-Object System.IO.MemoryStream
|
|
6
|
+
$img.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
|
|
7
|
+
$bytes = $ms.ToArray()
|
|
8
|
+
$ms.Close()
|
|
9
|
+
$base64 = [Convert]::ToBase64String($bytes)
|
|
10
|
+
Write-Output $base64
|
|
11
|
+
} else {
|
|
12
|
+
Write-Error "NoImage"
|
|
13
|
+
}
|