Skip to main content

MCP server for GNU Radio — build, validate, run, and export flowgraphs programmatically.

Project description

GR-MCP: GNU Radio MCP Server

Python Version License: MIT

GR-MCP is a FastMCP server for GNU Radio that enables programmatic, automated, and AI-driven creation of GNU Radio flowgraphs. It exposes 80+ MCP tools for building, validating, running, and exporting .grc files — plus block development, protocol analysis, and OOT module management.

What can you do with it?

  • Build and validate flowgraphs programmatically
  • Generate custom GNU Radio blocks from natural language descriptions
  • Parse protocol specifications into decoder pipelines
  • Analyze IQ recordings to detect signal characteristics
  • Export blocks to distributable OOT modules
  • Run flowgraphs in Docker containers with real-time variable control
  • Install and manage OOT modules via Docker

Quickstart

1. Install

git clone https://github.com/rsp2k/gr-mcp
cd gr-mcp

# Create venv with system site-packages (required for gnuradio)
uv venv --system-site-packages --python 3.14
uv sync

2. Run

uv run gnuradio-mcp

3. Add to your MCP client

Claude Code:

claude mcp add gnuradio-mcp -- uv run --directory /path/to/gr-mcp gnuradio-mcp

Claude Desktop / Cursor / other MCP clients:

{
  "mcpServers": {
    "gnuradio-mcp": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/gr-mcp", "gnuradio-mcp"]
    }
  }
}

Requirements

  • Python >= 3.14
  • GNU Radio (tested with GRC v3.10.12.0)
  • Docker (optional — for runtime control, block testing, OOT builds)
  • uv package manager

Note: GR-MCP is designed for single-session use. All connected MCP clients share the same flowgraph state. Run one server instance per concurrent session.

Features

Flowgraph Building (30 tools)

Build, edit, validate, and export .grc files:

Category Tools
Blocks make_block, remove_block, get_blocks
Parameters get_block_params, set_block_params
Ports get_block_sources, get_block_sinks
Connections connect_blocks, disconnect_blocks, get_connections
Validation validate_block, validate_flowgraph, get_all_errors
Persistence save_flowgraph, load_flowgraph
Code Gen generate_code
Discovery get_all_available_blocks, search_blocks, get_block_categories
Options get_flowgraph_options, set_flowgraph_options
Python create_embedded_python_block, evaluate_expression
Bypass bypass_block, unbypass_block
Import/Export export_flowgraph_data, import_flowgraph_data
OOT Paths load_oot_blocks, add_block_path, get_block_paths

Block Development (18 tools, dynamically registered)

Generate, validate, test, and export custom blocks. These tools are registered on-demand via enable_block_dev_mode to minimize context usage:

Category Tools
Generation generate_sync_block, generate_basic_block, generate_interp_block, generate_decim_block
Validation validate_block_code, parse_block_prompt
Testing test_block_in_docker
Integration inject_generated_block
Protocol parse_protocol_spec, generate_decoder_chain, get_missing_oot_modules
Signal analyze_iq_file
OOT Export generate_oot_skeleton, export_block_to_oot, export_from_flowgraph
Mode enable_block_dev_mode, disable_block_dev_mode, get_block_dev_mode

Runtime Control (36 tools)

Run flowgraphs in Docker containers with real-time control:

Category Tools
XML-RPC connect, disconnect, get_status, list_variables, get_variable, set_variable
Execution start, stop, lock, unlock
ControlPort connect_controlport, disconnect_controlport, get_knobs, set_knobs, get_knob_properties, get_performance_counters, post_message
Docker launch_flowgraph, list_containers, stop_flowgraph, remove_flowgraph, connect_to_container, capture_screenshot, get_container_logs
Coverage collect_coverage, generate_coverage_report, combine_coverage, delete_coverage
OOT Mgmt detect_oot_modules, install_oot_module, list_oot_images, remove_oot_image, build_multi_oot_image, list_combo_images, remove_combo_image

MCP Resources

Resource URI Description
oot://directory Curated directory of 20 OOT modules (12 preinstalled)
oot://directory/{module} Details for a specific OOT module
prompts://block-generation/* Block generation patterns and templates
prompts://protocol-analysis/* Decoder pipeline guidance

Usage Examples

Building a flowgraph

# Create blocks
make_block(block_type="analog_sig_source_x", name="sig_source")
make_block(block_type="audio_sink", name="speaker")

# Configure
set_block_params(block_name="sig_source", params={
    "freq": "1000",
    "amplitude": "0.5",
    "waveform": "analog.GR_COS_WAVE"
})

# Wire and save
connect_blocks(
    source_block="sig_source", source_port="0",
    sink_block="speaker", sink_port="0"
)
validate_flowgraph()
save_flowgraph(path="/tmp/my_flowgraph.grc")

Generating a custom block

enable_block_dev_mode()

