anagashima82/mcp-excel-server
3.1
If you are the rightful owner of mcp-excel-server and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to dayong@mcphub.com.
This document provides a comprehensive guide to setting up an MCP server for Excel operations using Dify and openpyxl.
Tools
7
Resources
0
Prompts
0
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サーバーを追加
- 上部メニューから ツール をクリック
- MCP タブを選択
- MCPサーバー(HTTP)を追加 をクリック
- 以下を入力:
| 項目 | 値 |
|---|---|
| サーバーURL | http://host.docker.internal:8000/mcp |
| 名前 | Excel操作 |
| サーバー識別子 | excel-mcp |
- 保存 をクリック
重要:
localhostではなくhost.docker.internalを使用してください。 これはDockerコンテナからホストPCにアクセスするためのホスト名です。
2-3. 接続確認
- 「認証済み」と表示され、7個のツールが認識されればOK
手順3: ワークフローで使用
3-1. ワークフロー作成
- スタジオで新規ワークフローを作成
- + → ツール をクリック
- MCP タブから Excel操作 を選択
- 使いたいツールを選択(例:
create_excel)
3-2. create_excel の設定例
| パラメータ | 値 |
|---|---|
| filename | test.xlsx |
| data | [["名前", "年齢"], ["太郎", "25"], ["花子", "30"]] |
| sheet_name | Sheet1 |
3-3. 実行
テスト実行すると ~/Documents/DifyExcel/test.xlsx にファイルが作成されます。
利用可能なツール一覧
| ツール名 | 説明 |
|---|---|
create_excel | 新規Excelファイル作成 |
read_excel | Excelファイル読み込み |
write_cell | 特定セルに書き込み |
write_range | 範囲に書き込み |
list_sheets | シート一覧取得 |
add_sheet | シート追加 |
list_files | ファイル一覧取得 |
トラブルシューティング
MCPサーバーに接続できない
-
MCPサーバーが起動しているか確認
curl http://localhost:8000/mcp -
Difyの設定で
host.docker.internalを使用しているか確認
ファイルが作成されない
- 出力ディレクトリ
~/Documents/DifyExcelが存在するか確認 - MCPサーバーのログでエラーを確認
注意事項
- MCPサーバーはDifyを使用する間、起動したままにしてください
- Excelファイルは
~/Documents/DifyExcelに保存されます - サンドボックスの制限を回避するため、MCPサーバー経由でopenpyxlを実行しています