MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
MCPサーバ - KiCADのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
MCPサーバ - KiCAD
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == KiCAD MCPサーバは、電子回路設計ソフトウェアであるKiCADをAIアシスタントから操作可能にするためのModel Context Protocol (MCP) サーバである。<br> このMCPを使用することにより、Claude等のLLMがKiCADプロジェクトの管理、回路図の操作、PCBレイアウトの編集等を実行することができる。<br> <br> KiCAD MCPサーバは、以下に示すような機能を提供する。<br> * KiCADプロジェクトファイルの読み込みと解析 * 回路図の情報取得 * PCB基板レイアウトの情報取得 * コンポーネントライブラリの管理 * ネットリストの生成と検証 * Design Rule Check (DRC) の実行 * Electrical Rule Check (ERC) の実行 <br> MCPサーバの実装において、PythonまたはNode.jsを使用することができる。<br> KiCADはPython APIを提供しているため、Pythonによる実装が推奨される。<br> <br> KiCAD MCPサーバは、Standard I/O (STDIO) トランスポートを使用してローカル環境で動作する。<br> これにより、Claude DesktopやCursor等のMCPクライアントと統合することができる。<br> <br> 以下の例では、PythonとFastMCPを使用したKiCAD MCPサーバの基本構造を示している。<br> <syntaxhighlight lang="python"> from fastmcp import FastMCP import pcbnew import os mcp = FastMCP("KiCAD MCP Server") @mcp.tool() def get_board_info(kicad_pcb_path: str) -> dict: """KiCAD PCBファイルから基板情報を取得する""" try: board = pcbnew.LoadBoard(kicad_pcb_path) info = { "board_name": os.path.basename(kicad_pcb_path), "num_tracks": board.GetTracks().GetCount(), "num_modules": len(list(board.GetFootprints())), "board_thickness": board.GetDesignSettings().GetBoardThickness(), } return info except Exception as e: return {"error": str(e)} @mcp.tool() def run_drc(kicad_pcb_path: str) -> str: """Design Rule Checkを実行する""" try: board = pcbnew.LoadBoard(kicad_pcb_path) # DRCの実装 return "DRC実行完了" except Exception as e: return f"エラー: {str(e)}" if __name__ == "__main__": mcp.run() </syntaxhighlight> <br> セキュリティでは、KiCADプロジェクトファイルへのアクセス権限の管理、ファイルパスのバリデーション、適切なエラーハンドリング等を行う必要がある。<br> 特に、パストラバーサル攻撃を防ぐため、入力されたファイルパスを適切に検証する必要がある。<br> <br> パフォーマンスとスケーラビリティでは、大規模なPCBファイルの処理時間の最適化、メモリ使用量の管理が重要である。<br> また、複数のKiCADプロジェクトを同時に扱う場合は、適切なリソース管理を実装する必要がある。<br> <br> KiCAD MCPサーバを構築・運用する場合は、以下に示す事柄に注意する。<br> * KiCAD Python APIのバージョン互換性の確認 * STDIOトランスポートでは標準出力 (stdout) にログを出力しない (JSON-RPC通信が破損する) * ファイル操作の実行時間を適切に管理して、タイムアウトを設定する * エラーハンドリングを適切に実装して、詳細なエラーメッセージを返す * KiCADプロジェクトファイルのバックアップを定期的に実施 * アクセスログの監視 * ツールのバージョン管理とドキュメントの維持 <br><br> == サーバ環境のインストール == まず、システムの更新を行う。<br> # RHEL sudo dnf update # SUSE sudo zypper update # Debian sudo apt update sudo apt upgrade <br> 次に、Linuxサーバに必要な基本環境をインストールする。<br> # RHEL sudo dnf install curl wget git gcc-c++ make python3 python3-pip # SUSE sudo zypper install curl wget git gcc-c++ make python3 python3-pip # Debian sudo apt install curl wget git build-essential python3 python3-pip <br><br> == KiCADのインストール == インストールが完了したら、KiCADのバージョンを確認する。<br> kicad-cli version <br> ==== RHEL==== RHELでは、EPELリポジトリを有効化してKiCADをインストールする。<br> sudo dnf install epel-release sudo dnf install kicad kicad-doc kicad-packages3d <br> ==== SUSE ==== SUSEでは、公式リポジトリからKiCADをインストールする。<br> sudo zypper install kicad kicad-doc kicad-packages3d <br> ==== Debian ==== Debianでは、公式リポジトリからKiCADをインストールする。<br> sudo apt install kicad kicad-doc-ja kicad-libraries <br> KiCADの最新版をインストールする場合は、公式PPAを使用する。<br> sudo add-apt-repository ppa:kicad/kicad-7.0-releases sudo apt update sudo apt install kicad <br><br> == Python開発環境の準備 == ==== Python仮想環境の作成 ==== プロジェクトディレクトリを作成して、Python仮想環境を設定する。<br> mkdir -p ~/kicad-mcp-server cd ~/kicad-mcp-server python3 -m venv venv <br> Pythonの仮想環境をアクティベートする。<br> # Bash / Zshの場合 source venv/bin/activate # Fishの場合 source venv/bin/activate.fish <br> 必要なPythonライブラリをインストールする。<br> pip install fastmcp <br> ==== KiCAD Python APIのインストール ==== KiCADのPython APIは、KiCADのインストール時に自動的にインストールされる。<br> Python仮想環境からKiCAD Python APIにアクセスできるように、シンボリックリンクを作成する。<br> <br> まず、KiCAD Python APIの場所を確認する。<br> python3 -c "import sys; print([p for p in sys.path if 'kicad' in p.lower()])" <br> 通常、以下に示すディレクトリにインストールされている。<br> * RHEL / SUSE *: /usr/lib64/python3.x/site-packages/ * Debian *: /usr/lib/python3/dist-packages/pcbnew.py <br> 仮想環境からアクセスできるように設定する。<br> # RHEL / SUSE ln -s /usr/lib64/python3.x/site-packages/pcbnew.so venv/lib/python3.x/site-packages/ # Debian ln -s /usr/lib/python3/dist-packages/pcbnew.py venv/lib/python3.x/site-packages/ <br> または、~/.profileファイル等に環境変数 <code>PYTHONPATH</code> を設定する方法もある。<br> <syntaxhighlight lang="sh"> # ~/.profileファイル等 ## RHEL / SUSEの場合 export PYTHONPATH=/usr/lib64/python3.x/site-packages:$PYTHONPATH ## Debianの場合 export PYTHONPATH=/usr/lib/python3/dist-packages:$PYTHONPATH </syntaxhighlight> <br> KiCAD Python APIが正常にインポートできるか確認する。<br> python3 -c "import pcbnew; print(pcbnew.Version())" <br><br> == KiCAD MCPサーバの実装 == ==== 基本的なサーバ構造 ==== KiCAD MCPサーバの基本実装を行う。<br> <syntaxhighlight lang="python"> # server.pyファイル from fastmcp import FastMCP import pcbnew import os from pathlib import Path mcp = FastMCP("KiCAD MCP Server") @mcp.tool() def load_board(kicad_pcb_path: str) -> dict: """KiCAD PCBファイルを読み込み、基本情報を取得する""" try: if not os.path.exists(kicad_pcb_path): return {"error": "ファイルが見つかりません"} if not kicad_pcb_path.endswith('.kicad_pcb'): return {"error": "KiCAD PCBファイルではありません"} board = pcbnew.LoadBoard(kicad_pcb_path) info = { "board_name": os.path.basename(kicad_pcb_path), "layer_count": board.GetCopperLayerCount(), "board_thickness": board.GetDesignSettings().GetBoardThickness() / 1000000.0, "track_count": board.GetTracks().GetCount(), "footprint_count": len(list(board.GetFootprints())), } return info except Exception as e: return {"error": f"PCB読み込みエラー: {str(e)}"} @mcp.tool() def get_footprints(kicad_pcb_path: str) -> list: """基板上のフットプリント一覧を取得する""" try: board = pcbnew.LoadBoard(kicad_pcb_path) footprints = [] for footprint in board.GetFootprints(): fp_info = { "reference": footprint.GetReference(), "value": footprint.GetValue(), "footprint": footprint.GetFPID().GetLibItemName().GetUniChar(), "layer": footprint.GetLayerName(), } footprints.append(fp_info) return footprints except Exception as e: return [{"error": str(e)}] @mcp.tool() def get_net_list(kicad_pcb_path: str) -> list: """ネットリストを取得する""" try: board = pcbnew.LoadBoard(kicad_pcb_path) nets = [] for net in board.GetNetInfo().NetsByName(): net_info = { "net_code": net[1].GetNetCode(), "net_name": net[1].GetNetname(), } nets.append(net_info) return nets except Exception as e: return [{"error": str(e)}] @mcp.tool() def run_drc(kicad_pcb_path: str) -> dict: """Design Rule Checkを実行する""" try: board = pcbnew.LoadBoard(kicad_pcb_path) # DRC設定の取得 drc_settings = board.GetDesignSettings() # 簡易的なDRCチェック track_width = drc_settings.m_TrackMinWidth / 1000000.0 clearance = drc_settings.m_MinClearance / 1000000.0 result = { "min_track_width": track_width, "min_clearance": clearance, "status": "DRCチェック完了", } return result except Exception as e: return {"error": f"DRCエラー: {str(e)}"} @mcp.tool() def get_board_outline(kicad_pcb_path: str) -> dict: """基板外形の寸法を取得する""" try: board = pcbnew.LoadBoard(kicad_pcb_path) bbox = board.GetBoardEdgesBoundingBox() dimensions = { "width": bbox.GetWidth() / 1000000.0, "height": bbox.GetHeight() / 1000000.0, "area": (bbox.GetWidth() * bbox.GetHeight()) / 1000000000000.0, } return dimensions except Exception as e: return {"error": str(e)} @mcp.tool() def export_gerber(kicad_pcb_path: str, output_dir: str) -> str: """Gerberファイルを出力する""" try: board = pcbnew.LoadBoard(kicad_pcb_path) if not os.path.exists(output_dir): os.makedirs(output_dir) plot_controller = pcbnew.PLOT_CONTROLLER(board) plot_options = plot_controller.GetPlotOptions() plot_options.SetOutputDirectory(output_dir) plot_options.SetPlotFrameRef(False) plot_options.SetLineWidth(pcbnew.FromMM(0.1)) # レイヤーごとにプロット layers = [ ("F.Cu", pcbnew.F_Cu, "Top Copper"), ("B.Cu", pcbnew.B_Cu, "Bottom Copper"), ("F.Mask", pcbnew.F_Mask, "Top Soldermask"), ("B.Mask", pcbnew.B_Mask, "Bottom Soldermask"), ("F.SilkS", pcbnew.F_SilkS, "Top Silkscreen"), ("B.SilkS", pcbnew.B_SilkS, "Bottom Silkscreen"), ("Edge.Cuts", pcbnew.Edge_Cuts, "Board Outline"), ] for layer_info in layers: plot_controller.SetLayer(layer_info[1]) plot_controller.OpenPlotfile(layer_info[0], pcbnew.PLOT_FORMAT_GERBER, layer_info[2]) plot_controller.PlotLayer() plot_controller.ClosePlot() return f"Gerberファイルを {output_dir} に出力しました" except Exception as e: return f"エラー: {str(e)}" if __name__ == "__main__": mcp.run() </syntaxhighlight> <br> ==== エラーハンドリング ==== 本番環境では、詳細なエラーハンドリングを定義する。<br> <syntaxhighlight lang="python"> import logging from typing import Optional # ログ設定 (stderrに出力) logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[logging.StreamHandler()] ) logger = logging.getLogger(__name__) def safe_load_board(kicad_pcb_path: str) -> Optional[pcbnew.BOARD]: """安全にKiCAD PCBファイルを読み込む""" try: # パスバリデーション path = Path(kicad_pcb_path).resolve() # パストラバーサル攻撃を防ぐ if '..' in str(path): logger.error(f"無効なパス: {kicad_pcb_path}") return None if not path.exists(): logger.error(f"ファイルが存在しません: {kicad_pcb_path}") return None if not str(path).endswith('.kicad_pcb'): logger.error(f"KiCAD PCBファイルではありません: {kicad_pcb_path}") return None board = pcbnew.LoadBoard(str(path)) logger.info(f"PCBファイルを読み込みました: {kicad_pcb_path}") return board except Exception as e: logger.exception(f"PCB読み込みエラー: {str(e)}") return None </syntaxhighlight> <br><br> == MCP Inspectorによるテスト == MCP Inspectorを使用して、KiCAD MCPサーバのツールをテストする。<br> <br> まず、MCP Inspectorをインストールする。<br> pip install mcp-inspector <br> MCP Inspectorを起動する。<br> mcp-inspector python server.py <br> Webブラウザが自動的に開いて、インスペクターのインターフェースが表示される。<br> <br> テスト用のKiCADプロジェクトファイルを準備して、各ツールの動作を確認する。<br> * load_board *: PCBファイルの基本情報を取得 * get_footprints *: フットプリント一覧を取得 * get_net_list *: ネットリスト一覧を取得 * run_drc *: DRCチェックの実行 * get_board_outline *: 基板外形の寸法を取得 * export_gerber *: Gerberファイルの出力 <br><br> == Systemdサービスファイルの作成 == KiCAD MCPサーバをシステムサービスとして常時起動させる場合、systemdユニットファイルを作成する。<br> <br> sudo vi /etc/systemd/system/kicad-mcp-server.service <br> <syntaxhighlight lang="ini"> # /etc/systemd/system/kicad-mcp-server.serviceファイル [Unit] Description=KiCAD MCP Server After=network.target [Service] Type=simple User=<実行する任意のユーザ名> WorkingDirectory=/home/<ユーザ名>/kicad-mcp-server ExecStart=/home/<ユーザ名>/kicad-mcp-server/venv/bin/python server.py Restart=always RestartSec=10 StandardOutput=journal StandardError=journal # 環境変数の設定 ## Debianの場合 Environment="PYTHONPATH=/usr/lib64/python3.x/site-packages" ## Debianの場合 Environment="PYTHONPATH=/usr/lib/python3/dist-packages" Environment="DISPLAY=:0" [Install] WantedBy=multi-user.target </syntaxhighlight> <br> サービスを有効化して起動する。<br> sudo systemctl daemon-reload sudo systemctl enable kicad-mcp-server sudo systemctl start kicad-mcp-server <br> サービスの状態を確認する。<br> sudo systemctl status kicad-mcp-server <br> ログを確認する。<br> sudo journalctl -u kicad-mcp-server -f <br><br> == セキュリティ設定 == ==== ファイルアクセスの制限 ==== KiCAD MCPサーバがアクセス可能なディレクトリを制限することが推奨される。<br> <br> <syntaxhighlight lang="python"> # 許可されたディレクトリのリスト ALLOWED_DIRECTORIES = [ "/home/<ユーザ名>/kicad-projects", "/home/<ユーザ名>/shared-projects", ] def is_path_allowed(file_path: str) -> bool: """ファイルパスが許可されたディレクトリ内にあるか確認する""" try: resolved_path = Path(file_path).resolve() for allowed_dir in ALLOWED_DIRECTORIES: allowed_path = Path(allowed_dir).resolve() if resolved_path.is_relative_to(allowed_path): return True return False except Exception: return False @mcp.tool() def load_board_secure(kicad_pcb_path: str) -> dict: """セキュアなPCBファイル読み込み""" if not is_path_allowed(kicad_pcb_path): return {"error": "このファイルへのアクセスは許可されていません"} # 以降の処理 </syntaxhighlight> <br> ==== 入力データのバリデーション ==== ツールのパラメータに対して、適切なバリデーションを行う。<br> <syntaxhighlight lang="python"> import re def validate_file_path(path: str) -> bool: """ファイルパスの妥当性を検証する""" # パストラバーサル攻撃を防ぐ if '..' in path: return False # 許可された拡張子のみ allowed_extensions = ['.kicad_pcb', '.kicad_pro', '.kicad_sch'] if not any(path.endswith(ext) for ext in allowed_extensions): return False # 不正な文字を含まない if not re.match(r'^[a-zA-Z0-9._\-/]+$', path): return False return True </syntaxhighlight> <br><br> == バックアップとリストア == ==== KiCADプロジェクトのバックアップ ==== 定期的にKiCADプロジェクトをバックアップする。<br> <br> <syntaxhighlight lang="sh"> #!/usr/bin/env sh ## backup-kicad-projects.shファイル BACKUP_DIR="/var/backups/kicad-projects" DATE=$(date +%Y%m%d_%H%M%S) PROJECT_DIR="/home/username/kicad-projects" # バックアップディレクトリの作成 mkdir -p $BACKUP_DIR # プロジェクトディレクトリの圧縮 tar -czf "$BACKUP_DIR/kicad-projects_$DATE.tar.gz" -C $(dirname $PROJECT_DIR) $(basename $PROJECT_DIR) # 30日以上前のバックアップを削除 find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete echo "バックアップ完了: kicad-projects_$DATE.tar.gz" </syntaxhighlight> <br> バックアップスクリプトを実行可能にする。<br> chmod u+x backup-kicad-projects.sh <br> cronジョブとして設定する。<br> crontab -e <br> # 毎日午前3時にバックアップを実行 0 3 * * * /path/to/backup-kicad-projects.sh <br><br> == トラブルシューティング == ==== KiCAD Python APIがインポートできない ==== * KiCADが正しくインストールされているか確認する。 *: <pre>kicad-cli version</pre> * 環境変数<code>PYTHONPATH</code> が正しく設定されているか確認する。 *: <pre>echo $PYTHONPATH</pre> * Python仮想環境からKiCAD Python APIへのシンボリックリンクが正しいか確認する。 *: <pre>ls -la venv/lib/python3.x/site-packages/pcbnew*</pre> <br> ==== PCBファイルの読み込みに失敗する ==== * ファイルパスが正しいか確認する。 * ファイルの読み取り権限があるか確認する。 *: <pre>ls -la /path/to/file.kicad_pcb</pre> * KiCADのバージョンとファイルフォーマットの互換性を確認する。 <br> ==== Claude Desktopから接続できない ==== * 設定ファイルのパスが正しいか確認する。 * Python仮想環境のパスが正しいか確認する。 * 環境変数 <code>PYTHONPATH</code> が設定されているか確認する。 * STDIOトランスポートの場合、標準出力にログを出力していないか確認する。 <br> ==== Gerberファイルの出力に失敗する ==== * 出力ディレクトリの書き込み権限があるか確認する。 * ディスク容量が十分にあるか確認する。 * KiCADのプロットコントローラの設定を確認する。 <br><br> == パフォーマンス最適化 == ==== 大規模PCBファイルの処理 ==== 大規模なPCBファイルを処理する場合、メモリ使用量と処理時間に注意する必要がある。<br> <br> <syntaxhighlight lang="python"> import gc @mcp.tool() def process_large_board(kicad_pcb_path: str) -> dict: """大規模なPCBファイルを効率的に処理する""" try: board = pcbnew.LoadBoard(kicad_pcb_path) # 必要な情報のみを抽出 result = extract_board_info(board) # ボードオブジェクトを明示的に削除 del board gc.collect() return result except Exception as e: return {"error": str(e)} </syntaxhighlight> <br> ==== キャッシングの実装 ==== 頻繁にアクセスされるデータをキャッシュすることにより、パフォーマンスを向上させる。<br> <br> <syntaxhighlight lang="python"> from functools import lru_cache import hashlib def get_file_hash(file_path: str) -> str: """ファイルのハッシュ値を計算する""" with open(file_path, 'rb') as f: return hashlib.md5(f.read()).hexdigest() @lru_cache(maxsize=10) def get_cached_board_info(file_path: str, file_hash: str) -> dict: """キャッシュされたボード情報を取得する""" board = pcbnew.LoadBoard(file_path) # 情報を抽出 return extract_board_info(board) @mcp.tool() def load_board_cached(kicad_pcb_path: str) -> dict: """キャッシュを使用してPCBファイルを読み込む""" try: file_hash = get_file_hash(kicad_pcb_path) return get_cached_board_info(kicad_pcb_path, file_hash) except Exception as e: return {"error": str(e)} </syntaxhighlight> <br><br> == 外部リンク == * [https://www.kicad.org/ KiCAD公式サイト] * [https://docs.kicad.org/ KiCADドキュメント] * [https://github.com/KiCad/kicad-source-mirror KiCAD GitHubリポジトリ] * [https://modelcontextprotocol.io/ Model Context Protocol公式サイト] <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:電子回路]][[カテゴリ:PCB]]
MCPサーバ - KiCAD
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse