Audited the package against the two-stage procedure before a first PyPI publish. The sdist and wheel were already tight, but three things needed fixing and the controls needed to become real rather than documented. The simulator volunteered high="PI04" as its product serial, which is the real Bebop 2 serial prefix. Nothing unique to one aircraft, but a realistic prefix invites being quoted into a bug report as a specimen, so it now reads "N0TAREAL" / "0000000SIM" with a comment saying why it is nonsense on purpose. The low half and the 500.0 no-fix GPS sentinel were already fake. Hardened [tool.uv.build-backend] source-exclude well past the directories that exist today: captures at any depth, log dumps, recorded media by extension, caches, and anything credential-shaped. .gitignore governs git and source-exclude governs the sdist; a capture can sit in one and not the other, which is how this kind of data reaches an immutable index. Verified the broad patterns do not over-reach: arsdk-xml/ with PROVENANCE.md and tools/logs.py both still ship. Added LICENSE (MIT) and LICENSE-arsdk-xml (Parrot SA's BSD-3-Clause), and corrected the declared licence to "MIT AND BSD-3-Clause". The vendored XML ships in both artifacts because nothing here decodes a command without it, so MIT alone understated what is in the box. Both texts now appear in the artifacts and in the metadata. test_packaging.py grows privacy guards that fail on a serial prefix, a P7 CPU id, any MAC, a high-precision coordinate, an absolute home path, or any private address other than the drone's own documented 192.168.42.0/24. Each pattern was checked against the real identifiers to confirm it bites, since a guard that passes on an empty tree proves nothing. Example address in test_arsdk_session.py moved to RFC 5737 space. 504 tests pass, ruff clean.
129 lines
3.8 KiB
TOML
129 lines
3.8 KiB
TOML
[project]
|
|
name = "mcbebop"
|
|
version = "2026.10.02"
|
|
description = "MCP server for the Parrot Bebop 2 drone: telemetry, camera, files, and every ARSDK command"
|
|
readme = "README.md"
|
|
requires-python = ">=3.12"
|
|
# Our own code is MIT. The vendored arsdk-xml/ is Parrot SA's, BSD-3-Clause,
|
|
# and it ships in both artifacts because the package cannot decode a single
|
|
# command without it, so the distribution as a whole is both.
|
|
license = "MIT AND BSD-3-Clause"
|
|
license-files = ["LICENSE", "LICENSE-arsdk-xml"]
|
|
authors = [{name = "Ryan Malloy", email = "ryan@supported.systems"}]
|
|
keywords = ["mcp", "drone", "parrot", "bebop", "arsdk", "fastmcp"]
|
|
classifiers = [
|
|
"Development Status :: 3 - Alpha",
|
|
"Intended Audience :: Developers",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Topic :: Scientific/Engineering",
|
|
]
|
|
dependencies = [
|
|
# 4.x is the current family; <5 because FastMCP has moved import paths
|
|
# across majors before (mcvnc was broken by the 3 -> 4 move).
|
|
"fastmcp>=4.0.10,<5",
|
|
"pydantic-settings>=2.7",
|
|
"zeroconf>=0.147", # mDNS discovery of _arsdk-090c._udp
|
|
"pillow>=11.0", # downscale camera frames before they reach the model
|
|
]
|
|
|
|
[project.urls]
|
|
Homepage = "https://warehack.ing"
|
|
Repository = "https://git.supported.systems/rsp2k/mcbebop"
|
|
|
|
[project.scripts]
|
|
mcbebop = "mcbebop.server:main"
|
|
|
|
[build-system]
|
|
requires = ["uv_build>=0.11.3,<0.12.0"]
|
|
build-backend = "uv_build"
|
|
|
|
[tool.uv.build-backend]
|
|
# Err toward excluding. This repo sits next to a real aircraft, and `captures/`
|
|
# holds video of the owner's home plus `ckcm.bin` system logs that carry the
|
|
# serial, the CPU id and a real GPS fix together. None of it may ever reach an
|
|
# sdist, which is immutable and mirrored within minutes of upload.
|
|
#
|
|
# `.gitignore` does NOT protect this: it governs git, and source-exclude
|
|
# governs the sdist. A file can easily be in one and not the other, so the
|
|
# patterns below are deliberately broader than the directories that exist
|
|
# today -- a capture dropped into a new directory next year is still excluded.
|
|
# test_packaging.py asserts both halves stay in agreement.
|
|
source-exclude = [
|
|
# Operator-private context and anything credential-shaped.
|
|
"CLAUDE.md",
|
|
".env",
|
|
".env.*",
|
|
".mcp.json",
|
|
".claude",
|
|
".claude/**",
|
|
# Dev-only trees. Tests carry fixtures copy-pasted from a live aircraft.
|
|
"tests",
|
|
"tests/**",
|
|
"docs",
|
|
"docs/**",
|
|
"scripts",
|
|
"scripts/**",
|
|
"*.ipynb",
|
|
# Captures off the aircraft, at any depth, plus log dumps.
|
|
"captures",
|
|
"captures/**",
|
|
"**/captures/**",
|
|
"**/logs/**",
|
|
"ckcm*",
|
|
"**/ckcm*",
|
|
# Recorded media and binary blobs by extension, so a stray file in a
|
|
# directory nobody thought to list is still caught.
|
|
"*.rtpcap",
|
|
"*.raw",
|
|
"*.h264",
|
|
"*.bin",
|
|
"*.pcap",
|
|
"*.pcapng",
|
|
"*.mp4",
|
|
"*.jpg",
|
|
"*.jpeg",
|
|
"*.png",
|
|
"*.wav",
|
|
"*.ulg",
|
|
"**/*.rtpcap",
|
|
"**/*.raw",
|
|
"**/*.h264",
|
|
"**/*.bin",
|
|
"**/*.jpg",
|
|
"**/*.jpeg",
|
|
"**/*.png",
|
|
# Caches and build output. .pyc files embed the absolute build path, which
|
|
# leaks a username and the local directory layout.
|
|
"**/__pycache__",
|
|
"**/__pycache__/**",
|
|
"*.pyc",
|
|
"**/*.pyc",
|
|
".pytest_cache",
|
|
".pytest_cache/**",
|
|
".ruff_cache",
|
|
".ruff_cache/**",
|
|
".venv",
|
|
".venv/**",
|
|
"dist",
|
|
"dist/**",
|
|
"build",
|
|
"build/**",
|
|
"*.egg-info",
|
|
]
|
|
|
|
[dependency-groups]
|
|
dev = ["ruff>=0.16", "pytest>=8.0", "pytest-asyncio>=0.25"]
|
|
|
|
[tool.pytest.ini_options]
|
|
asyncio_mode = "auto"
|
|
markers = ["drone: needs a real Bebop 2 on the network (run with '-m drone')"]
|
|
addopts = "-m 'not drone'"
|
|
|
|
[tool.ruff]
|
|
line-length = 110
|
|
target-version = "py312"
|
|
|
|
[tool.ruff.lint]
|
|
select = ["E", "F", "I", "W", "UP", "B", "SIM", "RUF"]
|