Excel操作MCP服务器

通过Dify实现本地Excel操作的MCP服务器,支持Excel文件的创建、读写和管理。

  • by anagashima82
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 anagashima82/mcp-excel-server

使用说明

Dify + openpyxl MCP服务器生成过程

Dify从本地Excel用于进行操作MCP服务器构建过程。

前提条件

  • Docker / Docker Desktop 已安装
  • Python 3.10已安装
  • Dify 的Docker 已启动

步骤1:MCP服务器设置

1-1.创建目录

mkdir -p mcp-excel-server
cd mcp-excel-server

1-2. server.py 创建

#!/usr/bin/env python3
"""
Excel操作用MCPサーバー
Difyからローカルでエクセルを操作するためのサーバー
"""

import json
import os
from typing import Any
from mcp.server.fastmcp import FastMCP
from openpyxl import Workbook, load_workbook

# MCPサーバー作成
mcp = FastMCP("excel-server")

# デフォルトの出力ディレクトリ
OUTPUT_DIR = os.path.expanduser("~/Documents/DifyExcel")
os.makedirs(OUTPUT_DIR, exist_ok=True)


@mcp.tool()
def create_excel(filename: str, data: list[list[str]], sheet_name: str = "Sheet1") -> str:
    """
    新しいExcelファイルを作成します。

    Args:
        filename: ファイル名(例: "report.xlsx")
        data: 2次元配列のデータ(例: [["A1", "B1"], ["A2", "B2"]])
        sheet_name: シート名(デフォルト: "Sheet1")

    Returns:
        作成したファイルのパス
    """
    wb = Workbook()
    ws = wb.active
    ws.title = sheet_name

    for row_idx, row in enumerate(data, 1):
        for col_idx, value in enumerate(row, 1):
            ws.cell(row=row_idx, column=col_idx, value=value)

    filepath = os.path.join(OUTPUT_DIR, filename)
    wb.save(filepath)
    return f"ファイルを作成しました: {filepath}"


@mcp.tool()
def read_excel(filepath: str, sheet_name: str = None) -> dict:
    """
    Excelファイルを読み込みます。

    Args:
        filepath: ファイルパス
        sheet_name: シート名(省略時は最初のシート)

    Returns:
        シートのデータ
    """
    if not os.path.isabs(filepath):
        filepath = os.path.join(OUTPUT_DIR, filepath)

    wb = load_workbook(filepath, data_only=True)
    ws = wb[sheet_name] if sheet_name else wb.active

    data = []
    for row in ws.iter_rows():
        data.append([cell.value for cell in row])

    return {
        "sheet_name": ws.title,
        "data": data,
        "row_count": len(data),
        "col_count": len(data[0]) if data else 0
    }


@mcp.tool()
def write_cell(filepath: str, cell: str, value: str, sheet_name: str = None) -> str:
    """
    Excelファイルの特定セルに書き込みます。

    Args:
        filepath: ファイルパス
        cell: セル位置(例: "A1", "B2")
        value: 書き込む値
        sheet_name: シート名(省略時は最初のシート)

    Returns:
        結果メッセージ
    """
    if not os.path.isabs(filepath):
        filepath = os.path.join(OUTPUT_DIR, filepath)

    wb = load_workbook(filepath)
    ws = wb[sheet_name] if sheet_name else wb.active
    ws[cell] = value
    wb.save(filepath)

    return f"セル {cell} に '{value}' を書き込みました"


@mcp.tool()
def write_range(filepath: str, start_cell: str, data: list[list[str]], sheet_name: str = None) -> str:
    """
    Excelファイルの範囲に書き込みます。

    Args:
        filepath: ファイルパス
        start_cell: 開始セル(例: "A1")
        data: 2次元配列のデータ
        sheet_name: シート名(省略時は最初のシート)

    Returns:
        結果メッセージ
    """
    if not os.path.isabs(filepath):
        filepath = os.path.join(OUTPUT_DIR, filepath)

    wb = load_workbook(filepath)
    ws = wb[sheet_name] if sheet_name else wb.active

    from openpyxl.utils import coordinate_from_string, column_index_from_string
    col_letter, start_row = coordinate_from_string(start_cell)
    start_col = column_index_from_string(col_letter)

    for row_idx, row in enumerate(data):
        for col_idx, value in enumerate(row):
            ws.cell(row=start_row + row_idx, column=start_col + col_idx, value=value)

    wb.save(filepath)
    return f"{start_cell}から{len(data)}行x{len(data[0]) if data else 0}列を書き込みました"


