Bagel (Extelligence-ai/bagel): plain-English queries over robotics logs via MCP
Query robotics, drone, and IoT data in plain English through an MCP server, with an intelligent edge data reduction pipeline that keeps only the data that matters.
At a glance
- What is it?
- Bagel is an Apache-2.0 Python MCP server that turns plain-English questions about ROS, PX4, ArduPilot, Betaflight and IoT data into DuckDB SQL, and adds an edge reduction pipeline that keeps only the windows that matter. The design keeps the LLM out of the math, but the install path is Docker-first and the MCP endpoint is unauthenticated by design.
- Who is it for?
- Adopt Bagel if you already have Docker and an MCP client such as Claude Code, and you want auditable SQL over MCAP or ULog files instead of manual rosbag scripting. Skip it if you need a stable Python 3.13 environment, since pyproject.toml caps requires-python at >=3.10,<3.13, or if you cannot put an authenticated proxy in front of the MCP port, because compose.yaml binds it to 127.0.0.1 and SECURITY.md notes the endpoint is unauthenticated by design.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap Bagel targets: logs you can query, not logs you read
Robotics and drone logs are large, binary, and awkward to interrogate. A PX4 ULog or an MCAP bag holds thousands of messages across dozens of topics, and the usual workflow is to write a one-off Python script or click through a viewer. Bagel's premise is that the question you actually have ("is my IMU sensor overheating?") should be answerable in plain English, while the arithmetic underneath stays deterministic. The README states that every calculation over your message data is DuckDB SQL, not model guesswork, and that Bagel shows you the query so you can audit it. That separation is the whole point: the LLM translates intent into a query, and DuckDB executes it. The project is aimed at robotics, drone and IoT engineers who already know what they want to measure but do not want to hand-write the extraction layer for each log format.
How the MCP server, DuckDB and the reduction pipeline fit together
The architecture has three visible layers. First, format adapters: pyproject.toml lists optional dependency groups for px4 (pyulog, GitPython), ardupilot (pymavlink), betaflight (orangebox), ros1 (roslibpy, rospkg), ros2 (roslibpy) and a cv group with torch and transformers. Second, a query layer built on duckdb, pyarrow and pandas, with mcap, mcap-ros1-support and mcap-ros2-support for message decoding. Third, the MCP surface itself, served over SSE by server.py and run.py, with the mcp package pinned to >=1.11.0,<2.0.0 and a compatibility shim at src/mcp_compat.py. The README describes the reduction pipeline in natural language: you describe an event, and Bagel runs detection on the robot, keeping the windows that matter and dropping the rest. The example given is "Keep 10s around every hard brake, drop the rest", which the docs say becomes an auditable pipeline that is previewed before a byte is written, then run once, across a fleet, or standing at the edge. The pipelines/ directory in the repository layout is where those definitions live.
Installing Bagel and running your first query
Bagel is distributed as Docker images rather than as a pip package you install directly, and the README's quickstart assumes Docker Desktop plus an MCP-enabled LLM. The fastest path needs neither an MCP client nor a config file. This command pulls the PX4 image and runs the bundled demo against a sample flight log:
docker run -it --rm ghcr.io/extelligence-ai/bagel/px4:latest demoThe README shows the expected output as a robot-health report card: a header line reading `sample.ulg - 41.5s, 2018 messages, 77 topics`, followed by per-check rows for Power, IMU, GPS and Data gaps, each marked with a status symbol. The ROS2 images run the same `demo` subcommand against a lighter bundled sample, and `demo /path/to/log` points at your own file once it is mounted with `-v`.
To wire up the MCP server, clone the repository and start the service matching your environment. The compose.yaml file defines services including ros2-kilted, ros2-jazzy, ros2-iron, ros2-humble, ros1-noetic, px4, ardupilot, betaflight and iot:
git clone https://github.com/Extelligence-ai/bagel.git && cd bagel
docker compose run --service-ports ros2-kiltedWait for `INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)`, then register the endpoint with Claude Code from a second terminal:
claude mcp add --transport sse bagel http://localhost:8000/sseAfter that, `claude` opens a session and a prompt such as "Summarize the metadata of the ROS2 bag ./data/sample/ros2/mcap" is the first real use. The README also documents a fully offline variant using Ollama and ollmcp:
brew install ollama && ollama serve &
ollama pull qwen3:8b
uvx ollmcp --mcp-server-url http://localhost:8000/sse --model qwen3:8bIf port 8000 is taken, the README says to set MCP_SERVER_PORT, for example `MCP_SERVER_PORT=8100 docker compose run --service-ports ros2-kilted`, and use that port in the `claude mcp add` command. To give the container access to your own logs, the README instructs you to edit compose.yaml and uncomment the volumes section under the chosen service.
The security default you inherit from compose.yaml
The MCP endpoint is unauthenticated by design, and the repository is explicit about it. In compose.yaml, the port mapping is written as `127.0.0.1:${MCP_SERVER_PORT}:${MCP_SERVER_PORT}`, with a comment explaining that publishing to 0.0.0.0 would expose the endpoint to the LAN and bypass host firewalls. The container itself sets MCP_SERVER_HOST to 0.0.0.0 so Docker port publishing works, but the host-side mapping keeps it on loopback. SECURITY.md is cited for the reasoning, and the comment references issue #158 for the deliberate-sharing path: drop the 127.0.0.1 prefix and put an authenticated proxy in front. For a single developer on a laptop this is a sensible default. For a team that wants a shared Bagel instance, it means the proxy is your responsibility, and nothing in the quickstart sets one up.
Where Bagel is the wrong tool
Two constraints stand out. The first is the Python version ceiling: pyproject.toml declares `requires-python = ">=3.10,<3.13"`, so a host running Python 3.13 cannot install the package directly, even though the README's Python badge advertises 3.10+. The Docker images sidestep this, which is presumably why the quickstart is container-first rather than a pip install. The second is the MCP dependency pin. The comment above `mcp >=1.11.0,<2.0.0` says v2 readiness is handled through src/mcp_compat.py and was verified against 2.0.0b1, with the ceiling to be raised once v2 stable is validated end to end. Until that happens, projects already standardized on a newer MCP SDK may find Bagel lagging. Beyond versioning, Bagel is an analysis and reduction tool. The README is direct that the LLM stays in front of your logs and never in your robot's control loop, so it is not a telemetry transport, not a real-time control component, and not a substitute for your flight controller's own logging. If your need is live command and control, this is the wrong layer.
Bagel compared with Foxglove and PlotJuggler
The most natural alternative for robotics log work is Foxglove Studio, with PlotJuggler as the plotting-focused option. Both are interactive visual tools: you open a bag or a live connection, build panels, and inspect signals by hand. Bagel takes the opposite route. There is no panel layout and no live visualization in the quickstart; instead you ask a question in English and get back a DuckDB query plus its result, which you can then re-run or embed. The compose.yaml comment even positions Bagel as complementary, noting that artifacts land on the host under ~/.bagel/artifacts so that desktop tools like PlotJuggler can open them directly. That is the honest framing: Bagel is the query and reduction step, and a viewer remains useful once the reduced bag exists. If your workflow is exploratory and visual, a viewer is faster. If your workflow is repetitive (the same check across many logs, or a pipeline that must run on the robot), the SQL-plus-pipeline model is the differentiator.
Maintenance, licensing and upgrade cost
The repository is not archived, and the last push was on 2026-09-15. Recent releases on the main branch include v2.2.0 (2026-08-19), v2.1.1 (2026-08-19) and v2.1.0 (2026-08-18), with pyproject.toml at version 2.2.3. That is a fast release cadence, and the version ceilings in the dependency list (duckdb <2.0.0, pandas <3.0.0, protobuf <7.0.0, pyarrow <19.0.0) suggest the maintainers pin aggressively and raise ceilings deliberately. The practical upgrade cost is mostly Docker image tags: compose.yaml references `ghcr.io/extelligence-ai/bagel/<service>:latest`, so pulling a new image is the upgrade. If you want reproducibility, pin the image by digest instead of using latest. The licence is Apache-2.0, which permits commercial use and modification and includes a patent grant; this is a description of the licence file, not legal advice. One licensing-adjacent detail worth noting for anyone extending the tool: the README mentions user-authored capabilities in .poml or .md form, discovered by list_agent_capabilities and written by save_agent_capability, and mounted from ~/.bagel/capabilities. Those files are yours, and Apache-2.0 places no copyleft obligation on them.
Editorial conclusion
Adopt Bagel if you already have Docker and an MCP client such as Claude Code, and you want auditable SQL over MCAP or ULog files instead of manual rosbag scripting. Skip it if you need a stable Python 3.13 environment, since pyproject.toml caps requires-python at >=3.10,<3.13, or if you cannot put an authenticated proxy in front of the MCP port, because compose.yaml binds it to 127.0.0.1 and SECURITY.md notes the endpoint is unauthenticated by design. Before rolling it out, verify that your log format has a matching compose service and that the reduced artifacts land where you expect under ~/.bagel/artifacts.
Frequently asked questions
How do I install Bagel AI?
The README's quickstart installs Docker Desktop and an MCP-enabled LLM, clones the repository, and starts a compose service such as ros2-kilted. A pip install is not the documented path, and pyproject.toml caps requires-python at >=3.10,<3.13.
How do I use Bagel with my own log file?
The README says the demo subcommand accepts a path, so `demo /path/to/log` works after mounting the file with -v. For the MCP workflow, edit compose.yaml and uncomment the volumes section under your chosen service so the container can see your data.
Does Bagel send my robotics data to an LLM provider?
The README offers a fully offline path using Ollama and ollmcp with a local model such as qwen3:8b, so your data and your LLM stay on the machine. The default quickstart, by contrast, connects an MCP client such as Claude Code to the local SSE endpoint.
Which log formats does Bagel support?
compose.yaml defines services for ROS2 Kilted, Jazzy, Iron and Humble, ROS1 Noetic, PX4, ArduPilot, Betaflight and IoT/MQTT. pyproject.toml backs those with optional dependency groups including pyulog, pymavlink, orangebox and roslibpy.
Community notes