[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://bebop-2.warehack.ing" Repository = "https://git.supported.systems/warehack.ing/mcbebop" Issues = "https://git.supported.systems/warehack.ing/mcbebop/issues" [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"]