mobile-mcpサーバによるAutoCAD自動モデリング

 mobile-mcpサーバと連携し、AndroidでChatGPTに質問しながらAutoCADの自動モデリングをすることは可能か?


例えば、AndroidスマホでChatGPTに「半径100で中心座標(x=100,y=100)の円を描いて」と依頼すると、PCのAutoCADに自動で半径100で中心座標(x=100,y=100)の円が描かれるようにするにはどうすればよいか?



はい、可能です。仕組みはこうします:


全体像


1. PC側で「AutoCADブリッジ(MCPサーバ)」を常駐



2. AndroidのChatGPTから自然言語で依頼 → ChatGPTがMCPのツール呼び出しに変換



3. MCPサーバがAutoCAD APIを叩き、図形を生成(例:中心(100,100)、半径100の円)




> ポイント:MCP(Model Context Protocol)は“ChatGPTが外部ツールを安全に呼び出す”ための標準。

ツール=「円を描く」「線を引く」などの関数をスキーマ化して公開します。





---


構成パターン(おすすめ順)


A. Python(MCPサーバ)+ AutoCAD COM(最短で動く)


Windows上でPython(pywin32)を使い、AutoCADのCOMを直接操作します。


追加インストールはPythonとpywin32くらい。AutoCADはデスクトップ版が起動済みであること。



1) MCPサーバ(Python)


# mcp_acad_server.py

import asyncio, json, pythoncom, win32com.client

from mcp import MCPServer # pip install mcp

from pydantic import BaseModel, Field


# ---- AutoCAD COM helpers ----

def _get_acad():

    pythoncom.CoInitialize()

    try:

        acad = win32com.client.Dispatch("AutoCAD.Application")

    except Exception:

        acad = win32com.client.Dispatch("AutoCAD.Application")

    acad.Visible = True

    return acad


def _modelspace(acad):

    doc = acad.ActiveDocument

    return doc.ModelSpace


# ---- Tool Schemas ----

class CircleArgs(BaseModel):

    cx: float = Field(..., description="中心X")

    cy: float = Field(..., description="中心Y")

    r: float = Field(..., gt=0, description="半径")


# ---- MCP Server ----

server = MCPServer(name="acad-bridge")


@server.tool("draw_circle", args_schema=CircleArgs, description="AutoCADに円を描く")

async def draw_circle(args: CircleArgs):

    acad = _get_acad()

    ms = _modelspace(acad)

    # AutoCAD座標はZも必要

    center = win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (args.cx, args.cy, 0.0))

    ms.AddCircle(center, float(args.r))

    acad.ActiveDocument.Regen(1) # acActiveViewport

    return {"ok": True, "placed": {"center": [args.cx, args.cy, 0.0], "radius": args.r}}


async def main():

    # 0.0.0.0:port などで公開(ローカルでも可)

    await server.run(host="0.0.0.0", port=8765, use_ssl=False) # 本番はTLS推奨


if __name__ == "__main__":

    asyncio.run(main())


> 依存関係:

pip install mcp pywin32 pydantic

※ AutoCADは起動済みがラクです(未起動でもCOMが立ち上げますが時間がかかることあり)。




2) ChatGPT(Android)側の使い方


ChatGPTアプリでMCPサーバへの接続を設定(ホスト/ポート/TLS)。


以後、自然言語でOK:


「半径100で中心座標(x=100,y=100)の円を描いて」

→ ChatGPTが draw_circle ツールに {cx:100, cy:100, r:100} を自動で入れて呼びます。



応答はMCPサーバから「描けたよ(座標、半径)」が返ってきます。




---


B. C# .NET アドイン+HTTP(堅牢・高機能)


AutoCAD内でHTTPサーバを立ててJSONコマンドを受け、トランザクションで安全に作図する方式。外部のMCPサーバからHTTP POSTで叩きます。