generate_sync_block(
    name="pm_demod",
    description="Phase modulation demodulator",
    inputs=[{"dtype": "complex", "vlen": 1}],
    outputs=[{"dtype": "float", "vlen": 1}],
    parameters=[{"name": "sensitivity", "dtype": "float", "default": 1.0}],
    work_logic="Extract instantaneous phase from complex samples"
)

Protocol analysis to decoder chain

enable_block_dev_mode()

# Parse a protocol spec
protocol = parse_protocol_spec(
    "GFSK at 250k baud, deviation: 25khz, preamble 0xAA, sync 0x2DD4"
)

# Generate the decoder pipeline
chain = generate_decoder_chain(protocol=protocol, sample_rate=2000000.0)
# Returns: blocks, connections, variables, missing_oot_modules

Exporting to an OOT module

enable_block_dev_mode()

# Generate block
block = generate_sync_block(name="my_filter", ...)

# Export to distributable OOT module
export_block_to_oot(
    generated=block,
    module_name="mymodule",
    output_dir="/path/to/gr-mymodule",
    author="Your Name"
)
# Creates: CMakeLists.txt, python/mymodule/my_filter.py, grc/mymodule_my_filter.block.yml

Runtime control (Docker)

# Launch flowgraph in container
launch_flowgraph(
    flowgraph_path="/path/to/flowgraph.py",
    name="my-sdr",
    xmlrpc_port=8080,
    enable_vnc=True
)

# Tune in real-time
connect_to_container(name="my-sdr")
set_variable(name="freq", value=2.4e9)

# Inspect and clean up
capture_screenshot(name="my-sdr")
stop_flowgraph(name="my-sdr")

Architecture

src/gnuradio_mcp/
├── server.py                    # FastMCP app entry point
├── models.py                    # Pydantic models for all tools
├── utils.py                     # Unique IDs, error formatting
├── oot_catalog.py               # Curated OOT module directory
├── middlewares/
│   ├── platform.py              # GNU Radio Platform wrapper
│   ├── flowgraph.py             # Block/connection management
│   ├── block.py                 # Parameter/port access
│   ├── ports.py                 # Port resolution utilities
│   ├── docker.py                # Docker container lifecycle
│   ├── xmlrpc.py                # XML-RPC variable control
│   ├── thrift.py                # ControlPort/Thrift client
│   ├── oot.py                   # OOT module Docker builds
│   ├── block_generator.py       # Code generation for custom blocks
│   ├── oot_exporter.py          # Export blocks to OOT modules
│   └── protocol_analyzer.py     # Protocol parsing, decoder chains, IQ analysis
└── providers/
    ├── base.py                  # PlatformProvider (flowgraph tools)
    ├── mcp.py                   # McpPlatformProvider (registers tools)
    ├── runtime.py               # RuntimeProvider (Docker/XML-RPC/Thrift)
    ├── mcp_runtime.py           # McpRuntimeProvider (registers tools)
    ├── block_dev.py             # BlockDevProvider (generation/analysis)
    └── mcp_block_dev.py         # McpBlockDevProvider (dynamic registration)

Data flow: GNU Radio objects → Middlewares (validation/rewrite) → Pydantic Models (serialization) → MCP Tools

Development

# Install all dependencies
uv sync --all-extras

# Run tests
pytest

# Run specific test suite
pytest tests/unit/
pytest tests/integration/

# Pre-commit hooks (black, flake8, isort, mypy)
pre-commit run --all-files

Docker Images (Optional)

For runtime control and block testing:

# Runtime image (Xvfb + VNC + ImageMagick)
docker build -f docker/Dockerfile.gnuradio-runtime -t gnuradio-runtime:latest docker/

# Coverage image (adds python3-coverage)
docker build -f docker/Dockerfile.gnuradio-coverage -t gnuradio-coverage:latest docker/

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gnuradio_mcp-0.2.0.tar.gz (91.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gnuradio_mcp-0.2.0-py3-none-any.whl (101.6 kB view details)

Uploaded Python 3

File details

Details for the file gnuradio_mcp-0.2.0.tar.gz.

File metadata

  • Download URL: gnuradio_mcp-0.2.0.tar.gz
  • Upload date:
  • Size: 91.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for gnuradio_mcp-0.2.0.tar.gz
Algorithm Hash digest
SHA256 86821918a5f09468adeb8d36a91dadf7d0fe89bab9fb62747313a1a2af17a2c3
MD5 6ae509d6914f495fb9cebbcecdb13a5e
BLAKE2b-256 5eca6ee2bc5e6bcb394f3b33a29859f09e3fd902307e7f07d3da3f918984fe09

See more details on using hashes here.

File details

Details for the file gnuradio_mcp-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: gnuradio_mcp-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 101.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"EndeavourOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for gnuradio_mcp-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ac4f6d6a53f26bc630b20b27c086b59405d342dbe1b1c7e5a46cdcf67f94d777
MD5 90e63b35fbd2f83a88853491aaca4e1c
BLAKE2b-256 4806a9a5c1f7e230fd4295a48ce484748d90a4731add0cbc8027a6c01f1cfec6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page