firmwareloop 0.0.10__tar.gz → 0.0.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/PKG-INFO +12 -4
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/README.md +11 -3
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/firmwareloop.egg-info/PKG-INFO +12 -4
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/pyproject.toml +1 -1
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/__init__.py +1 -1
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/common/fw.psm1 +13 -5
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/fw_mcp_server.py +106 -10
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/setup-agent-mcp.ps1 +93 -40
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/LICENSE +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/firmwareloop.egg-info/SOURCES.txt +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/firmwareloop.egg-info/dependency_links.txt +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/firmwareloop.egg-info/entry_points.txt +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/firmwareloop.egg-info/requires.txt +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/firmwareloop.egg-info/top_level.txt +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/setup.cfg +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/acceptance-scenario.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/build.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/can.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/check-qoder-mcp.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/common/build-backends.psm1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/common/uart_probe.py +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/doctor.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/flash.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/instrument_cli.py +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/lib/__init__.py +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/lib/instruments.py +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/logic_capture.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/logic_decode.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/reset.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/test-backends.ps1 +0 -0
- {firmwareloop-0.0.10 → firmwareloop-0.0.12}/tools/test.ps1 +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: firmwareloop
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
4
4
|
Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
|
|
5
5
|
Author-email: WeilinZhang <19523330249@163.com>
|
|
6
6
|
License: MIT
|
|
@@ -243,7 +243,15 @@ claude mcp add agentic-hil -- "D:\Tools\FirmwareLoop\.venv\Scripts\agentic-hil.e
|
|
|
243
243
|
fwloop init
|
|
244
244
|
```
|
|
245
245
|
|
|
246
|
-
2.
|
|
246
|
+
2. 自动升级至 PyPI 最新版本(推荐以下任意一种方式):
|
|
247
|
+
```bash
|
|
248
|
+
uv tool upgrade firmwareloop
|
|
249
|
+
```
|
|
250
|
+
或者一键升级全部已安装工具:
|
|
251
|
+
```bash
|
|
252
|
+
uv tool upgrade --all
|
|
253
|
+
```
|
|
254
|
+
或者使用内置热更新命令:
|
|
247
255
|
```bash
|
|
248
256
|
fwloop update
|
|
249
257
|
```
|
|
@@ -328,7 +336,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
328
336
|
├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
|
|
329
337
|
├── demo-make/ 示例固件(Make;构建测试载体)
|
|
330
338
|
├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
|
|
331
|
-
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.0.
|
|
339
|
+
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.0.12)
|
|
332
340
|
├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
|
|
333
341
|
├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
|
|
334
342
|
├── CLAUDE.md Claude Code CLI 指南
|
|
@@ -338,7 +346,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
338
346
|
|
|
339
347
|
---
|
|
340
348
|
|
|
341
|
-
## 能力验证状态(v0.0.
|
|
349
|
+
## 能力验证状态(v0.0.12)
|
|
342
350
|
|
|
343
351
|
> 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
|
|
344
352
|
> `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
|
|
@@ -215,7 +215,15 @@ claude mcp add agentic-hil -- "D:\Tools\FirmwareLoop\.venv\Scripts\agentic-hil.e
|
|
|
215
215
|
fwloop init
|
|
216
216
|
```
|
|
217
217
|
|
|
218
|
-
2.
|
|
218
|
+
2. 自动升级至 PyPI 最新版本(推荐以下任意一种方式):
|
|
219
|
+
```bash
|
|
220
|
+
uv tool upgrade firmwareloop
|
|
221
|
+
```
|
|
222
|
+
或者一键升级全部已安装工具:
|
|
223
|
+
```bash
|
|
224
|
+
uv tool upgrade --all
|
|
225
|
+
```
|
|
226
|
+
或者使用内置热更新命令:
|
|
219
227
|
```bash
|
|
220
228
|
fwloop update
|
|
221
229
|
```
|
|
@@ -300,7 +308,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
300
308
|
├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
|
|
301
309
|
├── demo-make/ 示例固件(Make;构建测试载体)
|
|
302
310
|
├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
|
|
303
|
-
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.0.
|
|
311
|
+
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.0.12)
|
|
304
312
|
├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
|
|
305
313
|
├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
|
|
306
314
|
├── CLAUDE.md Claude Code CLI 指南
|
|
@@ -310,7 +318,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
310
318
|
|
|
311
319
|
---
|
|
312
320
|
|
|
313
|
-
## 能力验证状态(v0.0.
|
|
321
|
+
## 能力验证状态(v0.0.12)
|
|
314
322
|
|
|
315
323
|
> 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
|
|
316
324
|
> `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: firmwareloop
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
4
4
|
Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
|
|
5
5
|
Author-email: WeilinZhang <19523330249@163.com>
|
|
6
6
|
License: MIT
|
|
@@ -243,7 +243,15 @@ claude mcp add agentic-hil -- "D:\Tools\FirmwareLoop\.venv\Scripts\agentic-hil.e
|
|
|
243
243
|
fwloop init
|
|
244
244
|
```
|
|
245
245
|
|
|
246
|
-
2.
|
|
246
|
+
2. 自动升级至 PyPI 最新版本(推荐以下任意一种方式):
|
|
247
|
+
```bash
|
|
248
|
+
uv tool upgrade firmwareloop
|
|
249
|
+
```
|
|
250
|
+
或者一键升级全部已安装工具:
|
|
251
|
+
```bash
|
|
252
|
+
uv tool upgrade --all
|
|
253
|
+
```
|
|
254
|
+
或者使用内置热更新命令:
|
|
247
255
|
```bash
|
|
248
256
|
fwloop update
|
|
249
257
|
```
|
|
@@ -328,7 +336,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
328
336
|
├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
|
|
329
337
|
├── demo-make/ 示例固件(Make;构建测试载体)
|
|
330
338
|
├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
|
|
331
|
-
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.0.
|
|
339
|
+
├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.0.12)
|
|
332
340
|
├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
|
|
333
341
|
├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
|
|
334
342
|
├── CLAUDE.md Claude Code CLI 指南
|
|
@@ -338,7 +346,7 @@ claude mcp remove --scope user agentic-hil
|
|
|
338
346
|
|
|
339
347
|
---
|
|
340
348
|
|
|
341
|
-
## 能力验证状态(v0.0.
|
|
349
|
+
## 能力验证状态(v0.0.12)
|
|
342
350
|
|
|
343
351
|
> 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
|
|
344
352
|
> `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
|
|
@@ -96,14 +96,22 @@ function Resolve-FwPython {
|
|
|
96
96
|
function Get-FwRepoRoot {
|
|
97
97
|
<#
|
|
98
98
|
.SYNOPSIS
|
|
99
|
-
Root of the firmware project = directory containing tools/ and lab
|
|
99
|
+
Root of the firmware project = directory containing tools/ and lab/ (or parent of PSScriptRoot).
|
|
100
100
|
#>
|
|
101
|
-
$
|
|
102
|
-
|
|
101
|
+
if ($PSScriptRoot) {
|
|
102
|
+
$candidate = Split-Path -Parent $PSScriptRoot
|
|
103
|
+
if ($candidate -and ((Test-Path (Join-Path $candidate 'tools')) -or (Test-Path (Join-Path $candidate 'pyproject.toml')))) {
|
|
104
|
+
return $candidate
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
$cur = (Get-Location).Path
|
|
108
|
+
while ($cur -and (Test-Path -LiteralPath $cur)) {
|
|
103
109
|
if ((Test-Path (Join-Path $cur 'tools')) -and (Test-Path (Join-Path $cur 'lab'))) {
|
|
104
|
-
return $cur
|
|
110
|
+
return $cur
|
|
105
111
|
}
|
|
106
|
-
$
|
|
112
|
+
$parent = Split-Path -Parent $cur
|
|
113
|
+
if (-not $parent -or $parent -eq $cur) { break }
|
|
114
|
+
$cur = $parent
|
|
107
115
|
}
|
|
108
116
|
return (Get-Location).Path
|
|
109
117
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
|
-
fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.0.
|
|
3
|
+
fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.0.12).
|
|
4
4
|
|
|
5
5
|
Exposes high-level firmware engineering and hardware management tools to AI Coding
|
|
6
6
|
Agents (Antigravity CLI, Claude Code CLI, Qoder IDE, Cursor) via the Model Context
|
|
@@ -1160,7 +1160,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
|
1160
1160
|
},
|
|
1161
1161
|
"serverInfo": {
|
|
1162
1162
|
"name": "firmwareloop",
|
|
1163
|
-
"version": "0.0.
|
|
1163
|
+
"version": "0.0.12"
|
|
1164
1164
|
}
|
|
1165
1165
|
}
|
|
1166
1166
|
}
|
|
@@ -1252,7 +1252,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
|
1252
1252
|
def handle_cli_update() -> int:
|
|
1253
1253
|
"""Handle `firmwareloop update` command."""
|
|
1254
1254
|
print("============================================================")
|
|
1255
|
-
print(" FirmwareLoop Auto-Updater (v0.0.
|
|
1255
|
+
print(" FirmwareLoop Auto-Updater (v0.0.12)")
|
|
1256
1256
|
print("============================================================")
|
|
1257
1257
|
|
|
1258
1258
|
is_git_repo = os.path.exists(os.path.join(REPO_ROOT, ".git"))
|
|
@@ -1317,16 +1317,112 @@ def handle_cli_doctor() -> int:
|
|
|
1317
1317
|
|
|
1318
1318
|
|
|
1319
1319
|
def handle_cli_setup() -> int:
|
|
1320
|
-
"""Handle `firmwareloop setup` command."""
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1320
|
+
"""Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, and Qoder IDE."""
|
|
1321
|
+
print("============================================================")
|
|
1322
|
+
print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.0.12)")
|
|
1323
|
+
print("============================================================")
|
|
1324
|
+
print("")
|
|
1325
|
+
|
|
1326
|
+
user_home = os.path.expanduser("~")
|
|
1327
|
+
configured_agents = []
|
|
1328
|
+
|
|
1329
|
+
# 1. Google Antigravity / Gemini CLI
|
|
1330
|
+
print("[1] Google Antigravity / Gemini CLI:")
|
|
1331
|
+
ag_config_dir = os.path.join(user_home, ".gemini", "config")
|
|
1332
|
+
ag_mcp_file = os.path.join(ag_config_dir, "mcp_config.json")
|
|
1333
|
+
try:
|
|
1334
|
+
os.makedirs(ag_config_dir, exist_ok=True)
|
|
1335
|
+
ag_data = {}
|
|
1336
|
+
if os.path.exists(ag_mcp_file):
|
|
1337
|
+
try:
|
|
1338
|
+
with open(ag_mcp_file, "r", encoding="utf-8-sig") as f:
|
|
1339
|
+
ag_data = json.load(f)
|
|
1340
|
+
except Exception:
|
|
1341
|
+
ag_data = {}
|
|
1342
|
+
if "mcpServers" not in ag_data:
|
|
1343
|
+
ag_data["mcpServers"] = {}
|
|
1344
|
+
ag_data["mcpServers"]["firmwareloop"] = {"command": "fwloop"}
|
|
1345
|
+
ag_data["mcpServers"]["agentic-hil"] = {"command": "agentic-hil", "args": ["mcp-stdio"]}
|
|
1346
|
+
with open(ag_mcp_file, "w", encoding="utf-8") as f:
|
|
1347
|
+
json.dump(ag_data, f, indent=2)
|
|
1348
|
+
print(f" - Global MCP Config: [OK] Written to {ag_mcp_file}")
|
|
1349
|
+
configured_agents.append("Google Antigravity")
|
|
1350
|
+
except Exception as e:
|
|
1351
|
+
print(f" - Global MCP Config: [Warning] Could not write Antigravity config: {e}")
|
|
1352
|
+
|
|
1353
|
+
# 2. Claude Code CLI
|
|
1354
|
+
print("\n[2] Claude Code CLI:")
|
|
1355
|
+
claude_file = os.path.join(user_home, ".claude.json")
|
|
1356
|
+
try:
|
|
1357
|
+
claude_data = {}
|
|
1358
|
+
if os.path.exists(claude_file):
|
|
1359
|
+
try:
|
|
1360
|
+
with open(claude_file, "r", encoding="utf-8-sig") as f:
|
|
1361
|
+
claude_data = json.load(f)
|
|
1362
|
+
except Exception:
|
|
1363
|
+
claude_data = {}
|
|
1364
|
+
if "mcpServers" not in claude_data:
|
|
1365
|
+
claude_data["mcpServers"] = {}
|
|
1366
|
+
claude_data["mcpServers"]["fwloop"] = {"command": "fwloop"}
|
|
1367
|
+
claude_data["mcpServers"]["agentic-hil"] = {"command": "agentic-hil", "args": ["mcp-stdio"]}
|
|
1368
|
+
with open(claude_file, "w", encoding="utf-8") as f:
|
|
1369
|
+
json.dump(claude_data, f, indent=2)
|
|
1370
|
+
print(f" - Global MCP Config: [OK] Written to {claude_file}")
|
|
1371
|
+
configured_agents.append("Claude Code")
|
|
1372
|
+
except Exception as e:
|
|
1373
|
+
print(f" - Global MCP Config: [Warning] Could not update .claude.json: {e}")
|
|
1374
|
+
|
|
1375
|
+
# 3. Qoder IDE
|
|
1376
|
+
print("\n[3] Qoder IDE:")
|
|
1377
|
+
qoder_cmd = shutil.which("qoder.cmd") or shutil.which("qoder")
|
|
1378
|
+
if qoder_cmd:
|
|
1379
|
+
try:
|
|
1380
|
+
r1 = subprocess.run([qoder_cmd, "--add-mcp", json.dumps({"name": "firmwareloop", "command": "fwloop"})], shell=True, capture_output=True, text=True)
|
|
1381
|
+
r2 = subprocess.run([qoder_cmd, "--add-mcp", json.dumps({"name": "agentic-hil", "command": "agentic-hil", "args": ["mcp-stdio"]})], shell=True, capture_output=True, text=True)
|
|
1382
|
+
if r1.returncode == 0 and r2.returncode == 0:
|
|
1383
|
+
print(" - User Profile MCP: [OK] Automatically registered to Qoder User Profile")
|
|
1384
|
+
configured_agents.append("Qoder IDE")
|
|
1385
|
+
else:
|
|
1386
|
+
print(f" - User Profile MCP: [Notice] Qoder CLI output: {r1.stdout.strip()}")
|
|
1387
|
+
except Exception as e:
|
|
1388
|
+
print(f" - User Profile MCP: [Warning] Could not invoke qoder CLI: {e}")
|
|
1389
|
+
else:
|
|
1390
|
+
print(" - User Profile MCP: Qoder CLI not in PATH (Workspace .mcp.json supported)")
|
|
1391
|
+
|
|
1392
|
+
# 4. Global Skills Sync for Antigravity and Claude Code
|
|
1393
|
+
ag_skills_dir = os.path.join(user_home, ".gemini", "antigravity-cli", "skills")
|
|
1394
|
+
claude_skills_dir = os.path.join(user_home, ".claude", "skills")
|
|
1395
|
+
source_skills_dir = os.path.join(REPO_ROOT, "skills")
|
|
1396
|
+
skills_synced = 0
|
|
1397
|
+
if os.path.exists(source_skills_dir):
|
|
1398
|
+
for sk in ["firmwareloop", "fwloop-adapter"]:
|
|
1399
|
+
sk_src = os.path.join(source_skills_dir, sk, "SKILL.md")
|
|
1400
|
+
if os.path.exists(sk_src):
|
|
1401
|
+
try:
|
|
1402
|
+
ag_target = os.path.join(ag_skills_dir, sk)
|
|
1403
|
+
os.makedirs(ag_target, exist_ok=True)
|
|
1404
|
+
shutil.copyfile(sk_src, os.path.join(ag_target, "SKILL.md"))
|
|
1405
|
+
|
|
1406
|
+
cl_target = os.path.join(claude_skills_dir, sk)
|
|
1407
|
+
os.makedirs(cl_target, exist_ok=True)
|
|
1408
|
+
shutil.copyfile(sk_src, os.path.join(cl_target, "SKILL.md"))
|
|
1409
|
+
skills_synced += 1
|
|
1410
|
+
except Exception:
|
|
1411
|
+
pass
|
|
1412
|
+
|
|
1413
|
+
print(f"\n[4] Global Skills:")
|
|
1414
|
+
print(f" - Synchronized: [OK] {skills_synced} skills (firmwareloop, fwloop-adapter) to Antigravity & Claude Code")
|
|
1415
|
+
|
|
1416
|
+
print("\n============================================================")
|
|
1417
|
+
print(f"[+] All AI Coding Agents ({', '.join(configured_agents)}) are globally configured and ready!")
|
|
1418
|
+
print("============================================================")
|
|
1419
|
+
return 0
|
|
1324
1420
|
|
|
1325
1421
|
|
|
1326
1422
|
def handle_cli_init() -> int:
|
|
1327
1423
|
"""Handle `firmwareloop init` command."""
|
|
1328
1424
|
print("============================================================")
|
|
1329
|
-
print(" FirmwareLoop Multi-Agent Project Initializer (v0.0.
|
|
1425
|
+
print(" FirmwareLoop Multi-Agent Project Initializer (v0.0.12)")
|
|
1330
1426
|
print("============================================================")
|
|
1331
1427
|
cwd = os.getcwd()
|
|
1332
1428
|
print(f"[*] Initializing multi-agent guidelines & bench config in:\n {cwd}\n")
|
|
@@ -1347,7 +1443,7 @@ def handle_cli_init() -> int:
|
|
|
1347
1443
|
|
|
1348
1444
|
|
|
1349
1445
|
def print_cli_help() -> None:
|
|
1350
|
-
print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.0.
|
|
1446
|
+
print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.0.12)
|
|
1351
1447
|
|
|
1352
1448
|
Usage:
|
|
1353
1449
|
fwloop [command] (or: firmwareloop [command])
|
|
@@ -1378,7 +1474,7 @@ def main() -> None:
|
|
|
1378
1474
|
elif cmd in ["setup", "register"]:
|
|
1379
1475
|
sys.exit(handle_cli_setup())
|
|
1380
1476
|
elif cmd in ["version", "-v", "--version"]:
|
|
1381
|
-
print("FirmwareLoop v0.0.
|
|
1477
|
+
print("FirmwareLoop v0.0.12")
|
|
1382
1478
|
sys.exit(0)
|
|
1383
1479
|
elif cmd in ["help", "-h", "--help"]:
|
|
1384
1480
|
print_cli_help()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<#
|
|
2
2
|
.SYNOPSIS
|
|
3
|
-
Dual-Tier MCP setup and registration helper (v0.0.
|
|
3
|
+
Dual-Tier MCP setup and registration helper (v0.0.12).
|
|
4
4
|
Inspects installed AI coding agents (Qoder, Claude Code, Antigravity, Cursor)
|
|
5
|
-
and
|
|
5
|
+
and configures global MCP / skills or prints exact registration commands.
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
8
|
.\tools\setup-agent-mcp.ps1
|
|
@@ -24,17 +24,23 @@ $python = Resolve-FwPython -RepoRoot $repoRoot
|
|
|
24
24
|
$fwMcpServer = Join-Path $repoRoot 'tools\fw_mcp_server.py'
|
|
25
25
|
$ahilExe = Join-Path $repoRoot '.venv\Scripts\agentic-hil.exe'
|
|
26
26
|
|
|
27
|
+
$isSourceRepo = (Test-Path -LiteralPath $fwMcpServer)
|
|
28
|
+
|
|
29
|
+
$fwCmdName = if ($isSourceRepo -and $python) { "`"$python`" `"$fwMcpServer`"" } else { "fwloop" }
|
|
30
|
+
$ahilCmdName = if (Test-Path -LiteralPath $ahilExe) { "`"$ahilExe`" mcp-stdio" } else { "agentic-hil mcp-stdio" }
|
|
31
|
+
|
|
27
32
|
$report = [ordered]@{
|
|
28
33
|
schema = 'firmwareloop-mcp-setup/v1'
|
|
29
34
|
repo_root = $repoRoot
|
|
35
|
+
is_source_repo = $isSourceRepo
|
|
30
36
|
servers = [ordered]@{
|
|
31
37
|
firmwareloop = [ordered]@{
|
|
32
|
-
command = $python
|
|
33
|
-
args = @($fwMcpServer)
|
|
38
|
+
command = if ($isSourceRepo -and $python) { $python } else { "fwloop" }
|
|
39
|
+
args = if ($isSourceRepo) { @($fwMcpServer) } else { @() }
|
|
34
40
|
description = 'Upper-tier firmware engineering workflow MCP'
|
|
35
41
|
}
|
|
36
42
|
agentic_hil = [ordered]@{
|
|
37
|
-
command = $ahilExe
|
|
43
|
+
command = if (Test-Path -LiteralPath $ahilExe) { $ahilExe } else { "agentic-hil" }
|
|
38
44
|
args = @('mcp-stdio')
|
|
39
45
|
description = 'Lower-tier physical hardware & probe MCP'
|
|
40
46
|
}
|
|
@@ -42,42 +48,77 @@ $report = [ordered]@{
|
|
|
42
48
|
agents = [ordered]@{}
|
|
43
49
|
}
|
|
44
50
|
|
|
45
|
-
# 1. Claude Code CLI
|
|
51
|
+
# 1. Claude Code CLI 全局 MCP 自动配置
|
|
46
52
|
$claudeCmd = Get-Command claude -ErrorAction SilentlyContinue
|
|
53
|
+
$claudeConfigUpdated = $false
|
|
54
|
+
$claudeConfigFile = Join-Path $env:USERPROFILE '.claude.json'
|
|
55
|
+
if (Test-Path -LiteralPath $claudeConfigFile) {
|
|
56
|
+
try {
|
|
57
|
+
$existingClaude = Get-Content -LiteralPath $claudeConfigFile -Raw -Encoding UTF8 | ConvertFrom-Json
|
|
58
|
+
if (-not $existingClaude.PSObject.Properties['mcpServers']) {
|
|
59
|
+
$existingClaude | Add-Member -MemberType NoteProperty -Name 'mcpServers' -Value ([pscustomobject]@{})
|
|
60
|
+
}
|
|
61
|
+
$existingClaude.mcpServers | Add-Member -MemberType NoteProperty -Name 'fwloop' -Value ([pscustomobject]@{ command = "fwloop" }) -Force
|
|
62
|
+
$existingClaude.mcpServers | Add-Member -MemberType NoteProperty -Name 'agentic-hil' -Value ([pscustomobject]@{ command = "agentic-hil"; args = @("mcp-stdio") }) -Force
|
|
63
|
+
$updatedClaudeStr = ConvertTo-Json -InputObject $existingClaude -Depth 20
|
|
64
|
+
$utf8NoBom = [System.Text.UTF8Encoding]::new($false)
|
|
65
|
+
[System.IO.File]::WriteAllText($claudeConfigFile, $updatedClaudeStr, $utf8NoBom)
|
|
66
|
+
$claudeConfigUpdated = $true
|
|
67
|
+
} catch {
|
|
68
|
+
# ignore non-fatal config write error
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if ($claudeCmd -and -not $claudeConfigUpdated) {
|
|
72
|
+
try {
|
|
73
|
+
& $claudeCmd.Source mcp add --scope user fwloop -- fwloop | Out-Null
|
|
74
|
+
& $claudeCmd.Source mcp add --scope user agentic-hil -- agentic-hil mcp-stdio | Out-Null
|
|
75
|
+
$claudeConfigUpdated = $true
|
|
76
|
+
} catch {
|
|
77
|
+
# ignore non-fatal error
|
|
78
|
+
}
|
|
79
|
+
}
|
|
47
80
|
$report.agents.claude_code = [ordered]@{
|
|
48
81
|
detected = ($null -ne $claudeCmd)
|
|
49
82
|
path = if ($claudeCmd) { $claudeCmd.Source } else { $null }
|
|
83
|
+
configured = $claudeConfigUpdated
|
|
50
84
|
registration_commands = @(
|
|
51
|
-
"claude mcp add
|
|
52
|
-
"claude mcp add agentic-hil --
|
|
85
|
+
"claude mcp add --scope user fwloop -- $fwCmdName",
|
|
86
|
+
"claude mcp add --scope user agentic-hil -- $ahilCmdName"
|
|
53
87
|
)
|
|
54
88
|
}
|
|
55
89
|
|
|
56
|
-
# 2. Qoder IDE / CLI
|
|
90
|
+
# 2. Qoder IDE / CLI 全局 User Profile MCP 自动配置
|
|
57
91
|
$qoderCmd = $null
|
|
58
|
-
foreach ($name in @('qoder', 'qodercli')) {
|
|
92
|
+
foreach ($name in @('qoder.cmd', 'qoder', 'qodercli')) {
|
|
59
93
|
$c = Get-Command $name -ErrorAction SilentlyContinue
|
|
60
94
|
if ($c) { $qoderCmd = $c; break }
|
|
61
95
|
}
|
|
96
|
+
$qoderConfigured = $false
|
|
97
|
+
if ($qoderCmd) {
|
|
98
|
+
try {
|
|
99
|
+
$fwJsonStr = '{"name":"firmwareloop","command":"fwloop"}'
|
|
100
|
+
$ahilJsonStr = '{"name":"agentic-hil","command":"agentic-hil","args":["mcp-stdio"]}'
|
|
101
|
+
& $qoderCmd.Source --add-mcp $fwJsonStr | Out-Null
|
|
102
|
+
& $qoderCmd.Source --add-mcp $ahilJsonStr | Out-Null
|
|
103
|
+
$qoderConfigured = $true
|
|
104
|
+
} catch {
|
|
105
|
+
# ignore non-fatal error
|
|
106
|
+
}
|
|
107
|
+
}
|
|
62
108
|
$report.agents.qoder = [ordered]@{
|
|
63
109
|
detected = ($null -ne $qoderCmd)
|
|
64
110
|
path = if ($qoderCmd) { $qoderCmd.Source } else { $null }
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
} else {
|
|
71
|
-
@(
|
|
72
|
-
"qoder mcp add firmwareloop -- `"$python`" `"$fwMcpServer`"",
|
|
73
|
-
"qoder mcp add agentic-hil -- `"$ahilExe`" mcp-stdio"
|
|
74
|
-
)
|
|
75
|
-
}
|
|
111
|
+
user_profile_configured = $qoderConfigured
|
|
112
|
+
registration_commands = @(
|
|
113
|
+
"qoder.cmd --add-mcp '{\`"name\`":\`"firmwareloop\`",\`"command\`":\`"fwloop\`"}'",
|
|
114
|
+
"qoder.cmd --add-mcp '{\`"name\`":\`"agentic-hil\`",\`"command\`":\`"agentic-hil\`",\`"args\`":[\`"mcp-stdio\`"]}'"
|
|
115
|
+
)
|
|
76
116
|
}
|
|
77
117
|
|
|
78
|
-
# 3. Antigravity CLI / Gemini 全局 MCP
|
|
118
|
+
# 3. Antigravity CLI / Gemini 全局 MCP 自动配置与 Skills
|
|
79
119
|
$antigravityConfigDir = Join-Path $env:USERPROFILE '.gemini\config'
|
|
80
120
|
$antigravityMcpConfigFile = Join-Path $antigravityConfigDir 'mcp_config.json'
|
|
121
|
+
$antigravityMcpUpdated = $false
|
|
81
122
|
if (Test-Path -LiteralPath $antigravityConfigDir) {
|
|
82
123
|
try {
|
|
83
124
|
$existingJson = if (Test-Path -LiteralPath $antigravityMcpConfigFile) {
|
|
@@ -91,7 +132,9 @@ if (Test-Path -LiteralPath $antigravityConfigDir) {
|
|
|
91
132
|
$existingJson.mcpServers | Add-Member -MemberType NoteProperty -Name 'firmwareloop' -Value ([pscustomobject]@{ command = "fwloop" }) -Force
|
|
92
133
|
$existingJson.mcpServers | Add-Member -MemberType NoteProperty -Name 'agentic-hil' -Value ([pscustomobject]@{ command = "agentic-hil"; args = @("mcp-stdio") }) -Force
|
|
93
134
|
$updatedJsonStr = ConvertTo-Json -InputObject $existingJson -Depth 10
|
|
94
|
-
|
|
135
|
+
$utf8NoBom = [System.Text.UTF8Encoding]::new($false)
|
|
136
|
+
[System.IO.File]::WriteAllText($antigravityMcpConfigFile, $updatedJsonStr, $utf8NoBom)
|
|
137
|
+
$antigravityMcpUpdated = $true
|
|
95
138
|
} catch {
|
|
96
139
|
# ignore non-fatal config write error
|
|
97
140
|
}
|
|
@@ -126,6 +169,7 @@ if (Test-Path -LiteralPath $sourceSkillsDir) {
|
|
|
126
169
|
|
|
127
170
|
$report.agents.antigravity = [ordered]@{
|
|
128
171
|
mcp_config_path = $antigravityMcpConfigFile
|
|
172
|
+
mcp_configured = $antigravityMcpUpdated
|
|
129
173
|
global_skills_installed = ($installedSkills.Count -gt 0)
|
|
130
174
|
installed_skills = $installedSkills
|
|
131
175
|
note = "Antigravity global mcp_config.json and skills configured."
|
|
@@ -138,20 +182,21 @@ if ($WriteWorkspaceMcp) {
|
|
|
138
182
|
mcpServers = [ordered]@{
|
|
139
183
|
firmwareloop = [ordered]@{
|
|
140
184
|
type = 'stdio'
|
|
141
|
-
command = $python
|
|
142
|
-
args = @($fwMcpServer)
|
|
185
|
+
command = if ($isSourceRepo -and $python) { $python } else { "fwloop" }
|
|
186
|
+
args = if ($isSourceRepo) { @($fwMcpServer) } else { @() }
|
|
143
187
|
timeout = 300000
|
|
144
188
|
}
|
|
145
189
|
"agentic-hil" = [ordered]@{
|
|
146
190
|
type = 'stdio'
|
|
147
|
-
command = $ahilExe
|
|
191
|
+
command = if (Test-Path -LiteralPath $ahilExe) { $ahilExe } else { "agentic-hil" }
|
|
148
192
|
args = @('mcp-stdio')
|
|
149
193
|
timeout = 120000
|
|
150
194
|
}
|
|
151
195
|
}
|
|
152
196
|
}
|
|
153
197
|
$jsonContent = ConvertTo-Json -InputObject $mcpConfig -Depth 10
|
|
154
|
-
|
|
198
|
+
$utf8NoBom = [System.Text.UTF8Encoding]::new($false)
|
|
199
|
+
[System.IO.File]::WriteAllText($mcpJsonPath, $jsonContent, $utf8NoBom)
|
|
155
200
|
$report.workspace_mcp_written = $mcpJsonPath
|
|
156
201
|
}
|
|
157
202
|
|
|
@@ -159,24 +204,32 @@ if ($Json) {
|
|
|
159
204
|
Write-FwJson ([pscustomobject]$report)
|
|
160
205
|
} else {
|
|
161
206
|
Write-Host "============================================================" -ForegroundColor Cyan
|
|
162
|
-
Write-Host "FirmwareLoop
|
|
207
|
+
Write-Host " FirmwareLoop Dual-Tier MCP & Agent Setup Helper (v0.0.10)" -ForegroundColor Green
|
|
163
208
|
Write-Host "============================================================" -ForegroundColor Cyan
|
|
164
209
|
Write-Host ""
|
|
165
|
-
Write-Host "[1]
|
|
210
|
+
Write-Host "[1] Google Antigravity / Gemini CLI:" -ForegroundColor Yellow
|
|
211
|
+
if ($antigravityMcpUpdated) {
|
|
212
|
+
Write-Host " - Global MCP Config: [OK] Written to $antigravityMcpConfigFile" -ForegroundColor Green
|
|
213
|
+
} else {
|
|
214
|
+
Write-Host " - Global MCP Config: ~/.gemini/config/mcp_config.json (Ready)"
|
|
215
|
+
}
|
|
216
|
+
if ($installedSkills.Count -gt 0) {
|
|
217
|
+
Write-Host " - Global Skills: [OK] Synchronized $($installedSkills.Count) skills ($($installedSkills -join ', ')) to Antigravity & Claude Code" -ForegroundColor Green
|
|
218
|
+
}
|
|
219
|
+
Write-Host ""
|
|
220
|
+
Write-Host "[2] Claude Code CLI Registration:" -ForegroundColor Yellow
|
|
166
221
|
Write-Host " $($report.agents.claude_code.registration_commands[0])"
|
|
167
222
|
Write-Host " $($report.agents.claude_code.registration_commands[1])"
|
|
168
223
|
Write-Host ""
|
|
169
|
-
Write-Host "[
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
Write-Host ""
|
|
175
|
-
Write-Host "[3] Antigravity CLI / Cursor / VS Code:" -ForegroundColor Yellow
|
|
176
|
-
Write-Host " - MCP: Automatically reads '.mcp.json' in workspace root"
|
|
177
|
-
if ($skillInstalled) {
|
|
178
|
-
Write-Host " - Global Skill: [OK] Successfully registered to: $targetGlobalSkillDir\SKILL.md" -ForegroundColor Green
|
|
224
|
+
Write-Host "[3] Qoder IDE:" -ForegroundColor Yellow
|
|
225
|
+
if ($qoderConfigured) {
|
|
226
|
+
Write-Host " - User Profile MCP: [OK] Automatically registered to Qoder User Profile" -ForegroundColor Green
|
|
227
|
+
} else {
|
|
228
|
+
Write-Host " - User Profile MCP: Run $($report.agents.qoder.registration_commands[0])"
|
|
179
229
|
}
|
|
180
|
-
Write-Host " -
|
|
230
|
+
Write-Host " - Workspace: Project root '.mcp.json' is automatically detected"
|
|
181
231
|
Write-Host ""
|
|
232
|
+
Write-Host "============================================================" -ForegroundColor Cyan
|
|
233
|
+
Write-Host "[+] All AI Coding Agents are configured and ready!" -ForegroundColor Green
|
|
234
|
+
Write-Host "============================================================" -ForegroundColor Cyan
|
|
182
235
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|