Bagel MCP Server
io.github.Extelligence-ai/bagel
Plain-English analysis of robotics, drone, and IoT data with intelligent edge data reduction.
What is the Bagel MCP server?
The Bagel MCP server lets you ask questions about robotics, drone, and IoT data in plain English, with every calculation backed by deterministic DuckDB SQL queries you can audit. It supports ROS1/ROS2, PX4, ArduPilot, Betaflight, MQTT, PostgreSQL, InfluxDB, and automotive formats, and includes an intelligent edge data reduction pipeline that detects events and keeps only the data windows that matter.
Bagel bridges the gap between natural language and robotics data analysis. Instead of writing SQL or bash scripts, you ask questions like "Is my IMU sensor overheating?" or "Find every deceleration under −10 m/s² and cut ±30 s snippets." The server translates these into transparent, auditable SQL queries and can run event detection on edge devices to reduce data transmission by keeping only relevant windows.
How to install Bagel
Copy-paste configuration for popular MCP clients.
{
"mcpServers": {
"bagel": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/extelligence-ai/bagel/ros2-kilted:2.1.1"
]
}
}
}{
"mcpServers": {
"bagel": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/extelligence-ai/bagel/ros2-kilted:2.1.1"
]
}
}
}{
"mcpServers": {
"bagel": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/extelligence-ai/bagel/ros2-kilted:2.1.1"
]
}
}
}{
"servers": {
"bagel": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/extelligence-ai/bagel/ros2-kilted:2.1.1"
]
}
}
}claude mcp add bagel -- docker run -i --rm ghcr.io/extelligence-ai/bagel/ros2-kilted:2.1.1Tools & capabilities
Tools this server exposes to the agent.
Plain-language data queries— Ask questions about robotics, drone, and IoT data in English; Bagel generates and executes DuckDB SQL queries with full transparency.Edge data reduction pipelines— Define event detection rules in natural language; Bagel runs detection on the robot and keeps only data windows around real events, dropping the rest.Multi-format support— Analyze ROS1, ROS2, MCAP, PX4, ArduPilot, Betaflight, MQTT, PostgreSQL, InfluxDB, ASAM MDF4, and CAN captures with the same interface.POML capability extension— Teach Bagel new tricks by writing POML files that describe structured analysis tasks.Fleet batch processing— Run pipelines across multiple bags or robots and generate combined reports.Integration exports— Export results to PlotJuggler, Rerun, Lichtblick/Foxglove, Slack, and LeRobot formats.
Use cases
- Summarize metadata and find anomalies in robotics bags without writing scripts
- Detect specific events (hard braking, sensor overheating, deceleration) and extract ±N second windows for detailed analysis
- Reduce multi-gigabyte flight logs to megabytes by keeping only event windows, then upload to cloud storage
- Correlate signals across topics (e.g., current vs. voltage) using SQL joins instead of manual spreadsheet work
- Monitor live MQTT or PostgreSQL IoT data streams and trigger edge pipelines when conditions are met
- Inspect ROS text logs (~/.ros/log) for errors and warnings without opening a bag file
Bagel MCP server FAQ
Bagel is an MCP server that lets you analyze robotics, drone, and IoT data by asking questions in plain English. It translates your questions into deterministic DuckDB SQL queries, shows you the query for auditing, and supports ROS1/ROS2, PX4, ArduPilot, Betaflight, MQTT, PostgreSQL, InfluxDB, and automotive formats.
Yes, Bagel is open-source under the Apache 2.0 license.
Clone the repo, run `docker compose run --service-ports ros2-kilted` (or your data format), then in a new terminal run `claude mcp add --transport sse bagel http://localhost:8000/sse`. Then start Claude Code and you can chat with your data.
Robotics: ROS1, ROS2, MCAP, ROS text logs. Drones: PX4, ArduPilot, Betaflight. Automotive: ASAM MDF4, CAN (BLF/ASC + DBC). IoT: MQTT (live, Sparkplug B), PostgreSQL, TimescaleDB, InfluxDB 3. Hardware: WaffleForm snapshots.
No. The MCP endpoint binds to localhost only for security. You can run fully offline with a local LLM (e.g., Ollama) so your data and model never leave your machine.
Yes, Bagel works with any MCP-enabled LLM: Gemini CLI, Codex, Cursor, Copilot, and fully local models via Ollama.
README (reference)
Source of truth, from the repository.
Bagel lets you ask questions about robotics, drone, and IoT data in plain English. Every calculation over your message data is DuckDB SQL, not model guesswork, and Bagel shows you the query so you can audit it.
Is my IMU sensor overheating?
Bagel also has an intelligent edge data reduction pipeline: describe an event and Bagel runs the detection on the robot, keeping the windows that matter and dropping the rest. An MCP server puts all of it in your LLM's hands: Claude Code, Gemini, Cursor, or a fully local model.
Bagel was the first MCP server to ship a real analysis toolkit for robotics data, and it keeps the LLM where it belongs: in front of your logs, never in your robot's control loop.
🥯 Key Features
- Ask in plain language: No deep domain expertise needed.
- Transparent calculations: Deterministic SQL queries. No black-box LLM math.
- Natural-language pipelines: "Keep 10s around every hard brake, drop the rest": one sentence becomes an auditable pipeline: previewed before a byte is written, then run once, across a fleet, or standing at the edge.
- Broad LLM support: Claude Code, Gemini, Cursor, Codex, and more.
- Dockerized environments: No local dependencies required.
- Extensible capabilities: Bagel can learn new tricks.
- Wide format coverage: Missing your data format? Open a ticket.
⚡️ Quickstart
[!TIP] Already have Claude Code? Just paste the link to this repo and tell Claude what environment you want:
Set up https://github.com/Extelligence-ai/bagel for ROS2 Kilted.
Claude will clone the repo, start Docker, and wire up the MCP connection for you.
📋 Prerequisites
Install Docker Desktop and Claude Code (or another MCP-enabled LLM).
1. Clone and start Bagel
git clone https://github.com/Extelligence-ai/bagel.git && cd bagel
docker compose run --service-ports ros2-kilted
[!TIP] Port 8000 already in use? Set
MCP_SERVER_PORTto something else, for exampleMCP_SERVER_PORT=8100 docker compose run --service-ports ros2-kilted, and use that port in step 2.
Pick the service that matches your environment:
| Service | Use case |
|---|---|
ros2-kilted | ROS2 Kilted (latest) |
ros2-jazzy | ROS2 Jazzy |
ros2-iron | ROS2 Iron |
ros2-humble | ROS2 Humble |
ros1-noetic | ROS1 Noetic |
ros1-noetic-cv | ROS1 Noetic + CV |
px4 | PX4 flight logs |
ardupilot | ArduPilot flight logs |
betaflight | Betaflight flight logs |
iot | IoT / MQTT (live) |
[!TIP] To give Bagel access to your local files, edit
compose.yamlbefore starting Docker: uncomment and update thevolumessection under your chosen service.
Wait for this output:
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
2. Connect Claude Code
In a new terminal:
claude mcp add --transport sse bagel http://localhost:8000/sse
[!NOTE] The MCP endpoint is bound to
localhostonly (not exposed to the LAN) for security. To share it with other machines, drop the127.0.0.1prefix incompose.yamland put an authenticated proxy in front: see SECURITY.md.
3. Prompt
claude
Summarize the metadata of the ROS2 bag "./data/sample/ros2/mcap".
That’s it: you’re chatting with your data.
🔒 Prefer fully offline?
Swap step 2 for a local model: your data and your LLM stay on the machine:
brew install ollama && ollama serve & # or ollama.com
ollama pull qwen3:8b
uvx ollmcp --mcp-server-url http://localhost:8000/sse --model qwen3:8b
Model picks, expectations, and troubleshooting: Local LLMs guide.
<details> <summary>📚 Using a different LLM?</summary>Bagel works with any MCP-enabled LLM. Setup runbooks for tested alternatives:
- Claude Code (detailed guide)
- Gemini CLI
- Codex
- Cursor
- Copilot
Can’t find your LLM? Open a ticket.
</details>🔌 Agent plugins (Claude Code and Codex)
Bagel ships an agent plugin: four skills that teach the agent when and how
to drive the server (log triage, pipeline authoring, live sinks, visualization
export) plus the MCP connection, wired automatically. The same plugin/
directory serves both Claude Code and OpenAI Codex.
/plugin marketplace add Extelligence-ai/bagel
/plugin install bagel@bagel
Codex users: clone the repo and add it as a plugin marketplace (the repo
carries .agents/plugins/marketplace.json), then install bagel from
/plugins in Codex.
Then start the container for your data format (see Quickstart): the plugin
connects to http://localhost:8000/sse by default. Any other MCP client can
discover the same workflows server-side via the list_agent_capabilities tool.
Keep what matters, drop the rest
A robot records more data than you can afford to move. Bagel turns a question into a detector, runs it where the data is recorded, and ships only the windows around real events.
<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="./doc/assets/edge_reduce_dark_mode.svg"> <img src="./doc/assets/edge_reduce_light_mode.svg" width="80%"> </picture> </p>Here it is in one conversation:
<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="./doc/assets/nl_reduction_dark_mode.gif"> <img src="./doc/assets/nl_reduction_light_mode.gif" width="80%"> </picture> </p>The session above: a 20-minute (1,200 s) recording and the prompt "keep 10 seconds before and after every deceleration harder than −10 m/s²". The preview detects 7 events, merges them into 4 windows, and keeps 92 s of the 1,200 (7.6%); the run writes a 2.1 GB bag down to 161 MB. These figures are illustrative demo output, not a measured benchmark: the ratio is event-window duration over total duration, so it depends entirely on your workload.
✅ Supported Data Formats
| Industry | Formats |
|---|---|
| Robotics | ROS1, ROS2, MCAP (any profile), Copper (via MCAP export), ROS text logs (~/.ros/log) |
| Drones | PX4, ArduPilot, Betaflight |
| Automotive | ASAM MDF4 (.mf4), CAN captures (.blf/.asc + DBC) · beta |
| IoT | MQTT (live, Sparkplug B), PostgreSQL / TimescaleDB, InfluxDB 3 |
| Hardware state | WaffleForm snapshots (.waffleform.yaml), auto-detected via waffle-iron · beta |
🆚 Bagel vs. the Tools You Already Use
You already have ros2 *, PlotJuggler, and grep. Bagel doesn't replace them: it
answers the questions they make you work for, then hands off to them:
| You do this today | Ask Bagel instead |
|---|---|
ros2 bag info for metadata | "Summarize this bag": same prompt works on PX4, ArduPilot, MCAP, MQTT, Postgres |
ros2 topic echo /imu and eyeball raw values | "What's the peak z-deceleration in /imu? Running average over 5 s?" · real SQL underneath: peaks, running averages, percentiles, cross-topic correlations |
| Scrub PlotJuggler timelines hunting for the event | "Find every deceleration under −10 m/s² and cut ±30 s snippets": then open the result in PlotJuggler with a pre-framed layout |
rqt_console, or grep ~/.ros/log | "Read the ERRORs from ~/.ros/log and tell me what went wrong": tracebacks included, no bag needed |
| Echo two topics in two terminals, correlate in a spreadsheet | "What's the correlation between current and voltage?": topics live in one SQL relation, so joins and corr() are one question |
ros2 bag record -a and babysit the disk | A standing edge pipeline: record continuously, keep only event windows, drop the rest |
| A bash loop over 200 bags | "Run this pipeline on every bag in the folder": one pipeline, whole fleet, with a combined report |
scp/aws s3 sync scripts to ship data off the robot | Upload to S3, GCS, or Azure as a pipeline step, checksum-skipping files already there |
| A different viewer per format: FlightPlot for PX4, MAVExplorer for ArduPilot, Blackbox Explorer for Betaflight | The same conversation for all of them, and ROS, MCAP, MQTT, Postgres, InfluxDB |
| Write a one-off pandas script per question | Ask the question; Bagel writes and runs the query |
One sentence of plain language, one answer, instead of a pipeline of commands and a script you'll delete tomorrow.
💬 What Can I Prompt?
You can ask Bagel almost anything. For example:
What’s the correlation between current and voltage in the
/spot/status/battery_statestopic?
I think the robot hit a pothole. Can you check for sudden deceleration on the z-axis to confirm?
Every time the drone decelerates harder than -10 m/s², keep 10 seconds before and after. Drop everything else.
Did anything change on this robot since last week?
Time to put Bagel to the test: can it catch a drone doing barrel rolls? Spoiler: 🎉 It totally can.
<p align="center"> <picture> <img src="./doc/assets/drone_rolls.gif" width="80%"> </picture> </p>💡 How Bagel Works
When you ask a question, Bagel analyzes your data source’s metadata and topics to build a high-level understanding.
<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="./doc/assets/high_level_dark_mode.png"> <img src="./doc/assets/high_level_light_mode.png" width="80%"> </picture> </p>Based on your prompt, if further inspection is needed, Bagel identifies the most relevant topics and interprets their meaning and structure. Bagel then writes the relevant topic messages to an Apache Arrow file and uses DuckDB to generate and execute queries against it.
<p align="center"> <picture> <source media="(prefers-color-scheme: dark)" srcset="./doc/assets/llm_math_dark_mode.png"> <img src="./doc/assets/llm_math_light_mode.png" width="80%"> </picture> </p>This process is repeated as needed, running new queries until Bagel finds the best answer to your question.
LLMs excel at language but struggle with math. Bagel overcomes this by generating deterministic DuckDB SQL queries. These queries are displayed for you to audit, and you can guide Bagel to correct any errors.
🐶 Teach Bagel a New Trick
Bagel learns new capabilities through POML files: a structured set of instructions that describe a “trick,” such as computing latency statistics.
✍️ Create a .poml file
For example, let’s define ./src/agent/examples/woof.poml.
<poml>
<task>
Count the topics in the data source.
If the count is odd, say "woof", else say "meow".
</task>
<output-format>
Return the sound, the topic count, and a few cute emojis. Nothing else.
</output-format>
</poml>
🗣️ Use the capability
Prompt Bagel:
Run the POML capability "./src/agent/examples/woof.poml" on the ROS2 bag "./data/sample/ros2/mcap".
Result:
meow 🐱 4 topics 🐱💤🎯
📚 Guides
- Natural-language pipelines · the model: a cadence, gates, and tasks; preview → run → save → batch → standing at the edge
- Event-driven data reduction · detect events, keep windows around them (snippets or one reduced bag), batch across fleets, upload to the cloud
- Live ROS2 robots over rosbridge · a step-by-step tutorial
- ROS text logs · inspect
~/.ros/logerrors and warnings without opening a bag - MQTT · live IoT topics, Sparkplug B, edge recording
- PostgreSQL / TimescaleDB · every table is a topic
- InfluxDB 3 · every measurement is a topic
- Automotive MDF4 & CAN (beta) · channel groups and DBC messages are topics; units ride along
- Local LLMs · fully offline with Ollama: your data and your model never leave the machine
📦 Integrations
- Rerun · "show me that event in Rerun": any time window as a ready-to-open recording
- Lichtblick / Foxglove · event windows as MCAP + pre-framed layouts for either viewer
- PlotJuggler · open Bagel's MCAP outputs directly; one-sentence pre-framed sessions, flattened CSV/Parquet exports
- Cloudini · decode cloudini-compressed pointclouds, or compress a bag's PointCloud2 topics into CompressedPointCloud2
- Slack · pipelines post to your ops channel when they fire: "🚨 hard brake on {asset}"
- LeRobot (beta) · detected events become training episodes: a LeRobotDataset v3.0
🚧 Limitations
Rough edges we know about, so you don't find them the hard way:
- Two formats are beta. The automotive MDF4/CAN readers are verified against
files we generate with the same libraries that read them (
asammdf,python-can); real CANape/INCA/Vector-produced captures haven't crossed our test bench yet. LeRobot exports load-test clean with the reallerobotpackage, but no policy has been trained from a Bagel export yet. - Reduction ratios are workload-dependent, and unbenchmarked. The ratio is event-window duration over total duration: quiet recordings reduce dramatically, eventful ones much less. The figures in this README are illustrative demo output, not a measured benchmark.
- No authentication on the MCP endpoint. By design it binds to localhost only; treat it like a database socket and see SECURITY.md before sharing it beyond your machine.
- Small local models struggle with multi-step pipelines. A 4-8B model handles tool selection and simple SQL; event-windowed reduction and multi-topic joins want a bigger model. See the Local LLMs guide.
- Live-database end-to-end tests run outside CI. The InfluxDB and Postgres suites' pure tests run in CI; their live end-to-end cases only execute against an instance you point them at. Everything else, including the ROS bag write paths, runs in CI.
🫶 Contributing
We’d love your help! The easiest way to support the project is by giving it a ⭐ on GitHub.
Other great ways to contribute:
- Request new features
- Report bugs
- Improve documentation
- Add new capabilities
Before contributing, please review the guidelines.
Join the conversation in our Discord server. We hang out there regularly.
📄 License
Bagel is open source under the Apache License 2.0.
Related MCP servers
Control a real Chrome browser to complete any task: fill forms, extract data, book flights.
World Monitor
Real-time global intelligence: markets, conflicts, country risk, energy, and infrastructure monitoring via 39 MCP tools.
Netdata
Real-time infrastructure monitoring with per-second metrics, ML-powered anomaly detection, and zero-configuration setup.
Trending hip-hop artist momentum scores across four cultural dimensions.
AI orchestration platform with 100+ agents, swarm coordination, and self-learning memory for enterprise development.
Scrapling MCP Server
Web scraping with stealth HTTP, real browsers, and Cloudflare bypass capabilities.