MCPを使い、ChatGPTなどのAIとAutoCADを連携させて自動で作図するためのPythonソースコード

 MCPを使い、ChatGPTなどのAIとAutoCADを連携させて自動で作図するためのPythonソースコードを書いて。




AutoCADとAIを連携させるためのMCP(Model Context Protocol)サーバーとPythonクライアントコードを作成します。以下に完全な実装を提供します。


1. MCPサーバー (AutoCAD連携用)


```python

# mcp_autocad_server.py

import asyncio

import json

import sys

import pythoncom

import win32com.client

from mcp import MCPServer, ClientSession

from mcp.server.models import InitializationOptions

import logging


logging.basicConfig(level=logging.INFO)

logger = logging.getLogger(__name__)


class AutoCADMCPServer(MCPServer):

    def __init__(self):

        super().__init__("autocad-mcp-server")

        self.autocad_app = None

        self.current_drawing = None

        

    def connect_to_autocad(self):

        """AutoCADに接続"""

        try:

            pythoncom.CoInitialize()

            self.autocad_app = win32com.client.Dispatch("AutoCAD.Application")

            logger.info("AutoCADに接続しました")

            return True

        except Exception as e:

            logger.error(f"AutoCAD接続エラー: {e}")

            return False

    

    def get_active_document(self):

        """アクティブなドキュメントを取得"""

        try:

            if self.autocad_app:

                self.current_drawing = self.autocad_app.ActiveDocument

                return self.current_drawing

            return None

        except Exception as e:

            logger.error(f"ドキュメント取得エラー: {e}")

            return None


    async def initialize(self, session: ClientSession):

        """ツールの登録"""

        tools = [

            {

                "name": "create_line",

                "description": "2点間に直線を作成",

                "inputSchema": {

                    "type": "object",

                    "properties": {

                        "start_x": {"type": "number", "description": "始点X座標"},

                        "start_y": {"type": "number", "description": "始点Y座標"},

                        "end_x": {"type": "number", "description": "終点X座標"},

                        "end_y": {"type": "number", "description": "終点Y座標"}

                    },

                    "required": ["start_x", "start_y", "end_x", "end_y"]

                }

            },

            {

                "name": "create_circle",

                "description": "円を作成",

                "inputSchema": {

                    "type": "object",

                    "properties": {

                        "center_x": {"type": "number", "description": "中心X座標"},

                        "center_y": {"type": "number", "description": "中心Y座標"},

                        "radius": {"type": "number", "description": "半径"}

                    },

                    "required": ["center_x", "center_y", "radius"]

                }

            },

            {

                "name": "create_rectangle",

                "description": "矩形を作成",

                "inputSchema": {

                    "type": "object",

                    "properties": {

                        "x": {"type": "number", "description": "左下X座標"},

                        "y": {"type": "number", "description": "左下Y座標"},

                        "width": {"type": "number", "description": "幅"},

                        "height": {"type": "number", "description": "高さ"}

                    },

                    "required": ["x", "y", "width", "height"]

                }

            },

            {

                "name": "create_text",

                "description": "テキストを作成",

                "inputSchema": {

                    "type": "object",

                    "properties": {

                        "x": {"type": "number", "description": "挿入点X座標"},

                        "y": {"type": "number", "description": "挿入点Y座標"},

                        "text": {"type": "string", "description": "テキスト内容"},

                        "height": {"type": "number", "description": "文字高さ"}

                    },

                    "required": ["x", "y", "text"]

                }

            },

            {

                "name": "get_drawing_info",

                "description": "現在の図面情報を取得",

                "inputSchema": {

                    "type": "object",

                    "properties": {}

                }

            }

        ]

        

        for tool in tools:

            await session.register_tool(

                tool["name"],

                tool["description"],

                tool["inputSchema"]

            )

        

        # AutoCADに接続

        self.connect_to_autocad()

    

    async def handle_tool_call(self, session: ClientSession, name: str, arguments: dict):

        """ツール呼び出しの処理"""

        try:

            if name == "create_line":

                return await self.create_line(**arguments)

            elif name == "create_circle":

                return await self.create_circle(**arguments)

            elif name == "create_rectangle":

                return await self.create_rectangle(**arguments)

            elif name == "create_text":

                return await self.create_text(**arguments)

            elif name == "get_drawing_info":

                return await self.get_drawing_info()

            else:

                return {"error": f"未知のツール: {name}"}

        except Exception as e:

            logger.error(f"ツール実行エラー: {e}")

            return {"error": str(e)}

    

    async def create_line(self, start_x, start_y, end_x, end_y):

        """直線を作成"""

        try:

            doc = self.get_active_document()

            if not doc:

                return {"error": "AutoCADドキュメントが見つかりません"}

            

            model_space = doc.ModelSpace

            start_point = win32com.client.Variant(win32com.client.pythoncom.VT_ARRAY | win32com.client.pythoncom.VT_R8, [start_x, start_y, 0])

            end_point = win32com.client.Variant(win32com.client.pythoncom.VT_ARRAY | win32com.client.pythoncom.VT_R8, [end_x, end_y, 0])

            

            line = model_space.AddLine(start_point, end_point)

            doc.Regen(True)

            

            return {"success": True, "message": f"直線を作成しました: ({start_x},{start_y}) to ({end_x},{end_y})"}

        except Exception as e:

            return {"error": f"直線作成エラー: {e}"}

    

    async def create_circle(self, center_x, center_y, radius):

        """円を作成"""

        try:

            doc = self.get_active_document()

            if not doc:

                return {"error": "AutoCADドキュメントが見つかりません"}

            

            model_space = doc.ModelSpace

            center = win32com.client.Variant(win32com.client.pythoncom.VT_ARRAY | win32com.client.pythoncom.VT_R8, [center_x, center_y, 0])

            

            circle = model_space.AddCircle(center, radius)

            doc.Regen(True)

            

            return {"success": True, "message": f"円を作成しました: 中心({center_x},{center_y}), 半径{radius}"}

        except Exception as e:

            return {"error": f"円作成エラー: {e}"}

    

    async def create_rectangle(self, x, y, width, height):

        """矩形を作成"""

        try:

            doc = self.get_active_document()

            if not doc:

                return {"error": "AutoCADドキュメントが見つかりません"}

            

            model_space = doc.ModelSpace

            points = [

                [x, y, 0],

                [x + width, y, 0],

                [x + width, y + height, 0],

                [x, y + height, 0],

                [x, y, 0]

            ]

            

            for i in range(4):

                start = win32com.client.Variant(win32com.client.pythoncom.VT_ARRAY | win32com.client.pythoncom.VT_R8, points[i])

                end = win32com.client.Variant(win32com.client.pythoncom.VT_ARRAY | win32com.client.pythoncom.VT_R8, points[i+1])

                model_space.AddLine(start, end)

            

            doc.Regen(True)

            return {"success": True, "message": f"矩形を作成しました: 位置({x},{y}), サイズ{width}x{height}"}

        except Exception as e:

            return {"error": f"矩形作成エラー: {e}"}

    

    async def create_text(self, x, y, text, height=10):

        """テキストを作成"""

        try:

            doc = self.get_active_document()

            if not doc:

                return {"error": "AutoCADドキュメントが見つかりません"}

            

            model_space = doc.ModelSpace

            insertion_point = win32com.client.Variant(win32com.client.pythoncom.VT_ARRAY | win32com.client.pythoncom.VT_R8, [x, y, 0])

            

            text_obj = model_space.AddText(text, insertion_point, height)

            doc.Regen(True)

            

            return {"success": True, "message": f"テキストを作成しました: '{text}' at ({x},{y})"}

        except Exception as e:

            return {"error": f"テキスト作成エラー: {e}"}

    

    async def get_drawing_info(self):

        """図面情報を取得"""

        try:

            doc = self.get_active_document()

            if not doc:

                return {"error": "AutoCADドキュメントが見つかりません"}

            

            info = {

                "name": doc.Name,

                "path": doc.FullName if hasattr(doc, 'FullName') else "未保存",

                "units": doc.InsUnits if hasattr(doc, 'InsUnits') else "Unknown"

            }

            

            return {"drawing_info": info}

        except Exception as e:

            return {"error": f"図面情報取得エラー: {e}"}


async def main():

    server = AutoCADMCPServer()

    async with server.run_transport() as session:

        await session.wait_until_done()


if __name__ == "__main__":

    asyncio.run(main())

```


