Release prep 0.6.2 (#39)
* docs: note macro repo move * chore: bump workbench to 0.6.2 * docs: update README.md * docs: improve release notes * fix: better icons and minor tweaks * fix: Add reverse test
@@ -22,6 +22,7 @@ import contextlib
|
||||
import errno
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import queue
|
||||
import sys
|
||||
import threading
|
||||
@@ -236,8 +237,9 @@ class FreecadMCPPlugin:
|
||||
|
||||
self._running = True
|
||||
|
||||
# Print instance ID to stderr for test automation to capture.
|
||||
# Stdout may be reserved for JSON-RPC when running in stdio mode.
|
||||
# Print instance ID to stderr only for test automation (when env var is set).
|
||||
# This avoids red error text in FreeCAD's console during normal use.
|
||||
if os.environ.get("FREECAD_MCP_TESTING"):
|
||||
print(
|
||||
f"FREECAD_MCP_BRIDGE_INSTANCE_ID={self._instance_id}",
|
||||
file=sys.stderr,
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<!-- White background -->
|
||||
<rect width="64" height="64" fill="#ffffff"/>
|
||||
<!-- Transparent background (allows Qt pressed state to show through) -->
|
||||
|
||||
<!-- Bridge Structure -->
|
||||
<!-- Bridge Structure with light outline for dark background contrast -->
|
||||
<!-- Bridge deck -->
|
||||
<rect x="4" y="40" width="56" height="5" rx="1" fill="#8b7355" stroke="#6b5344" stroke-width="1"/>
|
||||
<rect x="4" y="40" width="56" height="5" rx="1" fill="#8b7355" stroke="#d4c4b0" stroke-width="1.5"/>
|
||||
<!-- Bridge railings -->
|
||||
<rect x="4" y="37" width="56" height="2" rx="0.5" fill="#a08060"/>
|
||||
<rect x="4" y="37" width="56" height="2" rx="0.5" fill="#b89c7a" stroke="#d4c4b0" stroke-width="0.5"/>
|
||||
<!-- Bridge supports/pillars -->
|
||||
<rect x="8" y="45" width="6" height="8" fill="#6b5344"/>
|
||||
<rect x="50" y="45" width="6" height="8" fill="#6b5344"/>
|
||||
<rect x="8" y="45" width="6" height="8" fill="#7a6450" stroke="#d4c4b0" stroke-width="1"/>
|
||||
<rect x="50" y="45" width="6" height="8" fill="#7a6450" stroke="#d4c4b0" stroke-width="1"/>
|
||||
<!-- Bridge arch underneath -->
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#6b5344" stroke-width="2"/>
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#7a6450" stroke-width="2.5"/>
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#d4c4b0" stroke-width="1" opacity="0.6"/>
|
||||
|
||||
<!-- Robot on the bridge (facing RIGHT - same direction as play buttons) -->
|
||||
<!-- Robot body -->
|
||||
<rect x="24" y="18" width="16" height="14" rx="2" fill="#4a90d9" stroke="#2c5aa0" stroke-width="1.5"/>
|
||||
<!-- Robot body with light outline -->
|
||||
<rect x="24" y="18" width="16" height="14" rx="2" fill="#5a9ee8" stroke="#e0f0ff" stroke-width="1.5"/>
|
||||
<!-- Robot head (facing right) -->
|
||||
<rect x="26" y="8" width="12" height="10" rx="2" fill="#4a90d9" stroke="#2c5aa0" stroke-width="1.5"/>
|
||||
<rect x="26" y="8" width="12" height="10" rx="2" fill="#5a9ee8" stroke="#e0f0ff" stroke-width="1.5"/>
|
||||
<!-- Robot face plate (on right side) -->
|
||||
<rect x="32" y="10" width="6" height="6" rx="1" fill="#e8f4fc"/>
|
||||
<rect x="32" y="10" width="6" height="6" rx="1" fill="#f0f8ff" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<!-- Robot eyes (looking right) -->
|
||||
<circle cx="36" cy="12" r="1.5" fill="#2c5aa0"/>
|
||||
<circle cx="36" cy="15" r="1.5" fill="#2c5aa0"/>
|
||||
<!-- Robot antenna -->
|
||||
<line x1="32" y1="8" x2="32" y2="3" stroke="#2c5aa0" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="32" cy="2" r="3" fill="#27ae60"/>
|
||||
<line x1="32" y1="8" x2="32" y2="3" stroke="#3c6ab0" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="32" cy="2" r="3" fill="#2ecc71" stroke="#e0ffe0" stroke-width="1"/>
|
||||
<!-- Robot arms (reaching forward to right) -->
|
||||
<rect x="18" y="22" width="6" height="4" rx="1.5" fill="#3a7bc8"/>
|
||||
<rect x="40" y="20" width="8" height="4" rx="1.5" fill="#3a7bc8"/>
|
||||
<rect x="18" y="22" width="6" height="4" rx="1.5" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<rect x="40" y="20" width="8" height="4" rx="1.5" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<!-- Robot legs (walking pose) -->
|
||||
<rect x="24" y="32" width="4" height="8" rx="1" fill="#3a7bc8" transform="rotate(10, 26, 36)"/>
|
||||
<rect x="36" y="32" width="4" height="8" rx="1" fill="#3a7bc8" transform="rotate(-10, 38, 36)"/>
|
||||
<rect x="24" y="32" width="4" height="8" rx="1" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5" transform="rotate(10, 26, 36)"/>
|
||||
<rect x="36" y="32" width="4" height="8" rx="1" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5" transform="rotate(-10, 38, 36)"/>
|
||||
|
||||
<!-- Bold Play Triangles in TOP corners -->
|
||||
<polygon points="4,4 4,16 12,10" fill="#27ae60" stroke="#1e8449" stroke-width="1.5"/>
|
||||
<polygon points="52,4 52,16 60,10" fill="#27ae60" stroke="#1e8449" stroke-width="1.5"/>
|
||||
<!-- Bold Play Triangles in TOP corners with light outline -->
|
||||
<polygon points="4,4 4,16 12,10" fill="#2ecc71" stroke="#c0ffc0" stroke-width="1.5"/>
|
||||
<polygon points="52,4 52,16 60,10" fill="#2ecc71" stroke="#c0ffc0" stroke-width="1.5"/>
|
||||
|
||||
<!-- Green Data Flow (river under bridge - active) -->
|
||||
<!-- Data stream background -->
|
||||
<path d="M 0 60 Q 32 55 64 60" fill="none" stroke="#27ae60" stroke-width="4" opacity="0.3"/>
|
||||
<path d="M 0 60 Q 32 55 64 60" fill="none" stroke="#2ecc71" stroke-width="4" opacity="0.4"/>
|
||||
<!-- Left arrow -->
|
||||
<path d="M 6 59 L 16 59" stroke="#27ae60" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="6,59 11,56 11,62" fill="#27ae60"/>
|
||||
<path d="M 6 59 L 16 59" stroke="#2ecc71" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="6,59 11,56 11,62" fill="#2ecc71" stroke="#c0ffc0" stroke-width="0.5"/>
|
||||
<!-- Right arrow -->
|
||||
<path d="M 48 59 L 58 59" stroke="#27ae60" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="58,59 53,56 53,62" fill="#27ae60"/>
|
||||
<path d="M 48 59 L 58 59" stroke="#2ecc71" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="58,59 53,56 53,62" fill="#2ecc71" stroke="#c0ffc0" stroke-width="0.5"/>
|
||||
<!-- Center data dots (flowing) -->
|
||||
<circle cx="26" cy="57" r="2" fill="#27ae60"/>
|
||||
<circle cx="32" cy="56" r="2" fill="#27ae60"/>
|
||||
<circle cx="38" cy="57" r="2" fill="#27ae60"/>
|
||||
<circle cx="26" cy="57" r="2" fill="#2ecc71" stroke="#c0ffc0" stroke-width="0.5"/>
|
||||
<circle cx="32" cy="56" r="2" fill="#2ecc71" stroke="#c0ffc0" stroke-width="0.5"/>
|
||||
<circle cx="38" cy="57" r="2" fill="#2ecc71" stroke="#c0ffc0" stroke-width="0.5"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -1,57 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<!-- White background -->
|
||||
<rect width="64" height="64" fill="#ffffff"/>
|
||||
<!-- Transparent background (allows Qt pressed state to show through) -->
|
||||
|
||||
<!-- Bridge Structure -->
|
||||
<!-- Bridge Structure with light outline -->
|
||||
<!-- Bridge deck -->
|
||||
<rect x="4" y="40" width="56" height="5" rx="1" fill="#8b7355" stroke="#6b5344" stroke-width="1"/>
|
||||
<rect x="4" y="40" width="56" height="5" rx="1" fill="#8b7355" stroke="#d4c4b0" stroke-width="1.5"/>
|
||||
<!-- Bridge railings -->
|
||||
<rect x="4" y="37" width="56" height="2" rx="0.5" fill="#a08060"/>
|
||||
<rect x="4" y="37" width="56" height="2" rx="0.5" fill="#b89c7a" stroke="#d4c4b0" stroke-width="0.5"/>
|
||||
<!-- Bridge supports/pillars -->
|
||||
<rect x="8" y="45" width="6" height="8" fill="#6b5344"/>
|
||||
<rect x="50" y="45" width="6" height="8" fill="#6b5344"/>
|
||||
<rect x="8" y="45" width="6" height="8" fill="#7a6450" stroke="#d4c4b0" stroke-width="1"/>
|
||||
<rect x="50" y="45" width="6" height="8" fill="#7a6450" stroke="#d4c4b0" stroke-width="1"/>
|
||||
<!-- Bridge arch underneath -->
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#6b5344" stroke-width="2"/>
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#7a6450" stroke-width="2.5"/>
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#d4c4b0" stroke-width="1" opacity="0.6"/>
|
||||
|
||||
<!-- Robot SITTING on bridge edge, feet dangling -->
|
||||
<!-- Robot body (sitting position - shorter/compressed) -->
|
||||
<rect x="24" y="24" width="16" height="10" rx="2" fill="#4a90d9" stroke="#2c5aa0" stroke-width="1.5"/>
|
||||
<!-- Robot head -->
|
||||
<rect x="26" y="14" width="12" height="10" rx="2" fill="#4a90d9" stroke="#2c5aa0" stroke-width="1.5"/>
|
||||
<!-- Robot body (sitting position - shorter/compressed) with light outline -->
|
||||
<rect x="24" y="24" width="16" height="10" rx="2" fill="#5a9ee8" stroke="#e0f0ff" stroke-width="1.5"/>
|
||||
<!-- Robot head with light outline -->
|
||||
<rect x="26" y="14" width="12" height="10" rx="2" fill="#5a9ee8" stroke="#e0f0ff" stroke-width="1.5"/>
|
||||
<!-- Robot face plate -->
|
||||
<rect x="28" y="16" width="8" height="6" rx="1" fill="#e8f4fc"/>
|
||||
<rect x="28" y="16" width="8" height="6" rx="1" fill="#f0f8ff" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<!-- Robot eyes (looking curious) -->
|
||||
<circle cx="30" cy="19" r="1.5" fill="#2c5aa0"/>
|
||||
<circle cx="34" cy="19" r="1.5" fill="#2c5aa0"/>
|
||||
<!-- Robot antenna with YELLOW ball (matches status color) -->
|
||||
<line x1="32" y1="14" x2="32" y2="9" stroke="#2c5aa0" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="32" cy="8" r="3" fill="#f1c40f"/>
|
||||
<!-- Robot antenna with YELLOW ball (matches status color) with light outline -->
|
||||
<line x1="32" y1="14" x2="32" y2="9" stroke="#3c6ab0" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="32" cy="8" r="3" fill="#f1c40f" stroke="#fff8c0" stroke-width="1"/>
|
||||
<!-- Robot arms (resting on bridge) -->
|
||||
<rect x="18" y="28" width="6" height="4" rx="1.5" fill="#3a7bc8"/>
|
||||
<rect x="40" y="28" width="6" height="4" rx="1.5" fill="#3a7bc8"/>
|
||||
<rect x="18" y="28" width="6" height="4" rx="1.5" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<rect x="40" y="28" width="6" height="4" rx="1.5" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<!-- Robot legs (dangling over edge) -->
|
||||
<rect x="26" y="34" width="4" height="12" rx="1" fill="#3a7bc8"/>
|
||||
<rect x="34" y="34" width="4" height="12" rx="1" fill="#3a7bc8"/>
|
||||
<rect x="26" y="34" width="4" height="12" rx="1" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<rect x="34" y="34" width="4" height="12" rx="1" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<!-- Robot feet -->
|
||||
<rect x="25" y="45" width="6" height="3" rx="1" fill="#2c5aa0"/>
|
||||
<rect x="33" y="45" width="6" height="3" rx="1" fill="#2c5aa0"/>
|
||||
<rect x="25" y="45" width="6" height="3" rx="1" fill="#3c6ab0" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<rect x="33" y="45" width="6" height="3" rx="1" fill="#3c6ab0" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
|
||||
<!-- Bold Question marks in TOP corners -->
|
||||
<text x="9" y="16" font-family="Arial, Helvetica, sans-serif" font-size="18" font-weight="900" fill="#f1c40f" stroke="#d4ac0d" stroke-width="1" text-anchor="middle">?</text>
|
||||
<text x="55" y="16" font-family="Arial, Helvetica, sans-serif" font-size="18" font-weight="900" fill="#f1c40f" stroke="#d4ac0d" stroke-width="1" text-anchor="middle">?</text>
|
||||
<!-- Bold Question marks in TOP corners with light stroke -->
|
||||
<text x="9" y="16" font-family="Arial, Helvetica, sans-serif" font-size="18" font-weight="900" fill="#f1c40f" stroke="#fff8c0" stroke-width="1.5" text-anchor="middle">?</text>
|
||||
<text x="55" y="16" font-family="Arial, Helvetica, sans-serif" font-size="18" font-weight="900" fill="#f1c40f" stroke="#fff8c0" stroke-width="1.5" text-anchor="middle">?</text>
|
||||
|
||||
<!-- Yellow Data Flow (river under bridge - status check) -->
|
||||
<!-- Data stream background -->
|
||||
<path d="M 0 60 Q 32 55 64 60" fill="none" stroke="#f1c40f" stroke-width="4" opacity="0.3"/>
|
||||
<path d="M 0 60 Q 32 55 64 60" fill="none" stroke="#f1c40f" stroke-width="4" opacity="0.4"/>
|
||||
<!-- Left arrow -->
|
||||
<path d="M 6 59 L 16 59" stroke="#f1c40f" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="6,59 11,56 11,62" fill="#f1c40f"/>
|
||||
<polygon points="6,59 11,56 11,62" fill="#f1c40f" stroke="#fff8c0" stroke-width="0.5"/>
|
||||
<!-- Right arrow -->
|
||||
<path d="M 48 59 L 58 59" stroke="#f1c40f" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="58,59 53,56 53,62" fill="#f1c40f"/>
|
||||
<polygon points="58,59 53,56 53,62" fill="#f1c40f" stroke="#fff8c0" stroke-width="0.5"/>
|
||||
<!-- Center data dots (checking) -->
|
||||
<circle cx="26" cy="57" r="2" fill="#f1c40f"/>
|
||||
<circle cx="32" cy="56" r="2" fill="#f1c40f"/>
|
||||
<circle cx="38" cy="57" r="2" fill="#f1c40f"/>
|
||||
<circle cx="26" cy="57" r="2" fill="#f1c40f" stroke="#fff8c0" stroke-width="0.5"/>
|
||||
<circle cx="32" cy="56" r="2" fill="#f1c40f" stroke="#fff8c0" stroke-width="0.5"/>
|
||||
<circle cx="38" cy="57" r="2" fill="#f1c40f" stroke="#fff8c0" stroke-width="0.5"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -1,43 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<!-- White background -->
|
||||
<rect width="64" height="64" fill="#ffffff"/>
|
||||
<!-- Transparent background (allows Qt pressed state to show through) -->
|
||||
|
||||
<!-- Bold Stop Squares in TOP corners (not overlapping bridge) -->
|
||||
<rect x="2" y="2" width="14" height="14" rx="2" fill="#e74c3c" stroke="#c0392b" stroke-width="2"/>
|
||||
<rect x="48" y="2" width="14" height="14" rx="2" fill="#e74c3c" stroke="#c0392b" stroke-width="2"/>
|
||||
<!-- Bold Stop Squares in TOP corners with light outline -->
|
||||
<rect x="2" y="2" width="14" height="14" rx="2" fill="#e74c3c" stroke="#ffc0c0" stroke-width="1.5"/>
|
||||
<rect x="48" y="2" width="14" height="14" rx="2" fill="#e74c3c" stroke="#ffc0c0" stroke-width="1.5"/>
|
||||
|
||||
<!-- DRAWBRIDGE OPEN - No robot -->
|
||||
<!-- Left bridge section (raised) -->
|
||||
<!-- Left bridge section (raised) with light outline -->
|
||||
<g transform="rotate(-35, 4, 40)">
|
||||
<rect x="4" y="40" width="26" height="5" rx="1" fill="#8b7355" stroke="#6b5344" stroke-width="1"/>
|
||||
<rect x="4" y="37" width="26" height="2" rx="0.5" fill="#a08060"/>
|
||||
<rect x="4" y="40" width="26" height="5" rx="1" fill="#8b7355" stroke="#d4c4b0" stroke-width="1.5"/>
|
||||
<rect x="4" y="37" width="26" height="2" rx="0.5" fill="#b89c7a" stroke="#d4c4b0" stroke-width="0.5"/>
|
||||
</g>
|
||||
|
||||
<!-- Right bridge section (raised) -->
|
||||
<!-- Right bridge section (raised) with light outline -->
|
||||
<g transform="rotate(35, 60, 40)">
|
||||
<rect x="34" y="40" width="26" height="5" rx="1" fill="#8b7355" stroke="#6b5344" stroke-width="1"/>
|
||||
<rect x="34" y="37" width="26" height="2" rx="0.5" fill="#a08060"/>
|
||||
<rect x="34" y="40" width="26" height="5" rx="1" fill="#8b7355" stroke="#d4c4b0" stroke-width="1.5"/>
|
||||
<rect x="34" y="37" width="26" height="2" rx="0.5" fill="#b89c7a" stroke="#d4c4b0" stroke-width="0.5"/>
|
||||
</g>
|
||||
|
||||
<!-- Bridge supports/pillars -->
|
||||
<rect x="8" y="45" width="6" height="8" fill="#6b5344"/>
|
||||
<rect x="50" y="45" width="6" height="8" fill="#6b5344"/>
|
||||
<!-- Bridge supports/pillars with light outline -->
|
||||
<rect x="8" y="45" width="6" height="8" fill="#7a6450" stroke="#d4c4b0" stroke-width="1"/>
|
||||
<rect x="50" y="45" width="6" height="8" fill="#7a6450" stroke="#d4c4b0" stroke-width="1"/>
|
||||
|
||||
<!-- Bridge arch underneath (broken/gap) -->
|
||||
<path d="M 14 53 Q 20 49 26 50" fill="none" stroke="#6b5344" stroke-width="2"/>
|
||||
<path d="M 38 50 Q 44 49 50 53" fill="none" stroke="#6b5344" stroke-width="2"/>
|
||||
<path d="M 14 53 Q 20 49 26 50" fill="none" stroke="#7a6450" stroke-width="2.5"/>
|
||||
<path d="M 14 53 Q 20 49 26 50" fill="none" stroke="#d4c4b0" stroke-width="1" opacity="0.6"/>
|
||||
<path d="M 38 50 Q 44 49 50 53" fill="none" stroke="#7a6450" stroke-width="2.5"/>
|
||||
<path d="M 38 50 Q 44 49 50 53" fill="none" stroke="#d4c4b0" stroke-width="1" opacity="0.6"/>
|
||||
|
||||
<!-- Red Data Flow (river under bridge - stopped) -->
|
||||
<!-- Data stream background -->
|
||||
<path d="M 0 60 Q 32 55 64 60" fill="none" stroke="#e74c3c" stroke-width="4" opacity="0.3"/>
|
||||
<path d="M 0 60 Q 32 55 64 60" fill="none" stroke="#e74c3c" stroke-width="4" opacity="0.4"/>
|
||||
<!-- Left arrow (blocked) -->
|
||||
<path d="M 6 59 L 16 59" stroke="#e74c3c" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="6,59 11,56 11,62" fill="#e74c3c"/>
|
||||
<polygon points="6,59 11,56 11,62" fill="#e74c3c" stroke="#ffc0c0" stroke-width="0.5"/>
|
||||
<!-- Right arrow (blocked) -->
|
||||
<path d="M 48 59 L 58 59" stroke="#e74c3c" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="58,59 53,56 53,62" fill="#e74c3c"/>
|
||||
<polygon points="58,59 53,56 53,62" fill="#e74c3c" stroke="#ffc0c0" stroke-width="0.5"/>
|
||||
<!-- Center X (flow blocked) -->
|
||||
<line x1="28" y1="55" x2="36" y2="61" stroke="#e74c3c" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<line x1="36" y1="55" x2="28" y2="61" stroke="#e74c3c" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<line x1="28" y1="55" x2="36" y2="61" stroke="#e74c3c" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="36" y1="55" x2="28" y2="61" stroke="#e74c3c" stroke-width="3" stroke-linecap="round"/>
|
||||
<line x1="28" y1="55" x2="36" y2="61" stroke="#ffc0c0" stroke-width="1" stroke-linecap="round" opacity="0.6"/>
|
||||
<line x1="36" y1="55" x2="28" y2="61" stroke="#ffc0c0" stroke-width="1" stroke-linecap="round" opacity="0.6"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -1,84 +1,84 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64">
|
||||
<!-- White background -->
|
||||
<rect width="64" height="64" fill="#ffffff"/>
|
||||
<!-- Transparent background (allows Qt pressed state to show through) -->
|
||||
|
||||
<!-- Bridge Structure -->
|
||||
<!-- Bridge Structure with light outline -->
|
||||
<!-- Bridge deck -->
|
||||
<rect x="4" y="40" width="56" height="5" rx="1" fill="#8b7355" stroke="#6b5344" stroke-width="1"/>
|
||||
<rect x="4" y="40" width="56" height="5" rx="1" fill="#8b7355" stroke="#d4c4b0" stroke-width="1.5"/>
|
||||
<!-- Bridge railings -->
|
||||
<rect x="4" y="37" width="56" height="2" rx="0.5" fill="#a08060"/>
|
||||
<rect x="4" y="37" width="56" height="2" rx="0.5" fill="#b89c7a" stroke="#d4c4b0" stroke-width="0.5"/>
|
||||
<!-- Bridge supports/pillars -->
|
||||
<rect x="8" y="45" width="6" height="8" fill="#6b5344"/>
|
||||
<rect x="50" y="45" width="6" height="8" fill="#6b5344"/>
|
||||
<rect x="8" y="45" width="6" height="8" fill="#7a6450" stroke="#d4c4b0" stroke-width="1"/>
|
||||
<rect x="50" y="45" width="6" height="8" fill="#7a6450" stroke="#d4c4b0" stroke-width="1"/>
|
||||
<!-- Bridge arch underneath -->
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#6b5344" stroke-width="2"/>
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#7a6450" stroke-width="2.5"/>
|
||||
<path d="M 14 53 Q 32 47 50 53" fill="none" stroke="#d4c4b0" stroke-width="1" opacity="0.6"/>
|
||||
|
||||
<!-- Robot SITTING on bridge edge, feet dangling -->
|
||||
<!-- Robot SITTING on bridge edge, feet dangling with light outline -->
|
||||
<!-- Robot body (sitting position - shorter/compressed) -->
|
||||
<rect x="24" y="24" width="16" height="10" rx="2" fill="#4a90d9" stroke="#2c5aa0" stroke-width="1.5"/>
|
||||
<rect x="24" y="24" width="16" height="10" rx="2" fill="#5a9ee8" stroke="#e0f0ff" stroke-width="1.5"/>
|
||||
<!-- Robot head -->
|
||||
<rect x="26" y="14" width="12" height="10" rx="2" fill="#4a90d9" stroke="#2c5aa0" stroke-width="1.5"/>
|
||||
<rect x="26" y="14" width="12" height="10" rx="2" fill="#5a9ee8" stroke="#e0f0ff" stroke-width="1.5"/>
|
||||
<!-- Robot face plate -->
|
||||
<rect x="28" y="16" width="8" height="6" rx="1" fill="#e8f4fc"/>
|
||||
<rect x="28" y="16" width="8" height="6" rx="1" fill="#f0f8ff" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<!-- Robot eyes -->
|
||||
<circle cx="30" cy="19" r="1.5" fill="#2c5aa0"/>
|
||||
<circle cx="34" cy="19" r="1.5" fill="#2c5aa0"/>
|
||||
<!-- Robot antenna with GRAY ball (matches gear color) -->
|
||||
<line x1="32" y1="14" x2="32" y2="9" stroke="#2c5aa0" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="32" cy="8" r="3" fill="#95a5a6"/>
|
||||
<!-- Robot antenna with GRAY ball (matches gear color) with light outline -->
|
||||
<line x1="32" y1="14" x2="32" y2="9" stroke="#3c6ab0" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="32" cy="8" r="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="1"/>
|
||||
<!-- Robot arms (resting on bridge) -->
|
||||
<rect x="18" y="28" width="6" height="4" rx="1.5" fill="#3a7bc8"/>
|
||||
<rect x="40" y="28" width="6" height="4" rx="1.5" fill="#3a7bc8"/>
|
||||
<rect x="18" y="28" width="6" height="4" rx="1.5" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<rect x="40" y="28" width="6" height="4" rx="1.5" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<!-- Robot legs (dangling over edge) -->
|
||||
<rect x="26" y="34" width="4" height="12" rx="1" fill="#3a7bc8"/>
|
||||
<rect x="34" y="34" width="4" height="12" rx="1" fill="#3a7bc8"/>
|
||||
<rect x="26" y="34" width="4" height="12" rx="1" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<rect x="34" y="34" width="4" height="12" rx="1" fill="#4a8bd8" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<!-- Robot feet -->
|
||||
<rect x="25" y="45" width="6" height="3" rx="1" fill="#2c5aa0"/>
|
||||
<rect x="33" y="45" width="6" height="3" rx="1" fill="#2c5aa0"/>
|
||||
<rect x="25" y="45" width="6" height="3" rx="1" fill="#3c6ab0" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
<rect x="33" y="45" width="6" height="3" rx="1" fill="#3c6ab0" stroke="#c0e0ff" stroke-width="0.5"/>
|
||||
|
||||
<!-- Better Gear symbols in TOP corners (more teeth, more obvious) -->
|
||||
<!-- Better Gear symbols in TOP corners with light outlines -->
|
||||
<!-- Left gear -->
|
||||
<circle cx="10" cy="10" r="6" fill="#95a5a6" stroke="#7f8c8d" stroke-width="1"/>
|
||||
<circle cx="10" cy="10" r="6" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="1.5"/>
|
||||
<!-- Gear teeth (8 teeth around the gear) -->
|
||||
<rect x="8" y="2" width="4" height="3" fill="#95a5a6"/>
|
||||
<rect x="8" y="15" width="4" height="3" fill="#95a5a6"/>
|
||||
<rect x="2" y="8" width="3" height="4" fill="#95a5a6"/>
|
||||
<rect x="15" y="8" width="3" height="4" fill="#95a5a6"/>
|
||||
<rect x="8" y="2" width="4" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<rect x="8" y="15" width="4" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<rect x="2" y="8" width="3" height="4" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<rect x="15" y="8" width="3" height="4" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<!-- Diagonal teeth -->
|
||||
<rect x="3" y="3" width="3" height="3" fill="#95a5a6" transform="rotate(45, 4.5, 4.5)"/>
|
||||
<rect x="14" y="3" width="3" height="3" fill="#95a5a6" transform="rotate(-45, 15.5, 4.5)"/>
|
||||
<rect x="3" y="14" width="3" height="3" fill="#95a5a6" transform="rotate(-45, 4.5, 15.5)"/>
|
||||
<rect x="14" y="14" width="3" height="3" fill="#95a5a6" transform="rotate(45, 15.5, 15.5)"/>
|
||||
<rect x="3" y="3" width="3" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5" transform="rotate(45, 4.5, 4.5)"/>
|
||||
<rect x="14" y="3" width="3" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5" transform="rotate(-45, 15.5, 4.5)"/>
|
||||
<rect x="3" y="14" width="3" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5" transform="rotate(-45, 4.5, 15.5)"/>
|
||||
<rect x="14" y="14" width="3" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5" transform="rotate(45, 15.5, 15.5)"/>
|
||||
<!-- Gear center hole -->
|
||||
<circle cx="10" cy="10" r="2.5" fill="#6b5344"/>
|
||||
<circle cx="10" cy="10" r="2.5" fill="#7a6450" stroke="#d4c4b0" stroke-width="0.5"/>
|
||||
|
||||
<!-- Right gear -->
|
||||
<circle cx="54" cy="10" r="6" fill="#95a5a6" stroke="#7f8c8d" stroke-width="1"/>
|
||||
<circle cx="54" cy="10" r="6" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="1.5"/>
|
||||
<!-- Gear teeth (8 teeth around the gear) -->
|
||||
<rect x="52" y="2" width="4" height="3" fill="#95a5a6"/>
|
||||
<rect x="52" y="15" width="4" height="3" fill="#95a5a6"/>
|
||||
<rect x="46" y="8" width="3" height="4" fill="#95a5a6"/>
|
||||
<rect x="59" y="8" width="3" height="4" fill="#95a5a6"/>
|
||||
<rect x="52" y="2" width="4" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<rect x="52" y="15" width="4" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<rect x="46" y="8" width="3" height="4" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<rect x="59" y="8" width="3" height="4" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<!-- Diagonal teeth -->
|
||||
<rect x="47" y="3" width="3" height="3" fill="#95a5a6" transform="rotate(45, 48.5, 4.5)"/>
|
||||
<rect x="58" y="3" width="3" height="3" fill="#95a5a6" transform="rotate(-45, 59.5, 4.5)"/>
|
||||
<rect x="47" y="14" width="3" height="3" fill="#95a5a6" transform="rotate(-45, 48.5, 15.5)"/>
|
||||
<rect x="58" y="14" width="3" height="3" fill="#95a5a6" transform="rotate(45, 59.5, 15.5)"/>
|
||||
<rect x="47" y="3" width="3" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5" transform="rotate(45, 48.5, 4.5)"/>
|
||||
<rect x="58" y="3" width="3" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5" transform="rotate(-45, 59.5, 4.5)"/>
|
||||
<rect x="47" y="14" width="3" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5" transform="rotate(-45, 48.5, 15.5)"/>
|
||||
<rect x="58" y="14" width="3" height="3" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5" transform="rotate(45, 59.5, 15.5)"/>
|
||||
<!-- Gear center hole -->
|
||||
<circle cx="54" cy="10" r="2.5" fill="#6b5344"/>
|
||||
<circle cx="54" cy="10" r="2.5" fill="#7a6450" stroke="#d4c4b0" stroke-width="0.5"/>
|
||||
|
||||
<!-- Gray Data Flow (river under bridge - settings) -->
|
||||
<!-- Data stream background -->
|
||||
<path d="M 0 60 Q 32 55 64 60" fill="none" stroke="#95a5a6" stroke-width="4" opacity="0.3"/>
|
||||
<path d="M 0 60 Q 32 55 64 60" fill="none" stroke="#a8b8c8" stroke-width="4" opacity="0.4"/>
|
||||
<!-- Left arrow -->
|
||||
<path d="M 6 59 L 16 59" stroke="#95a5a6" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="6,59 11,56 11,62" fill="#95a5a6"/>
|
||||
<path d="M 6 59 L 16 59" stroke="#a8b8c8" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="6,59 11,56 11,62" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<!-- Right arrow -->
|
||||
<path d="M 48 59 L 58 59" stroke="#95a5a6" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="58,59 53,56 53,62" fill="#95a5a6"/>
|
||||
<path d="M 48 59 L 58 59" stroke="#a8b8c8" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<polygon points="58,59 53,56 53,62" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<!-- Center data dots -->
|
||||
<circle cx="26" cy="57" r="2" fill="#95a5a6"/>
|
||||
<circle cx="32" cy="56" r="2" fill="#95a5a6"/>
|
||||
<circle cx="38" cy="57" r="2" fill="#95a5a6"/>
|
||||
<circle cx="26" cy="57" r="2" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<circle cx="32" cy="56" r="2" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
<circle cx="38" cy="57" r="2" fill="#a8b8c8" stroke="#d0e0f0" stroke-width="0.5"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 5.8 KiB |
@@ -33,6 +33,7 @@ Example:
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
from collections.abc import AsyncIterator
|
||||
@@ -411,8 +412,10 @@ def main() -> None:
|
||||
# Set up logging
|
||||
logging.getLogger().setLevel(config.log_level)
|
||||
|
||||
# Print instance ID to stderr for test automation to capture
|
||||
# Must use stderr because stdout is reserved for JSON-RPC in stdio mode
|
||||
# Print instance ID to stderr only for test automation (when env var is set).
|
||||
# This avoids unwanted output during normal use.
|
||||
# Must use stderr because stdout is reserved for JSON-RPC in stdio mode.
|
||||
if os.environ.get("FREECAD_MCP_TESTING"):
|
||||
print(f"FREECAD_MCP_INSTANCE_ID={INSTANCE_ID}", file=sys.stderr, flush=True)
|
||||
|
||||
logger.info("Starting FreeCAD Robust MCP Server")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Tests for the main server module."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
|
||||
@@ -226,7 +227,7 @@ class TestMain:
|
||||
"""Tests for main function."""
|
||||
|
||||
def test_main_prints_instance_id(self):
|
||||
"""Main should print instance ID on startup."""
|
||||
"""Main should print instance ID on startup when FREECAD_MCP_TESTING is set."""
|
||||
import freecad_mcp.server as server_module
|
||||
from freecad_mcp.config import TransportType
|
||||
|
||||
@@ -240,6 +241,7 @@ class TestMain:
|
||||
patch.object(server_module, "get_config", return_value=mock_config),
|
||||
patch.object(server_module.mcp, "run") as mock_run,
|
||||
patch("builtins.print") as mock_print,
|
||||
patch.dict(os.environ, {"FREECAD_MCP_TESTING": "1"}),
|
||||
):
|
||||
# Mock run to exit immediately
|
||||
mock_run.return_value = None
|
||||
@@ -258,6 +260,37 @@ class TestMain:
|
||||
)
|
||||
assert instance_id_call.kwargs.get("file") == sys.stderr
|
||||
|
||||
def test_main_no_instance_id_without_testing_env(self):
|
||||
"""Main should NOT print instance ID when FREECAD_MCP_TESTING is unset."""
|
||||
import freecad_mcp.server as server_module
|
||||
from freecad_mcp.config import TransportType
|
||||
|
||||
mock_config = MagicMock()
|
||||
mock_config.log_level = "INFO"
|
||||
mock_config.mode = FreecadMode.EMBEDDED
|
||||
mock_config.transport = TransportType.STDIO
|
||||
|
||||
# Ensure FREECAD_MCP_TESTING is not set
|
||||
env_without_testing = {
|
||||
k: v for k, v in os.environ.items() if k != "FREECAD_MCP_TESTING"
|
||||
}
|
||||
|
||||
with (
|
||||
patch.object(sys, "argv", DEFAULT_ARGV),
|
||||
patch.object(server_module, "get_config", return_value=mock_config),
|
||||
patch.object(server_module.mcp, "run") as mock_run,
|
||||
patch("builtins.print") as mock_print,
|
||||
patch.dict(os.environ, env_without_testing, clear=True),
|
||||
):
|
||||
# Mock run to exit immediately
|
||||
mock_run.return_value = None
|
||||
|
||||
server_module.main()
|
||||
|
||||
# Check that instance ID was NOT printed
|
||||
print_calls = [str(call) for call in mock_print.call_args_list]
|
||||
assert not any("FREECAD_MCP_INSTANCE_ID=" in call for call in print_calls)
|
||||
|
||||
def test_main_http_transport(self):
|
||||
"""Main should start HTTP transport when configured."""
|
||||
import freecad_mcp.server as server_module
|
||||
@@ -438,6 +471,7 @@ class TestStdioProtocolCleanliness:
|
||||
"FREECAD_MODE": "xmlrpc",
|
||||
"FREECAD_XMLRPC_PORT": "59999",
|
||||
"FREECAD_SOCKET_HOST": "localhost",
|
||||
"FREECAD_MCP_TESTING": "1", # Enable stderr instance ID output
|
||||
},
|
||||
)
|
||||
|
||||
|
||||