Has Octave developed an MCP server/connector for BricsCAD yet?

Interested to connect Claude AI so I can direct him to do mundane tasks like update layout names.

eg Layout sheets are named by job number, sheet and revision:

26-1233-01(0) revision in brackets

I'd want to replace the 0 in the brackets with 1 (01)

Doing this manually, right clicking each of the 30 layout tabs to change 1 digit is time consuming.

There's a myriad of other use cases.

Comments

  • There is no such a feature yet.

  • Owen Wengerd
    edited August 21

    You don't need an MCP server for such things. BricsCAD plugins can do almost anything you want, and Claude is perfectly capable of writing plugins.

  • Option one: ask Claude to write a script specifically for this concert task.
    Option two: ask Claude to write a BricsCAD plugin that will allow him to retrieve sheet data and rename sheets. Claude is more or less familiar with simple AutoCAD APIs and (I think) will guess that the same code will work in BricsCAD.

  • You may want to take a look at the JTB World plugins, BatchAttEdit and SmartBatch may be the plugins worth looking at. BatchAttEdit runs internally in BricsCAD and SmartBatch is used externally (i.e. outside BricsCAD) and its scripts call on BricsCAD to do the changes/updates.

  • There one here one could pick apart https://github.com/puran-water/autocad-mcp
    Really, all you need is the ability for the model to run scripts, most models should be able to access CAD via ActiveX

  • Like the others, write your own lisp to update the layout names the way you want. I have a couple, as an example reorder the display of the layouts so now update layout names to match.

    For us job number was dwg name, sheet number you can get using VL code returns layout number, revision look at title block attributes and find last revision, eg PA PB A B 1 2 and so on.

    Something to get you started.

    ; rename layouts by AlanH

    (defun c:renlayouts ( / laylst lays lay)
    (setq laylst '())

    (setq dname (cadr (fnsplitl (getvar 'dwgname ))))
    (setq lays (vla-get-layouts (vla-get-activedocument (vlax-get-acad-object))))
    (vlax-for lay lays
    (setq laylst (cons (list (vla-get-taborder lay) (vla-get-name lay)) laylst))
    )

    (foreach lay laylst
    (if (= (car lay) 0)
    (princ)
    (command "layout" "R" (cadr lay) (strcat dname "D-" (rtos (car lay) 2 0)))
    )
    )
    (princ)
    )
    (c:renlayouts)

  • Hello, everyone,
    I set up an MCP server that generates, loads (via COM), and modifies LISP code using BricsCAD, FastMCP, and Claude. https://note.com/gizmolabs/n/n7c19f2c28689?hl=en

    By establishing a workflow that loads AI-generated code, automatically corrects and re-executes it if errors occur, and registers reusable code in a LISP library accessible to the AI, we can now utilize this as a development environment that includes AI as a partner. 😊

  • Its_Alive
    edited August 31

    @gizmon, that's awesome! I think it might be cool to build some sort of harness, or tools the model can call in process

    Here's a proof of concept

    import lmstudio as lms
    from pyrx import Ap, Db, Ge, Ed
    import json
    
    # missing in BRX, maybe LOGFILE
    def tool_get_command_history():
        print("tool_get_command_history_called")
        return Ed.Core.getLastCommandLines(32, True)
    
    tool_get_command_history.__doc__ = (
        "Retrieves the last lines of the CAD command line log to inspect errors or past commands."
    )
    
    def tool_evaluate_lisp(statement: str):
        print("tool_evaluate_lisp_called {}".format(statement))
        lock = Ap.AutoDocLock()
        result = Ed.Core.evaluateLisp(statement)
        return f"tool_evaluate_lisp_result: {result}"
    
    tool_evaluate_lisp.__doc__ = (
        "Evaluates an AutoLISP statement within the active CAD document context. "
        "Accepts a 'statement' string parameter containing the LISP code. "
        "Example: \"(entmake (list '(0 . \"LINE\") '(8 . \"0\") '(100 . \"AcDbEntity\") "
        "'(100 . \"AcDbLine\") (cons 10 '(0.0 0.0 0.0)) (cons 11 '(10.0 0.0 0.0))))\""
    )
    
    @Ap.Command(Ap.CmdFlags.SESSION)
    def doit():
        ps, user_prompt = Ed.Editor.getString(1, "\nWhat should the agent do? ")
        if ps != Ed.PromptStatus.eNormal or not user_prompt:
            return
    
        model = lms.llm("qwen/qwen3.8-27b")
        print("\nAgent is deciding which CAD tool to use...")
        try:
            response = model.act(
                user_prompt, tools=[tool_get_command_history, tool_evaluate_lisp], on_message=print
            )
            print(f"\nFinal Agent Summary: {str(response)}")
        except Exception as ex:
            print(f"\nAn error occurred during SDK communication: {str(ex)}")
    
    
    
    

    Result

    Command: DOIT
    What should the agent do? draw a line
    Agent is deciding which CAD tool to use...
    AssistantResponse.from_dict({
    "content": [
    {
    "text": "The user wants to draw a line. I'm in a CAD environment with AutoLISP. I can use tool_evaluate_lisp to create a LINE entity with entmake.\n\nLet's draw a simple line from (0,0,0) to (10,0,0).\n__LM_STUDIO_INTERNAL_LSEP_SYNTHETIC_REASONING_END_f4e9a8d2c6b14d0c9e5f3a7b8c1d2e6a__",
    "type": "text"
    },
    {
    "toolCallRequest": {
    "arguments": {
    "statement": "(entmake (list '(0 . "LINE") '(8 . "0") '(100 . "AcDbEntity") '(100 . "AcDbLine") (cons 10 '(0.0 0.0 0.0)) (cons 11 '(10.0 0.0 0.0))))"
    },
    "id": "AZPvJbQVzAoSMrxAXJpj842ySASFJjaT",
    "name": "tool_evaluate_lisp",
    "type": "function"
    },
    "type": "toolCallRequest"
    }
    ],
    "role": "assistant"
    })
    ToolResultMessage.from_dict({
    "content": [
    {
    "content": ""tool_evaluate_lisp_result: [(0, 'LINE'), (8, '0'), (100, 'AcDbEntity'), (100, 'AcDbLine'), (10, PyGe.Point3d(0.00000000000000,0.00000000000000,0.00000000000000)), (11, PyGe.Point3d(10.00000000000000,0.00000000000000,0.00000000000000))]"",
    "toolCallId": "AZPvJbQVzAoSMrxAXJpj842ySASFJjaT",
    "type": "toolCallResult"
    }
    ],
    "role": "tool"
    })
    AssistantResponse.from_dict({
    "content": [
    {
    "text": "The line has been created successfully. I'll report this to the user.\n__LM_STUDIO_INTERNAL_LSEP_SYNTHETIC_REASONING_END_f4e9a8d2c6b14d0c9e5f3a7b8c1d2e6a__Done! I've drawn a line on the "0" layer:\n\n- Start point: (0.0, 0.0, 0.0)\n- End point: (10.0, 0.0, 0.0)\n\nA 10-unit horizontal line along the X axis. Want me to draw more lines, change the length, or put it on a specific layer?",
    "type": "text"
    }
    ],
    "role": "assistant"
    })
    Final Agent Summary: ActResult(rounds=2, total_time_seconds=10.108471999999892)
    tool_evaluate_lisp_called (entmake (list '(0 . "LINE") '(8 . "0") '(100 . "AcDbEntity") '(100 . "AcDbLine") (cons 10 '(0.0 0.0 0.0)) (cons 11 '(10.0 0.0 0.0))))

    It draws the line!

    other tools could be, tool_pyload, tool_pyreload, tool_appload a tool for Ed.Core.cmdS(). The model could generate Lisp, Python routines to load a run.

  • Yes, thanks to this environment, I can now easily create features that I hadn't been able to develop before due to time constraints.
    When combined with AI agents, it enables automation on a much broader scale, which is quite disruptive. 🤐