The Python MCP server + hardware test harness that lived under mcp-server/ now has its own home at https://github.com/meshtastic/meshtastic-mcp (published, versioned independently). Remove the in-tree copy and wire the firmware repo to the standalone server externally. - Delete mcp-server/ (96 files) and the 8 harness-coupled AI workflow files under .claude/commands/ and .github/prompts/ that drove ./mcp-server/ run-tests.sh — those workflows now ship with meshtastic-mcp as skills. - .mcp.json: register the server via `uvx --from git+https://github.com/meshtastic/meshtastic-mcp meshtastic-mcp` instead of a local ./mcp-server/.venv, keeping MESHTASTIC_FIRMWARE_ROOT="." so the MCP tools still work from this checkout with no local build. - Repoint the remaining references (AGENTS.md, CLAUDE.md, .github/copilot-instructions.md, bin/regen-*.sh, docs, Screen.h, userPrefs.jsonc, test/fixtures/nodedb/README.md, .trunk/configs/.bandit) at the standalone repo. The MCP tool surface is unchanged — only the pytest harness moves out; run it from a meshtastic-mcp checkout with MESHTASTIC_FIRMWARE_ROOT pointed here. No build/CI/platformio coupling existed, so nothing in the firmware build changes. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
65 lines
2.5 KiB
Python
Executable File
65 lines
2.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Post-process protoc-generated Python files to live under a local namespace.
|
|
|
|
Called by bin/regen-py-protos.sh. Walks the generated *_pb2.py files in the
|
|
target directory and rewrites every `meshtastic` reference (imports, dotted
|
|
attribute access) to use the new namespace (e.g., `meshtastic_v25`).
|
|
|
|
Why: the .proto files declare `package meshtastic;`, so protoc emits
|
|
`from meshtastic import mesh_pb2 as ...` lines. That would shadow the PyPI
|
|
`meshtastic` package which the meshtastic-mcp tooling depends on. Renaming
|
|
to a local namespace keeps both available.
|
|
|
|
Usage:
|
|
_rewrite_proto_namespace.py <generated_dir> <new_namespace>
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pathlib
|
|
import re
|
|
import sys
|
|
|
|
|
|
def rewrite(dir_path: pathlib.Path, new_ns: str) -> int:
|
|
# Standard protoc import forms:
|
|
# from meshtastic.X_pb2 import ... (rare, for direct symbol pulls)
|
|
# from meshtastic import X_pb2 as ... (common, the cross-file ref)
|
|
# import meshtastic.X_pb2 (also possible)
|
|
pattern_dotted_from = re.compile(r"^from meshtastic\.", re.MULTILINE)
|
|
pattern_bare_from = re.compile(r"^from meshtastic import ", re.MULTILINE)
|
|
pattern_dotted_import = re.compile(r"^import meshtastic\.", re.MULTILINE)
|
|
|
|
count = 0
|
|
for p in dir_path.glob("*.py"):
|
|
text = p.read_text(encoding="utf-8")
|
|
new = pattern_dotted_from.sub(f"from {new_ns}.", text)
|
|
new = pattern_bare_from.sub(f"from {new_ns} import ", new)
|
|
new = pattern_dotted_import.sub(f"import {new_ns}.", new)
|
|
# NOTE: we deliberately leave `meshtastic/X.proto` source-filename
|
|
# references inside descriptor strings alone. The descriptor pool is
|
|
# keyed by source filename (independent of Python package layout), so
|
|
# those don't collide with the PyPI package's descriptors.
|
|
if new != text:
|
|
p.write_text(new, encoding="utf-8")
|
|
count += 1
|
|
return count
|
|
|
|
|
|
def main(argv: list[str]) -> int:
|
|
if len(argv) != 2:
|
|
print("usage: _rewrite_proto_namespace.py <generated_dir> <new_namespace>", file=sys.stderr)
|
|
return 2
|
|
dir_path = pathlib.Path(argv[0])
|
|
new_ns = argv[1]
|
|
if not dir_path.is_dir():
|
|
print(f"directory not found: {dir_path}", file=sys.stderr)
|
|
return 2
|
|
n = rewrite(dir_path, new_ns)
|
|
print(f"rewrote {n} file(s) in {dir_path} → namespace {new_ns}", file=sys.stderr)
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main(sys.argv[1:]))
|