@mcp.tool()
def list_sheets(filepath: str) -> list[str]:
    """
    Excelファイルのシート一覧を取得します。

    Args:
        filepath: ファイルパス

    Returns:
        シート名のリスト
    """
    if not os.path.isabs(filepath):
        filepath = os.path.join(OUTPUT_DIR, filepath)

    wb = load_workbook(filepath)
    return wb.sheetnames


@mcp.tool()
def add_sheet(filepath: str, sheet_name: str) -> str:
    """
    Excelファイルに新しいシートを追加します。

    Args:
        filepath: ファイルパス
        sheet_name: 新しいシート名

    Returns:
        結果メッセージ
    """
    if not os.path.isabs(filepath):
        filepath = os.path.join(OUTPUT_DIR, filepath)

    wb = load_workbook(filepath)
    wb.create_sheet(sheet_name)
    wb.save(filepath)

    return f"シート '{sheet_name}' を追加しました"


@mcp.tool()
def list_files() -> list[str]:
    """
    出力ディレクトリのExcelファイル一覧を取得します。

    Returns:
        ファイル名のリスト
    """
    files = [f for f in os.listdir(OUTPUT_DIR) if f.endswith(('.xlsx', '.xls'))]
    return files


if __name__ == "__main__":
    mcp.run(transport="streamable-http")

1-3. requirements.txt 创建

mcp[cli]>=1.0.0
openpyxl>=3.1.0

1-4.依赖性安装

python3 -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate
pip install -r requirements.txt

1-5. MCP服务器启动

source venv/bin/activate
python server.py

启动后显示如下:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

步骤2:Dify的MCP注册工具

2-1. Dify打开管理屏幕

在浏览器中 http://localhost 访问

2-2. MCP添加服务器

  1. 单击功能区上 工具 来修改标记元素的显示属性
  2. 主控程序 选择选项卡
  3. MCP添加服务器(HTTP) 来修改标记元素的显示属性
  4. 输入:
项目 値
服务器URL http://host.docker.internal:8000/mcp
名前 Excel操作
服务器标识符 excel-mcp
  1. 保存 来修改标记元素的显示属性

重要: localhost 不是,不是 host.docker.internal 中所述修改相应参数的值。 这是Docker从容器到主机PC中所述修改相应参数的值。

2-3.接続确认

  • 显示“已认证”,如果识别出7个工具OK

步骤3:用于工作流

3-1.创建工作流

  1. 在工作室中创建新工作流
  2. + → 工具 来修改标记元素的显示属性
  3. 主控程序 在工作空间的边缘 Excel操作 列表框中,此格式对应于条目“无”
  4. 选择要使用的工具(例如: create_excel)

3-2. create_excel 设置示例

参数|值| |-----------|-----| |文件名| test.xlsx | |数据| [["名前", "年齢"], ["太郎", "25"], ["花子", "30"]] | |图纸名称| Sheet1 |

3-3. 実行

测试运行时 ~/Documents/DifyExcel/test.xlsx 中所述修改相应参数的值。


可用工具列表

工具名称|说明| |---------|------| | create_excel 新建Excel文件创建 | read_excel | Excel文件读取 | write_cell |写入特定单元格| | write_range 写入范围 | list_sheets 获取工作表列表 | add_sheet 添加工作表 | list_files 获取文件列表


故障排除

MCP无法连接到服务器

  1. MCP确认服务器是否启动

    curl http://localhost:8000/mcp
    
  2. Dify在工作空间的边缘 host.docker.internal 确认是否使用

未创建文件

  • 输出目录 ~/Documents/DifyExcel 确认是否存在
  • MCP在服务器日志中检查错误

注意事项

  • MCP服务器是Dify中选择所需的墙类型
  • Excel文件是 ~/Documents/DifyExcel 将条目添加到文档注册表
  • 在动态输入提示中单击MCP通过服务器openpyxl正在运行