dicom-mcp 1.1.7 → 1.2.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 +29 -0
- package/bin/dicom-mcp.js +8 -2
- package/dicom_mcp/server.py +24 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,35 @@
|
|
|
5
5
|
格式遵循 [Keep a Changelog](https://keepachangelog.com/),
|
|
6
6
|
版本号遵循 [Semantic Versioning](https://semver.org/)。
|
|
7
7
|
|
|
8
|
+
## [1.2.0] - 2025-01-13
|
|
9
|
+
|
|
10
|
+
### 新功能
|
|
11
|
+
|
|
12
|
+
- **实时下载进度反馈**: 在下载过程中向用户显示详细的进度信息
|
|
13
|
+
- 下载开始:显示下载数量、输出目录、扫描参数
|
|
14
|
+
- 下载进行中:显示逐个 URL 的处理进度 [1/N], [2/N]...
|
|
15
|
+
- 下载完成:显示每个 URL 保存的文件数
|
|
16
|
+
- 最终汇总:显示总共下载的文件数量
|
|
17
|
+
- 失败处理:显示详细的错误信息
|
|
18
|
+
|
|
19
|
+
### 改进
|
|
20
|
+
|
|
21
|
+
- **可选的 pip 进度显示**: 添加环保变量控制 pip 安装输出
|
|
22
|
+
- 默认:抑制 pip 输出(用于 Claude Desktop,避免 JSON 污染)
|
|
23
|
+
- 调试模式:设置 `DICOM_MCP_VERBOSE=1` 显示 pip 进度
|
|
24
|
+
- 用法:`DICOM_MCP_VERBOSE=1 npx dicom-mcp@latest`
|
|
25
|
+
|
|
26
|
+
## [1.1.8] - 2025-01-13
|
|
27
|
+
|
|
28
|
+
### 修复
|
|
29
|
+
|
|
30
|
+
- **pip 输出完全抑制**: 彻底解决 pip 安装大量日志污染 JSON 消息流
|
|
31
|
+
- 原因:pip 的 stdout 包含 Looking in、Installing、Requirements 等大量进度信息
|
|
32
|
+
- 解决:
|
|
33
|
+
- 添加 `-q`(quiet)参数到 pip 命令
|
|
34
|
+
- 改用 `stdio: 'pipe'` 完全抑制 stdout 输出
|
|
35
|
+
- 影响:MCP Inspector 现在可以正常运行,无 JSON 解析错误
|
|
36
|
+
|
|
8
37
|
## [1.1.7] - 2025-01-13
|
|
9
38
|
|
|
10
39
|
### 修复
|
package/bin/dicom-mcp.js
CHANGED
|
@@ -68,8 +68,14 @@ function installLocalPackage(pythonCmd) {
|
|
|
68
68
|
process.exit(1);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
// Check if verbose mode is enabled (for debugging)
|
|
72
|
+
const verbose = process.env.DICOM_MCP_VERBOSE === '1' || process.env.DICOM_MCP_VERBOSE === 'true';
|
|
73
|
+
const quietFlag = verbose ? '' : '-q';
|
|
74
|
+
const stdioOption = verbose ? 'inherit' : 'pipe';
|
|
75
|
+
|
|
76
|
+
// Install with optional verbosity
|
|
77
|
+
execSync(`${pythonCmd} -m pip install ${quietFlag} -e "${rootDir}"`, {
|
|
78
|
+
stdio: stdioOption,
|
|
73
79
|
});
|
|
74
80
|
console.error('✓ Local dicom_mcp package installed');
|
|
75
81
|
} catch (error) {
|
package/dicom_mcp/server.py
CHANGED
|
@@ -266,14 +266,15 @@ async def run_multi_download(
|
|
|
266
266
|
cmd.extend(["--max-rounds", str(max_rounds)])
|
|
267
267
|
cmd.extend(["--step-wait-ms", str(step_wait_ms)])
|
|
268
268
|
|
|
269
|
-
# Show progress banner (to stderr,
|
|
269
|
+
# Show progress banner (to stderr, visible to Claude)
|
|
270
270
|
print("\n" + "=" * 70, file=sys.stderr)
|
|
271
271
|
print("🚀 DICOM 下载开始", file=sys.stderr)
|
|
272
272
|
print("=" * 70, file=sys.stderr)
|
|
273
273
|
print(f"📍 下载数量: {len(urls)} 个URL", file=sys.stderr)
|
|
274
274
|
print(f"📁 输出目录: {output_parent}", file=sys.stderr)
|
|
275
275
|
print(f"⚙️ 扫描次数: {max_rounds}, 帧间延迟: {step_wait_ms}ms", file=sys.stderr)
|
|
276
|
-
print("⏳ 请稍候,下载中... (可能需要 2-10 分钟)
|
|
276
|
+
print("⏳ 请稍候,下载中... (可能需要 2-10 分钟)", file=sys.stderr)
|
|
277
|
+
print("", file=sys.stderr)
|
|
277
278
|
|
|
278
279
|
# Run subprocess with real-time output streaming
|
|
279
280
|
process = await asyncio.create_subprocess_exec(
|
|
@@ -292,15 +293,19 @@ async def run_multi_download(
|
|
|
292
293
|
|
|
293
294
|
if returncode == 0:
|
|
294
295
|
print("\n" + "=" * 70, file=sys.stderr)
|
|
295
|
-
print("✅
|
|
296
|
-
print("=" * 70
|
|
296
|
+
print("✅ 下载完成!", file=sys.stderr)
|
|
297
|
+
print("=" * 70, file=sys.stderr)
|
|
298
|
+
print("📊 处理结果中...", file=sys.stderr)
|
|
299
|
+
print("", file=sys.stderr)
|
|
297
300
|
|
|
298
301
|
# Parse output directories from stdout
|
|
299
302
|
results = []
|
|
300
|
-
for url in urls:
|
|
303
|
+
for idx, url in enumerate(urls, 1):
|
|
301
304
|
# Extract share_id and construct output dir
|
|
302
305
|
from common_utils import extract_share_id
|
|
303
306
|
|
|
307
|
+
print(f"[{idx}/{len(urls)}] 处理: {url}", file=sys.stderr)
|
|
308
|
+
|
|
304
309
|
share_id = extract_share_id(url)
|
|
305
310
|
out_dir = os.path.join(output_parent, share_id)
|
|
306
311
|
file_count = count_files_recursive(out_dir)
|
|
@@ -310,6 +315,8 @@ async def run_multi_download(
|
|
|
310
315
|
else None
|
|
311
316
|
)
|
|
312
317
|
|
|
318
|
+
print(f" ✓ 已保存 {file_count} 个文件到: {out_dir}", file=sys.stderr)
|
|
319
|
+
|
|
313
320
|
results.append(
|
|
314
321
|
DownloadResult(
|
|
315
322
|
success=True,
|
|
@@ -320,13 +327,21 @@ async def run_multi_download(
|
|
|
320
327
|
file_count=file_count,
|
|
321
328
|
)
|
|
322
329
|
)
|
|
330
|
+
|
|
331
|
+
# Final summary
|
|
332
|
+
total_files = sum(r.file_count or 0 for r in results)
|
|
333
|
+
print("=" * 70, file=sys.stderr)
|
|
334
|
+
print(f"📈 汇总: 共下载 {total_files} 个文件", file=sys.stderr)
|
|
335
|
+
print("=" * 70, file=sys.stderr)
|
|
336
|
+
print("", file=sys.stderr)
|
|
323
337
|
return results
|
|
324
338
|
else:
|
|
325
339
|
error_msg = stderr if stderr else "Unknown error"
|
|
326
|
-
print("\n" + "=" * 70)
|
|
327
|
-
print("❌ 下载失败")
|
|
328
|
-
print("=" * 70)
|
|
329
|
-
print(f"错误信息: {error_msg}
|
|
340
|
+
print("\n" + "=" * 70, file=sys.stderr)
|
|
341
|
+
print("❌ 下载失败", file=sys.stderr)
|
|
342
|
+
print("=" * 70, file=sys.stderr)
|
|
343
|
+
print(f"错误信息: {error_msg}", file=sys.stderr)
|
|
344
|
+
print("", file=sys.stderr)
|
|
330
345
|
return [
|
|
331
346
|
DownloadResult(
|
|
332
347
|
success=False,
|