2. MCPクライアント (AI連携用)


```python

# mcp_autocad_client.py

import asyncio

import json

from mcp import ClientSession, StdioServerParameters

from mcp.client import create_mcp_client

import openai

from typing import Dict, Any


class AutoCADMCPClient:

    def __init__(self, openai_api_key: str = None):

        self.openai_client = openai.OpenAI(api_key=openai_api_key) if openai_api_key else None

        self.mcp_session = None

        

    async def connect_to_mcp_server(self, server_script_path: str):

        """MCPサーバーに接続"""

        server_params = StdioServerParameters(

            command="python",

            args=[server_script_path]

        )

        

        async with create_mcp_client(server_params) as (client, sessions):

            self.mcp_session = sessions[0]

            print("MCPサーバーに接続しました")

    

    async def process_natural_language_command(self, command: str) -> Dict[str, Any]:

        """自然言語コマンドを処理"""

        if not self.openai_client:

            return {"error": "OpenAI APIキーが設定されていません"}

        

        # 利用可能なツールを取得

        available_tools = [

            {

                "type": "function",

                "function": {

                    "name": "create_line",

                    "description": "2点間に直線を作成",

                    "parameters": {

                        "type": "object",

                        "properties": {

                            "start_x": {"type": "number"},

                            "start_y": {"type": "number"},

                            "end_x": {"type": "number"},

                            "end_y": {"type": "number"}

                        },

                        "required": ["start_x", "start_y", "end_x", "end_y"]

                    }

                }

            },

            {

                "type": "function",

                "function": {

                    "name": "create_circle",

                    "description": "円を作成",

                    "parameters": {

                        "type": "object",

                        "properties": {

                            "center_x": {"type": "number"},

                            "center_y": {"type": "number"},

                            "radius": {"type": "number"}

                        },

                        "required": ["center_x", "center_y", "radius"]

                    }

                }

            },

            {

                "type": "function",

                "function": {

                    "name": "create_rectangle",

                    "description": "矩形を作成",

                    "parameters": {

                        "type": "object",

                        "properties": {

                            "x": {"type": "number"},

                            "y": {"type": "number"},

                            "width": {"type": "number"},

                            "height": {"type": "number"}

                        },

                        "required": ["x", "y", "width", "height"]

                    }

                }

            },

            {

                "type": "function",

                "function": {

                    "name": "create_text",

                    "description": "テキストを作成",

                    "parameters": {

                        "type": "object",

                        "properties": {

                            "x": {"type": "number"},

                            "y": {"type": "number"},

                            "text": {"type": "string"},

                            "height": {"type": "number"}

                        },

                        "required": ["x", "y", "text"]

                    }

                }

            },

            {

                "type": "function",

                "function": {

                    "name": "get_drawing_info",

                    "description": "現在の図面情報を取得",

                    "parameters": {

                        "type": "object",

                        "properties": {}

                    }

                }

            }

        ]

        

        # OpenAI APIでコマンドを解析

        response = self.openai_client.chat.completions.create(

            model="gpt-3.5-turbo",

            messages=[

                {"role": "system", "content": "あなたはAutoCAD作図アシスタントです。ユーザーの自然言語コマンドをAutoCAD操作に変換します。座標は適切な数値を推定してください。"},

                {"role": "user", "content": command}

            ],

            tools=available_tools,

            tool_choice="auto"

        )

        

        message = response.choices[0].message

        

        if message.tool_calls:

            tool_call = message.tool_calls[0]

            function_name = tool_call.function.name

            function_args = json.loads(tool_call.function.arguments)

            

            # MCPサーバーでツールを実行

            result = await self.mcp_session.call_tool(function_name, function_args)

            return result

        else:

            return {"message": message.content}

    

    async def execute_direct_command(self, tool_name: str, **kwargs):

        """直接ツールを実行"""

        if not self.mcp_session:

            return {"error": "MCPサーバーに接続されていません"}

        

        result = await self.mcp_session.call_tool(tool_name, kwargs)

        return result


async def main():

    # クライアントの設定

    client = AutoCADMCPClient(openai_api_key="your-openai-api-key-here")

    

    # MCPサーバーに接続

    await client.connect_to_mcp_server("mcp_autocad_server.py")

    

    # 自然言語コマンドの例

    commands = [

        "原点から(100,100)まで直線を引いて",

        "中心(50,50)、半径30の円を作成して",

        "左下(10,10)で幅80、高さ60の四角形を描いて",

        "座標(25,25)に'Hello AutoCAD'というテキストを追加して",

        "現在の図面情報を教えて"

    ]

    

    for command in commands:

        print(f"\nコマンド: {command}")

        result = await client.process_natural_language_command(command)

        print(f"結果: {result}")

        

        # 各コマンドの間に少し待機

        await asyncio.sleep(1)


if __name__ == "__main__":

    asyncio.run(main())

```


