forked from 1b-agent/opencadstudio-upstream
118 lines
4.5 KiB
Python
118 lines
4.5 KiB
Python
#!/usr/bin/env python3
|
|
"""Build the client-neutral OpenCADStudio MCP Bundle and registry metadata."""
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
from pathlib import Path
|
|
import stat
|
|
import zipfile
|
|
|
|
|
|
def manifest(version: str) -> dict:
|
|
return {
|
|
"manifest_version": "0.3",
|
|
"name": "opencadstudio",
|
|
"display_name": "OpenCADStudio",
|
|
"version": version,
|
|
"description": "Control and inspect live OpenCADStudio drawings through MCP",
|
|
"long_description": "Opens OpenCADStudio when needed and provides semantic drawing commands, document inspection, measurements, and visual verification.",
|
|
"author": {
|
|
"name": "Hakan Seven",
|
|
"url": "https://github.com/HakanSeven12/OpenCADStudio",
|
|
},
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/HakanSeven12/OpenCADStudio",
|
|
},
|
|
"server": {
|
|
"type": "binary",
|
|
"entry_point": "server/linux-x86_64/OpenCADStudio",
|
|
"mcp_config": {
|
|
"command": "${__dirname}/server/linux-x86_64/OpenCADStudio",
|
|
"args": ["--mcp"],
|
|
"env": {},
|
|
"platform_overrides": {
|
|
"win32": {
|
|
"command": "${__dirname}/server/win32-x86_64/OpenCADStudio.exe"
|
|
},
|
|
"darwin": {
|
|
"command": "${__dirname}/server/darwin-aarch64/OpenCADStudio"
|
|
},
|
|
},
|
|
},
|
|
},
|
|
"tools": [
|
|
{"name": "ocs_sessions", "description": "List or open live editor sessions"},
|
|
{"name": "ocs_read", "description": "Read drawing and editor state"},
|
|
{"name": "ocs_execute", "description": "Execute a semantic editor action"},
|
|
{"name": "ocs_capture", "description": "Capture the current editor window"},
|
|
],
|
|
"keywords": ["cad", "drawing", "mcp"],
|
|
"license": "GPL-3.0-or-later",
|
|
"compatibility": {"platforms": ["linux", "win32", "darwin"]},
|
|
}
|
|
|
|
|
|
def add(archive: zipfile.ZipFile, source: Path, destination: str) -> None:
|
|
if not source.is_file():
|
|
raise SystemExit(f"Missing MCP binary: {source}")
|
|
info = zipfile.ZipInfo(destination, date_time=(1980, 1, 1, 0, 0, 0))
|
|
info.compress_type = zipfile.ZIP_DEFLATED
|
|
info.create_system = 3
|
|
info.external_attr = (stat.S_IFREG | 0o755) << 16
|
|
archive.writestr(info, source.read_bytes())
|
|
|
|
|
|
def registry_metadata(version: str, bundle: Path) -> dict:
|
|
digest = hashlib.sha256(bundle.read_bytes()).hexdigest()
|
|
return {
|
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
"name": "io.github.HakanSeven12/opencadstudio",
|
|
"title": "OpenCADStudio",
|
|
"description": "Control and inspect live OpenCADStudio drawings through MCP",
|
|
"version": version,
|
|
"repository": {
|
|
"url": "https://github.com/HakanSeven12/OpenCADStudio",
|
|
"source": "github",
|
|
},
|
|
"websiteUrl": "https://github.com/HakanSeven12/OpenCADStudio",
|
|
"packages": [
|
|
{
|
|
"registryType": "mcpb",
|
|
"identifier": f"https://github.com/HakanSeven12/OpenCADStudio/releases/download/v{version}/{bundle.name}",
|
|
"version": version,
|
|
"fileSha256": digest,
|
|
"transport": {"type": "stdio"},
|
|
}
|
|
],
|
|
}
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--version", required=True)
|
|
parser.add_argument("--linux", type=Path, required=True)
|
|
parser.add_argument("--windows", type=Path, required=True)
|
|
parser.add_argument("--macos", type=Path, required=True)
|
|
parser.add_argument("--output", type=Path, required=True)
|
|
parser.add_argument("--server-json", type=Path, required=True)
|
|
args = parser.parse_args()
|
|
|
|
args.output.parent.mkdir(parents=True, exist_ok=True)
|
|
with zipfile.ZipFile(args.output, "w") as archive:
|
|
archive.writestr("manifest.json", json.dumps(manifest(args.version), indent=2) + "\n")
|
|
add(archive, args.linux, "server/linux-x86_64/OpenCADStudio")
|
|
add(archive, args.windows, "server/win32-x86_64/OpenCADStudio.exe")
|
|
add(archive, args.macos, "server/darwin-aarch64/OpenCADStudio")
|
|
|
|
args.server_json.parent.mkdir(parents=True, exist_ok=True)
|
|
args.server_json.write_text(
|
|
json.dumps(registry_metadata(args.version, args.output), indent=2) + "\n",
|
|
encoding="utf-8",
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|