1) AutoCADアドイン(C# .NET)


// AcadMcpBridge.csproj のクラス例(.NET Framework 4.8想定)

// 参照: acmgd.dll, acdbmgd.dll

using Autodesk.AutoCAD.Runtime;

using Autodesk.AutoCAD.ApplicationServices;

using Autodesk.AutoCAD.DatabaseServices;

using Autodesk.AutoCAD.Geometry;

using System.Net;

using System.Text;

using System.Threading;


public class McpBridge : IExtensionApplication

{

    private HttpListener _listener;

    private Thread _thread;


    public void Initialize()

    {

        _listener = new HttpListener();

        _listener.Prefixes.Add("http://127.0.0.1:8888/");

        _listener.Start();

        _thread = new Thread(HandleLoop) { IsBackground = true };

        _thread.Start();

    }

    public void Terminate()

    {

        _listener?.Stop();

        _listener = null;

    }


    private void HandleLoop()

    {

        while (_listener != null && _listener.IsListening)

        {

            try {

                var ctx = _listener.GetContext();

                using (var reader = new System.IO.StreamReader(ctx.Request.InputStream, ctx.Request.ContentEncoding))

                {

                    var body = reader.ReadToEnd();

                    // 期待JSON: {"tool":"draw_circle","cx":100,"cy":100,"r":100}

                    var req = System.Text.Json.JsonDocument.Parse(body).RootElement;

                    string tool = req.GetProperty("tool").GetString();

                    if (tool == "draw_circle")

                    {

                        double cx = req.GetProperty("cx").GetDouble();

                        double cy = req.GetProperty("cy").GetDouble();

                        double r = req.GetProperty("r").GetDouble();

                        DrawCircle(cx, cy, r);

                        Respond(ctx, "{\"ok\":true}");

                    }

                    else Respond(ctx, "{\"ok\":false,\"error\":\"unknown tool\"}", 400);

                }

            } catch { /* ignore */ }

        }

    }


    private void DrawCircle(double cx, double cy, double r)

    {

        var doc = Application.DocumentManager.MdiActiveDocument;

        using (doc.LockDocument())

        {

            var db = doc.Database;

            using (var tr = db.TransactionManager.StartTransaction())

            {

                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

                var btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);

                var circle = new Circle(new Point3d(cx, cy, 0), Vector3d.ZAxis, r);

                btr.AppendEntity(circle);

                tr.AddNewlyCreatedDBObject(circle, true);

                tr.Commit();

            }

        }

    }


    private void Respond(HttpListenerContext ctx, string json, int code = 200)

    {

        var buf = Encoding.UTF8.GetBytes(json);

        ctx.Response.StatusCode = code;

        ctx.Response.ContentType = "application/json; charset=utf-8";

        ctx.Response.OutputStream.Write(buf, 0, buf.Length);

        ctx.Response.OutputStream.Close();

    }

}


2) MCPサーバ(Python → HTTP転送)


# mcp_http_proxy.py

import asyncio, aiohttp

from mcp import MCPServer

from pydantic import BaseModel


class CircleArgs(BaseModel):

    cx: float; cy: float; r: float


server = MCPServer(name="acad-http-proxy")


@server.tool("draw_circle", args_schema=CircleArgs)

async def draw_circle(a: CircleArgs):

    async with aiohttp.ClientSession() as s:

        async with s.post("http://127.0.0.1:8888/", json={"tool":"draw_circle", **a.model_dump()}) as resp:

            return await resp.json()


async def main():

    await server.run(host="0.0.0.0", port=8765, use_ssl=False)


if __name__ == "__main__":

    asyncio.run(main())


> 利点:AutoCADのトランザクションやドキュメントロックを確実に扱える。将来、押し出し/寸法/レイヤ/ブロック挿入などを拡張しやすい。





---


Android からの利用(ユーザー体験)


あなた:「半径100で中心(100,100)の円を描いて」


ChatGPT:意図を解析 → MCPツール draw_circle を発火(引数 {cx:100, cy:100, r:100})


PCのAutoCAD:円がモデル空間に生成される


ChatGPT:「描きました」 と結果(座標/半径)を返す




---


単位と座標系の取り扱い


AutoCADは図面の単位(mm/m/インチなど)を持ちます。


ユーザー入力(日本語の自然言語)→ デフォルト単位をmmにする、あるいはプロンプトで単位を明示する運用が安全。


UCS/WCSの区別:基本はWCSで処理(例コードもWCS 2D平面でZ=0固定)。




---


セキュリティ&運用のコツ


ローカル専用(127.0.0.1)から開始。本番運用ではTLS+APIトークン必須。


ジョブキュー化で連続依頼に耐性(順序制御・排他制御)。


監査:実行ログ(日時、コマンド、引数、ユーザー)を残す。


フェイルセーフ:例外時はトランザクション中断、UIにエラーメッセージ返却。




---


よくある躓き


COMはSTA必須:Pythonでpythoncom.CoInitialize()をそのスレッドで呼んでください。


AutoCAD未起動だとCOMの起動に時間。最初の呼び出しが遅いのは正常。


アドイン版(C#)は**DocumentLock と Transaction** を必ず使う。


権限エラー(会社PC等):ポート開放/プロキシ/EDRルールに注意。




---


次のステップ(拡張)


ツールを増やす:draw_line, draw_arc, extrude, insert_block, set_layer, add_dim など。


パラメータのバリデーション(半径>0、座標範囲、既存レイヤ確認)。


自然言語→幾何の曖昧対応:例「この線を半分に」→ 選択コンテキスト(選択ハンドル/最後に作ったエンティティID)を持たせる。


形状の可視確認サムネを自動保存(DWG to PNGのパイプライン)→ ChatGPT側にプレビュー返信。




---


必要なら、あなたの環境(AutoCADバージョン、希望する操作セット)に合わせてMCPツール一覧やコードの最適化もこちらで作ってお渡しします。



コメント

このブログの人気の投稿

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

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

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