From 53eb25b98ebe0e24764b3faa8e04c3f506d2fed6 Mon Sep 17 00:00:00 2001 From: liangweihao <734499798@qq.com> Date: Thu, 12 Feb 2026 16:47:20 +0800 Subject: [PATCH] sse mcp --- Dockerfile | 12 ++++------ docker-compose.yml | 15 +++++------- mcp_docx_server.py | 59 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 61 insertions(+), 25 deletions(-) diff --git a/Dockerfile b/Dockerfile index 391bff7..1dec5ca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,11 +6,6 @@ ENV PYTHONDONTWRITEBYTECODE=1 \ WORKDIR /app -# 安装系统依赖(Pandoc) -RUN apt-get update \ - && apt-get install -y --no-install-recommends pandoc \ - && rm -rf /var/lib/apt/lists/* - # 安装 Python 依赖 COPY 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 等) COPY . . -# 默认启动 MCP 服务器 -CMD ["python", "mcp_docx_server.py"] - +# SSE MCP 服务默认端口 +EXPOSE 8080 +# 默认以 SSE 模式启动 MCP 服务器,支持远程调用 +CMD ["python", "mcp_docx_server.py", "--transport", "sse", "--host", "0.0.0.0", "--port", "8080"] diff --git a/docker-compose.yml b/docker-compose.yml index d20e172..e6836cb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,12 +7,9 @@ services: dockerfile: Dockerfile container_name: mcp-docx-server working_dir: /app - # MCP 通常通过标准输入/输出与客户端通信,因此不需要暴露端口 - stdin_open: true - tty: true - volumes: - # 可选:将当前目录挂载到容器内,便于共享 ref.docx、color.lua 和输出文件 - - ./:/app - command: ["python", "mcp_docx_server.py"] - - + # SSE MCP 服务端口 + ports: + - "8080:8080" + # 可选:挂载数据目录供 DOCX 读写 + # volumes: + # - ./data:/data diff --git a/mcp_docx_server.py b/mcp_docx_server.py index 2160aa6..aed12d5 100644 --- a/mcp_docx_server.py +++ b/mcp_docx_server.py @@ -6,25 +6,42 @@ - list_docx_images:列出 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://:/sse + # 消息端点: http://:/messages/ + 注意:底层仍然完全复用 mcp_docx.py 中的逻辑,只是通过 MCP SDK 对外提供。 """ +import argparse import os 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 -server = FastMCPServer( +mcp = FastMCP( "docx-editor", version="0.1.0", description="DOCX 文本和图片编辑工具(基于 mcp_docx.py 封装)", ) -@server.tool() +@mcp.tool() async def list_docx_images(docx_path: str) -> List[Dict[str, Any]]: """ 列出指定 DOCX 文件中的所有图片信息。 @@ -36,7 +53,6 @@ async def list_docx_images(docx_path: str) -> List[Dict[str, Any]]: - 图片信息列表,每一项包含: - index: 图片在文档中的顺序(从 1 开始) - media_file: DOCX 内部的资源路径 - - abs_path: 解包后的绝对路径(仅用于调试) - ext: 图片扩展名 - docpr_name: Word 内部的图片名称 - 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}") imgs = get_images_info(docx_path) - # 为了避免泄露容器内部路径,可选择屏蔽 abs_path 字段 + # 为了避免泄露容器内部路径,屏蔽 abs_path 字段 for img in imgs: img.pop("abs_path", None) return imgs -@server.tool() +@mcp.tool() async def edit_docx( input_docx: str, output_docx: str, @@ -132,5 +148,32 @@ async def edit_docx( if __name__ == "__main__": - # 通过 stdio 运行 MCP 服务器 - server.run() \ No newline at end of file + parser = argparse.ArgumentParser(description="DOCX MCP 服务器") + 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")