3. シンプルな使用例


```python

# simple_example.py

import asyncio

from mcp_autocad_client import AutoCADMCPClient


async def simple_demo():

    """シンプルなデモ"""

    client = AutoCADMCPClient()

    

    # MCPサーバーに接続

    await client.connect_to_mcp_server("mcp_autocad_server.py")

    

    # 直接コマンド実行

    commands = [

        ("create_line", {"start_x": 0, "start_y": 0, "end_x": 100, "end_y": 100}),

        ("create_circle", {"center_x": 50, "center_y": 50, "radius": 25}),

        ("create_rectangle", {"x": 10, "y": 10, "width": 80, "height": 60}),

        ("create_text", {"x": 25, "y": 25, "text": "AutoCAD AI", "height": 5})

    ]

    

    for tool_name, args in commands:

        print(f"実行: {tool_name} {args}")

        result = await client.execute_direct_command(tool_name, **args)

        print(f"結果: {result}")

        await asyncio.sleep(0.5)


if __name__ == "__main__":

    asyncio.run(simple_demo())

```


4. 必要な依存関係


```txt

# requirements.txt

mcp>=1.0.0

pywin32>=300

openai>=1.0.0

asyncio

pythoncom

```


セットアップ手順


1. 必要なパッケージをインストール:


```bash

pip install mcp pywin32 openai

```


1. AutoCADがインストールされていることを確認

2. OpenAI APIキーを設定 (自然言語処理を使用する場合):


```python

client = AutoCADMCPClient(openai_api_key="your-api-key")

```


1. MCPサーバーを起動:


```bash

python mcp_autocad_server.py

```


主な機能


· 直線作成: 2点間の直線描画

· 円作成: 中心座標と半径指定での円描画

· 矩形作成: 位置とサイズ指定での四角形描画

· テキスト追加: 指定位置へのテキスト配置

· 図面情報取得: 現在の図面状態の確認

· 自然言語処理: ChatGPTとの連携によるコマンド解釈


このシステムにより、AIが自然言語でAutoCAD操作を指示でき、自動的に作図を実行できます。MCPプロトコルを使用しているため、様々なAIモデルと連携可能です。

コメント

このブログの人気の投稿

ミライアイ内服薬は薬事法違反で、ほとんど効果がない詐欺ですか?

最高裁での上告理由書受理・却下の判断基準について

裁判官の忌避申立書の作成例