This commit is contained in:
2026-02-12 16:47:20 +08:00
parent 1b4f81a9bc
commit 53eb25b98e
3 changed files with 61 additions and 25 deletions

View File

@@ -6,11 +6,6 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
WORKDIR /app WORKDIR /app
# 安装系统依赖Pandoc
RUN apt-get update \
&& apt-get install -y --no-install-recommends pandoc \
&& rm -rf /var/lib/apt/lists/*
# 安装 Python 依赖 # 安装 Python 依赖
COPY requirements.txt . COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt
@@ -18,7 +13,8 @@ RUN pip install --no-cache-dir -r requirements.txt
# 拷贝代码和相关资源(包括 ref.docx、color.lua 等) # 拷贝代码和相关资源(包括 ref.docx、color.lua 等)
COPY . . COPY . .
# 默认启动 MCP 服务 # SSE MCP 服务默认端口
CMD ["python", "mcp_docx_server.py"] EXPOSE 8080
# 默认以 SSE 模式启动 MCP 服务器,支持远程调用
CMD ["python", "mcp_docx_server.py", "--transport", "sse", "--host", "0.0.0.0", "--port", "8080"]

View File

@@ -7,12 +7,9 @@ services:
dockerfile: Dockerfile dockerfile: Dockerfile
container_name: mcp-docx-server container_name: mcp-docx-server
working_dir: /app working_dir: /app
# MCP 通常通过标准输入/输出与客户端通信,因此不需要暴露端口 # SSE MCP 服务端口
stdin_open: true ports:
tty: true - "8080:8080"
volumes: # 可选:挂载数据目录供 DOCX 读写
# 可选:将当前目录挂载到容器内,便于共享 ref.docx、color.lua 和输出文件 # volumes:
- ./:/app # - ./data:/data
command: ["python", "mcp_docx_server.py"]

View File

@@ -6,25 +6,42 @@
- list_docx_images列出 DOCX 中的图片信息 - list_docx_images列出 DOCX 中的图片信息
- edit_docx: 进行文本替换 / 关键字上色 / 图片替换 - edit_docx: 进行文本替换 / 关键字上色 / 图片替换
支持两种传输方式:
- stdio默认本地使用
- sse远程调用通过 HTTP SSE 协议)
用法:
# 本地 stdio 模式
python mcp_docx_server.py
# SSE 远程模式(默认 0.0.0.0:8080
python mcp_docx_server.py --transport sse
python mcp_docx_server.py --transport sse --host 0.0.0.0 --port 8080
# 客户端连接地址:
# SSE 端点: http://<host>:<port>/sse
# 消息端点: http://<host>:<port>/messages/
注意:底层仍然完全复用 mcp_docx.py 中的逻辑,只是通过 MCP SDK 对外提供。 注意:底层仍然完全复用 mcp_docx.py 中的逻辑,只是通过 MCP SDK 对外提供。
""" """
import argparse
import os import os
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from mcp.server.fastmcp import FastMCPServer from mcp.server.fastmcp import FastMCP
from mcp_docx import get_images_info, process, _parse_span_replacement from mcp_docx import get_images_info, process, _parse_span_replacement
server = FastMCPServer( mcp = FastMCP(
"docx-editor", "docx-editor",
version="0.1.0", version="0.1.0",
description="DOCX 文本和图片编辑工具(基于 mcp_docx.py 封装)", description="DOCX 文本和图片编辑工具(基于 mcp_docx.py 封装)",
) )
@server.tool() @mcp.tool()
async def list_docx_images(docx_path: str) -> List[Dict[str, Any]]: async def list_docx_images(docx_path: str) -> List[Dict[str, Any]]:
""" """
列出指定 DOCX 文件中的所有图片信息。 列出指定 DOCX 文件中的所有图片信息。
@@ -36,7 +53,6 @@ async def list_docx_images(docx_path: str) -> List[Dict[str, Any]]:
- 图片信息列表,每一项包含: - 图片信息列表,每一项包含:
- index: 图片在文档中的顺序(从 1 开始) - index: 图片在文档中的顺序(从 1 开始)
- media_file: DOCX 内部的资源路径 - media_file: DOCX 内部的资源路径
- abs_path: 解包后的绝对路径(仅用于调试)
- ext: 图片扩展名 - ext: 图片扩展名
- docpr_name: Word 内部的图片名称 - docpr_name: Word 内部的图片名称
- width_cm / height_cm: 近似尺寸(厘米),可能为 None - width_cm / height_cm: 近似尺寸(厘米),可能为 None
@@ -45,13 +61,13 @@ async def list_docx_images(docx_path: str) -> List[Dict[str, Any]]:
raise FileNotFoundError(f"DOCX 文件不存在: {docx_path}") raise FileNotFoundError(f"DOCX 文件不存在: {docx_path}")
imgs = get_images_info(docx_path) imgs = get_images_info(docx_path)
# 为了避免泄露容器内部路径,可选择屏蔽 abs_path 字段 # 为了避免泄露容器内部路径,屏蔽 abs_path 字段
for img in imgs: for img in imgs:
img.pop("abs_path", None) img.pop("abs_path", None)
return imgs return imgs
@server.tool() @mcp.tool()
async def edit_docx( async def edit_docx(
input_docx: str, input_docx: str,
output_docx: str, output_docx: str,
@@ -132,5 +148,32 @@ async def edit_docx(
if __name__ == "__main__": if __name__ == "__main__":
# 通过 stdio 运行 MCP 服务器 parser = argparse.ArgumentParser(description="DOCX MCP 服务器")
server.run() parser.add_argument(
"--transport",
choices=["stdio", "sse"],
default="stdio",
help="传输方式stdio本地或 sse远程 SSE",
)
parser.add_argument(
"--host",
default="0.0.0.0",
help="SSE 模式监听地址(默认 0.0.0.0",
)
parser.add_argument(
"--port",
type=int,
default=8080,
help="SSE 模式监听端口(默认 8080",
)
args = parser.parse_args()
if args.transport == "sse":
# SSE 远程模式:通过 HTTP 暴露 MCP 服务
mcp.settings.host = args.host
mcp.settings.port = args.port
print(f"🚀 MCP SSE 服务器启动中 → http://{args.host}:{args.port}/sse")
mcp.run(transport="sse")
else:
# 本地 stdio 模式
mcp.run(transport="stdio")