docs: add block dev tools, fix entry points, update architecture

- Replace main.py references with gnuradio-mcp entry point
- Add block-dev.mdx reference page (18 tools documented)
- Add block-development.mdx workflow guide
- Update architecture diagram with BlockDevProvider column
- Update dynamic-tools.mdx with three-group model
- Add block dev section to tools-overview.mdx
- Add OOT export workflow to oot-modules.mdx
- Update tool counts and MCP resource listings
This commit is contained in:
Ryan Malloy 2026-02-24 10:25:26 -07:00
parent ce785029f4
commit bbcf4e784c
8 changed files with 783 additions and 105 deletions

View File

@ -21,54 +21,48 @@ objects into clean, serializable models suitable for the MCP protocol.
┌─────────────────────────────────────────────────────────────────┐
│ FastMCP App │
(main.py) │
(server.py) │
└─────────────────────────────────────────────────────────────────┘
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────────────┐
│ McpPlatformProvider │ │ McpRuntimeProvider │
│ (29 tools) │ │ (5 always + ~40 dynamic) │
│ │ │ │
│ • get_blocks │ │ Always: │
│ • make_block │ │ • get_runtime_mode │
│ • connect_blocks │ │ • enable_runtime_mode │
│ • validate_flowgraph │ │ • disable_runtime_mode │
│ • generate_code │ │ • get_client_capabilities │
│ • ... │ │ • list_client_roots │
│ │ │ │
│ │ │ Dynamic (when enabled): │
│ │ │ • launch_flowgraph │
│ │ │ • connect_to_container │
│ │ │ • set_variable │
│ │ │ • ... │
└─────────────────────────┘ └─────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────────────┐
│ PlatformProvider │ │ RuntimeProvider │
│ (Business Logic) │ │ (Business Logic) │
└─────────────────────────┘ └─────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────────────┐
│ Middlewares │ │ Middlewares │
│ │ │ │
│ • PlatformMiddleware │ │ • DockerMiddleware │
│ • FlowGraphMiddleware │ │ • XmlRpcMiddleware │
│ • BlockMiddleware │ │ • ThriftMiddleware │
│ │ │ • OOTInstallerMiddleware │
└─────────────────────────┘ └─────────────────────────────────┘
│ │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────────────┐
│ GNU Radio Objects │ │ External Services │
│ │ │ │
│ • Platform │ │ • Docker daemon │
│ • FlowGraph │ │ • XML-RPC servers │
│ • Block │ │ • Thrift servers │
│ • Connections │ │ • Container processes │
└─────────────────────────┘ └─────────────────────────────────┘
▼ ▼ ▼
┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐
│ McpPlatformProvider │ │ McpBlockDevProvider │ │ McpRuntimeProvider │
│ (~30 tools, always) │ │ (~18 tools, dynamic) │ │ (~40 tools, dynamic) │
│ │ │ │ │ │
│ • get_blocks │ │ enable_block_dev_mode │ │ enable_runtime_mode │
│ • make_block │ │ generate_sync_block │ │ launch_flowgraph │
│ • connect_blocks │ │ validate_block_code │ │ connect_to_container │
│ • validate_flowgraph │ │ generate_grc_yaml │ │ set_variable │
│ • generate_code │ │ export_block_to_oot │ │ install_oot_module │
│ • ... │ │ ... │ │ ... │
└───────────────────────┘ └───────────────────────┘ └───────────────────────┘
│ │ │
▼ ▼ ▼
┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐
│ PlatformProvider │ │ BlockDevProvider │ │ RuntimeProvider │
│ (Business Logic) │ │ (Business Logic) │ │ (Business Logic) │
└───────────────────────┘ └───────────────────────┘ └───────────────────────┘
│ │ │
▼ ▼ ▼
┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐
│ Middlewares │ │ Middlewares │ │ Middlewares │
│ │ │ │ │ │
│ • PlatformMiddleware │ │ • BlockGenerator │ │ • DockerMiddleware │
│ • FlowGraphMiddleware │ │ • ProtocolAnalyzer │ │ • XmlRpcMiddleware │
│ • BlockMiddleware │ │ • OOTExporter │ │ • ThriftMiddleware │
│ │ │ │ │ • OOTInstaller │
└───────────────────────┘ └───────────────────────┘ └───────────────────────┘
│ │ │
▼ ▼ ▼
┌───────────────────────┐ ┌───────────────────────┐ ┌───────────────────────┐
│ GNU Radio Objects │ │ Code Generation │ │ External Services │
│ │ │ │ │ │
│ • Platform │ │ • AST validation │ │ • Docker daemon │
│ • FlowGraph │ │ • Prompt templates │ │ • XML-RPC servers │
│ • Block │ │ • GRC YAML templates │ │ • Thrift servers │
│ • Connections │ │ • OOT scaffolding │ │ • Container processes │
└───────────────────────┘ └───────────────────────┘ └───────────────────────┘
```
## Layer Responsibilities
@ -84,6 +78,7 @@ objects into clean, serializable models suitable for the MCP protocol.
Business logic that doesn't know about MCP:
- **PlatformProvider**: All flowgraph operations (create, edit, validate, save)
- **BlockDevProvider**: Block generation, protocol analysis, OOT export
- **RuntimeProvider**: All runtime operations (launch, connect, control)
### Middleware Layer
@ -93,6 +88,9 @@ Wraps external systems with validation and normalization:
- **PlatformMiddleware**: Wraps GNU Radio's `Platform` class
- **FlowGraphMiddleware**: Wraps `FlowGraph` with block/connection management
- **BlockMiddleware**: Wraps `Block` with parameter/port access
- **BlockGeneratorMiddleware**: Code generation and validation for custom blocks
- **ProtocolAnalyzerMiddleware**: Protocol parsing, decoder chain generation, IQ analysis
- **OOTExporterMiddleware**: OOT skeleton creation, block export, GRC YAML generation
- **DockerMiddleware**: Wraps Docker SDK operations
- **XmlRpcMiddleware**: Wraps XML-RPC client
- **ThriftMiddleware**: Wraps ControlPort Thrift client
@ -167,16 +165,26 @@ Return: True
## Dynamic Tool Registration
Runtime tools are registered dynamically to minimize context usage:
Both runtime and block dev tools are registered dynamically to minimize context usage:
```python
# At startup: only 5 mode control tools
get_runtime_mode() # Check status
enable_runtime_mode() # Register all runtime tools
# At startup: ~38 always-on tools (platform + mode control)
get_runtime_mode() # Check runtime status
enable_runtime_mode() # Register runtime tools
disable_runtime_mode() # Unregister runtime tools
get_block_dev_mode() # Check block dev status
enable_block_dev_mode() # Register block dev tools
disable_block_dev_mode() # Unregister block dev tools
get_client_capabilities() # Debug client info
list_client_roots() # Debug client roots
# After enable_block_dev_mode(): ~18 additional tools
generate_sync_block()
validate_block_code()
generate_grc_yaml()
export_block_to_oot()
# ...etc
# After enable_runtime_mode(): ~40 additional tools
launch_flowgraph()
connect_to_container()
@ -185,8 +193,9 @@ set_variable()
```
<Aside type="tip">
This design reduces the tool list from ~70 to ~35 when only doing flowgraph design,
saving context tokens in LLM applications.
This design reduces the tool list from ~90+ to ~38 when only doing flowgraph design,
saving context tokens in LLM applications. Block dev and runtime modes can be enabled
independently or together.
</Aside>
## Key Design Decisions
@ -218,20 +227,27 @@ With 70+ tools, this wastes significant context. Dynamic registration:
```
src/gnuradio_mcp/
├── models.py # All Pydantic models
├── utils.py # Helper functions
├── oot_catalog.py # OOT module catalog
├── server.py # FastMCP app entry point + Platform init
├── models.py # All Pydantic models
├── utils.py # Helper functions
├── oot_catalog.py # OOT module catalog
├── middlewares/
│ ├── platform.py # PlatformMiddleware
│ ├── flowgraph.py # FlowGraphMiddleware
│ ├── block.py # BlockMiddleware
│ ├── docker.py # DockerMiddleware
│ ├── xmlrpc.py # XmlRpcMiddleware
│ ├── thrift.py # ThriftMiddleware
│ └── oot.py # OOTInstallerMiddleware
│ ├── platform.py # PlatformMiddleware
│ ├── flowgraph.py # FlowGraphMiddleware
│ ├── block.py # BlockMiddleware
│ ├── block_generator.py # BlockGeneratorMiddleware
│ ├── protocol_analyzer.py # ProtocolAnalyzerMiddleware
│ ├── oot_exporter.py # OOTExporterMiddleware
│ ├── docker.py # DockerMiddleware
│ ├── xmlrpc.py # XmlRpcMiddleware
│ ├── thrift.py # ThriftMiddleware
│ └── oot.py # OOTInstallerMiddleware
├── prompts/ # LLM prompt templates for block generation
└── providers/
├── base.py # PlatformProvider
├── mcp.py # McpPlatformProvider
├── runtime.py # RuntimeProvider
└── mcp_runtime.py # McpRuntimeProvider
├── base.py # PlatformProvider
├── mcp.py # McpPlatformProvider
├── block_dev.py # BlockDevProvider
├── mcp_block_dev.py # McpBlockDevProvider
├── runtime.py # RuntimeProvider
└── mcp_runtime.py # McpRuntimeProvider
```

View File

@ -6,8 +6,9 @@ draft: false
import { Aside, Steps } from '@astrojs/starlight/components';
GR-MCP uses **dynamic tool registration** to minimize context usage. Runtime tools
are only registered when needed, keeping the tool list small during flowgraph design.
GR-MCP uses **dynamic tool registration** to minimize context usage. Runtime and block
development tools are only registered when needed, keeping the tool list small during
flowgraph design.
## The Problem
@ -22,9 +23,9 @@ For LLM applications, this is wasteful when you only need flowgraph design tools
## The Solution
GR-MCP splits tools into two groups:
GR-MCP splits tools into three groups:
### Always Available (34 tools)
### Always Available (~38 tools)
Platform tools for flowgraph design:
- `get_blocks`, `make_block`, `remove_block`
@ -32,16 +33,24 @@ Platform tools for flowgraph design:
- `validate_flowgraph`, `generate_code`
- etc.
Plus 5 runtime mode control tools:
- `get_runtime_mode`
- `enable_runtime_mode`
- `disable_runtime_mode`
- `get_client_capabilities`
- `list_client_roots`
Plus mode control tools (always registered):
- `get_runtime_mode`, `enable_runtime_mode`, `disable_runtime_mode`
- `get_block_dev_mode`, `enable_block_dev_mode`, `disable_block_dev_mode`
- `get_client_capabilities`, `list_client_roots`
### Dynamically Registered (~40 tools)
### Block Dev Tools (~18 tools)
Runtime tools loaded via `enable_runtime_mode()`:
Loaded via `enable_block_dev_mode()`:
- 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`
- Protocol: `parse_protocol_spec`, `generate_decoder_chain`
- Signal: `analyze_iq_file`
- Export: `generate_grc_yaml`, `generate_oot_skeleton`, `export_block_to_oot`
### Runtime Tools (~40 tools)
Loaded via `enable_runtime_mode()`:
- Container lifecycle: `launch_flowgraph`, `stop_flowgraph`
- XML-RPC: `connect`, `set_variable`, `get_variable`
- ControlPort: `connect_controlport`, `get_knobs`, `get_performance_counters`
@ -51,7 +60,7 @@ Runtime tools loaded via `enable_runtime_mode()`:
## Usage Pattern
<Steps>
1. **Flowgraph Design** (29 platform tools + 5 mode tools = 34 total)
1. **Flowgraph Design** (~38 always-on tools)
```python
make_block(block_type="osmosdr_source")
@ -60,27 +69,34 @@ Runtime tools loaded via `enable_runtime_mode()`:
generate_code(output_dir="/tmp")
```
2. **Enable Runtime** (adds ~40 tools = ~74 total)
2. **Enable Block Dev** (adds ~18 tools)
```python
enable_block_dev_mode()
# Generate blocks, analyze protocols, export to OOT
generate_sync_block(
name="my_gain", description="Multiply by gain",
input_signature=[{"dtype": "float", "vlen": 1}],
output_signature=[{"dtype": "float", "vlen": 1}],
)
generate_grc_yaml(source_code="...", block_name="my_gain")
```
3. **Enable Runtime** (adds ~40 more tools)
```python
enable_runtime_mode()
# Now runtime tools are available
```
3. **Runtime Control**
```python
launch_flowgraph(flowgraph_path="/tmp/fm.py")
connect_to_container(name="gr-fm")
set_variable(name="freq", value=101.1e6)
capture_screenshot()
```
4. **Disable Runtime** (back to 34 tools)
4. **Scale Down** (disable either group independently)
```python
disable_runtime_mode()
# Runtime tools removed, back to design mode
disable_runtime_mode() # Removes runtime tools
disable_block_dev_mode() # Removes block dev tools
```
</Steps>
@ -189,8 +205,9 @@ status = get_runtime_mode()
## Benefits
1. **Reduced Context** — ~35 tools instead of ~75 during design
1. **Reduced Context** — ~38 tools instead of ~90+ during design
2. **Faster Responses** — Less prompt processing for simple queries
3. **Clear Separation** — Design vs runtime is explicit
4. **Graceful Degradation** — Missing Docker doesn't break design tools
5. **Discovery** — `get_runtime_mode()` shows what's available
3. **Clear Separation** — Design, generation, and runtime are explicit phases
4. **Independent Modes** — Enable block dev and runtime separately or together
5. **Graceful Degradation** — Missing Docker doesn't break design or generation tools
6. **Discovery** — `get_runtime_mode()` and `get_block_dev_mode()` show what's available

View File

@ -85,7 +85,7 @@ sudo usermod -aG docker $USER
4. **Verify the installation**
```bash
uv run main.py
uv run gnuradio-mcp
```
You should see the FastMCP server start. Press `Ctrl+C` to stop.
@ -104,7 +104,7 @@ Edit `~/.config/claude/claude_desktop_config.json`:
"mcpServers": {
"gr-mcp": {
"command": "uv",
"args": ["--directory", "/path/to/gr-mcp", "run", "main.py"]
"args": ["--directory", "/path/to/gr-mcp", "run", "gnuradio-mcp"]
}
}
}
@ -112,7 +112,7 @@ Edit `~/.config/claude/claude_desktop_config.json`:
</TabItem>
<TabItem label="Claude Code">
```bash
claude mcp add gr-mcp -- uv --directory /path/to/gr-mcp run main.py
claude mcp add gr-mcp -- uv --directory /path/to/gr-mcp run gnuradio-mcp
```
Or add to your project's `.mcp.json`:
@ -122,7 +122,7 @@ Or add to your project's `.mcp.json`:
"mcpServers": {
"gr-mcp": {
"command": "uv",
"args": ["--directory", "/path/to/gr-mcp", "run", "main.py"]
"args": ["--directory", "/path/to/gr-mcp", "run", "gnuradio-mcp"]
}
}
}
@ -136,7 +136,7 @@ Edit your Cursor settings or `.cursor/mcp.json`:
"mcpServers": {
"gr-mcp": {
"command": "uv",
"args": ["--directory", "/path/to/gr-mcp", "run", "main.py"]
"args": ["--directory", "/path/to/gr-mcp", "run", "gnuradio-mcp"]
}
}
}

View File

@ -0,0 +1,229 @@
---
title: Block Development
description: Generate custom GNU Radio blocks and export to OOT modules
draft: false
---
import { Steps, Aside, Tabs, TabItem } from '@astrojs/starlight/components';
GR-MCP provides tools for generating custom GNU Radio blocks from descriptions,
testing them in isolation, and exporting them to full Out-of-Tree modules with
GRC integration.
## Enable Block Dev Mode
Block development tools are dynamically registered to keep the tool list lean:
```python
enable_block_dev_mode()
# Registers ~18 tools + 5 prompt resources
```
## Generate a Block
<Steps>
1. **Describe what you want**
```python
result = generate_sync_block(
name="configurable_gain",
description="Multiply input samples by a configurable gain factor",
input_signature=[{"dtype": "float", "vlen": 1}],
output_signature=[{"dtype": "float", "vlen": 1}],
parameters=[{
"name": "gain",
"dtype": "float",
"default": 1.0,
"description": "Gain factor"
}],
work_logic="Multiply each input sample by self.gain"
)
```
2. **Validate the generated code**
```python
validation = validate_block_code(source_code=result.source_code)
# Checks: ast.parse, imports, class hierarchy, work() signature
```
3. **Test in Docker** (optional)
```python
test = test_block_in_docker(
source_code=result.source_code,
test_input=[1.0, 2.0, 3.0],
parameters={"gain": 2.0}
)
# Expected output: [2.0, 4.0, 6.0]
```
</Steps>
## Block Types
Choose the right block type for your use case:
| Type | Tool | When to Use |
|------|------|-------------|
| `sync_block` | `generate_sync_block` | 1:1 input/output ratio (most common) |
| `basic_block` | `generate_basic_block` | Variable I/O rates, custom forecast |
| `interp_block` | `generate_interp_block` | More outputs than inputs (upsampling) |
| `decim_block` | `generate_decim_block` | Fewer outputs than inputs (downsampling) |
## Generate GRC YAML
For blocks to appear in GNU Radio Companion's graphical editor, they need a `.block.yml` definition:
```python
yaml_result = generate_grc_yaml(
source_code=result.source_code,
block_name="configurable_gain",
module_name="custom",
inputs=[{"dtype": "float", "vlen": 1}],
outputs=[{"dtype": "float", "vlen": 1}],
parameters=[{
"name": "gain",
"dtype": "float",
"default": 1.0,
"min_value": 0.0,
"description": "Gain factor"
}],
category="Signal Processing"
)
# yaml_result.yaml_content contains the full .block.yml
# yaml_result.filename = "custom_configurable_gain.block.yml"
# yaml_result.notes may warn about missing setter methods
```
The generated YAML handles:
- **dtype mapping**: Python `float` → GRC `real`, `int` → `int`, `complex` → `complex`
- **Callbacks**: Detects `set_*()` methods for runtime parameter updates
- **Asserts**: Generates validation from `min_value`/`max_value` constraints
- **Documentation**: Extracts class docstrings
<Aside type="tip">
If `notes` mentions missing `set_*()` methods, add setter methods to your block for
runtime parameter updates in GRC:
```python
def set_gain(self, gain):
self.gain = gain
```
</Aside>
## Export to OOT Module
Once your block is working, export it to a proper Out-of-Tree module:
<Steps>
1. **Export the block** (creates OOT skeleton if needed)
```python
export = export_block_to_oot(
source_code=result.source_code,
block_name="configurable_gain",
module_name="custom",
output_dir="/tmp/gr-custom"
)
```
This creates:
```
/tmp/gr-custom/
├── CMakeLists.txt
├── python/custom/
│ ├── __init__.py
│ └── configurable_gain.py
└── grc/
└── custom_configurable_gain.block.yml
```
2. **Or generate the skeleton first**
```python
generate_oot_skeleton(
module_name="custom",
output_dir="/tmp/gr-custom",
author="Your Name"
)
# Then export multiple blocks into it
export_block_to_oot(...)
export_block_to_oot(...)
```
3. **Build and install** (requires runtime mode)
```python
enable_runtime_mode()
install_oot_module(
git_url="file:///tmp/gr-custom",
branch="main"
)
```
</Steps>
## Protocol-Driven Development
Generate decoder pipelines from protocol specifications:
```python
# Parse a protocol description
protocol = parse_protocol_spec("""
Chirp Spread Spectrum (CSS) signal:
- Spreading factor: 7
- Bandwidth: 125 kHz
- Preamble: 8 upchirps
- Sync word: 0x34
""")
# Generate the decoder chain
pipeline = generate_decoder_chain(protocol=protocol.name)
# Selects existing blocks + generates custom ones
# Check what OOT modules you need
missing = get_missing_oot_modules(protocol=protocol.name)
```
## Signal Analysis Workflow
Start from a captured IQ file and work backwards to a decoder:
```python
# Analyze the capture
analysis = analyze_iq_file(
file_path="/tmp/capture.raw",
sample_rate=2e6,
dtype="complex64"
)
# Returns: bandwidth, center freq offset, SNR, modulation hints
# Use the analysis to guide block generation
result = generate_sync_block(
name="matched_demod",
description=f"Demodulator for {analysis.estimated_modulation} signal "
f"with {analysis.estimated_bandwidth} Hz bandwidth",
...
)
```
## Prompt Resources
Block dev mode registers prompt resources that guide code generation:
| Resource | Content |
|----------|---------|
| `prompts://block-generation/sync-block` | `gr.sync_block` patterns and examples |
| `prompts://block-generation/basic-block` | `gr.basic_block` with forecast patterns |
| `prompts://block-generation/common-patterns` | Reusable idioms (history, tags, PMTs) |
| `prompts://block-generation/grc-yaml` | `.block.yml` format reference |
| `prompts://protocol-analysis/decoder-chain` | Decoder pipeline patterns |
These are accessible to any MCP client and contain the patterns needed to generate
correct GNU Radio block code.
## Next Steps
- [Block Dev Tools Reference](/reference/tools/block-dev/) — Complete parameter reference
- [Working with OOT Modules](/guides/oot-modules/) — Install and manage OOT modules
- [Tools Overview](/reference/tools-overview/) — All available tools

View File

@ -245,7 +245,69 @@ launch_flowgraph(
)
```
## Export Custom Blocks to OOT
GR-MCP can also create OOT modules from scratch using the block development tools:
<Steps>
1. **Enable block dev mode**
```python
enable_block_dev_mode()
```
2. **Generate a block**
```python
result = generate_sync_block(
name="my_filter",
description="Custom bandpass filter",
input_signature=[{"dtype": "complex", "vlen": 1}],
output_signature=[{"dtype": "complex", "vlen": 1}],
)
```
3. **Generate GRC YAML** (for GUI integration)
```python
yaml_result = generate_grc_yaml(
source_code=result.source_code,
block_name="my_filter",
module_name="custom",
category="Filters"
)
```
4. **Export to OOT module**
```python
export_block_to_oot(
source_code=result.source_code,
block_name="my_filter",
module_name="custom",
output_dir="/tmp/gr-custom"
)
# Creates: CMakeLists.txt, python/custom/my_filter.py, grc/custom_my_filter.block.yml
```
5. **Build as Docker image** (for container deployment)
```python
enable_runtime_mode()
install_oot_module(
git_url="file:///tmp/gr-custom",
branch="main"
)
```
</Steps>
<Aside type="tip">
See the [Block Development guide](/guides/block-development/) for the full workflow
including protocol analysis and signal analysis.
</Aside>
## Next Steps
- [Block Development](/guides/block-development/) — Generate custom blocks and export to OOT
- [Runtime Control](/guides/runtime-control/) — Control variables while the flowgraph runs
- [OOT Catalog Reference](/reference/oot-catalog/) — Full module list with install examples

View File

@ -27,18 +27,18 @@ GR-MCP is a [FastMCP](https://gofastmcp.com) server that exposes GNU Radio's flo
- **OOT module management** — Install and combine Out-of-Tree modules on demand
<CardGrid stagger>
<Card title="29 Platform Tools" icon="puzzle">
<Card title="34 Platform Tools" icon="puzzle">
Create blocks, connect ports, validate flowgraphs, and generate Python code
</Card>
<Card title="40+ Runtime Tools" icon="rocket">
Launch containers, control XML-RPC variables, monitor ControlPort knobs
</Card>
<Card title="Block Development" icon="seti:python">
Generate blocks from descriptions, analyze protocols, export to OOT modules with GRC YAML
</Card>
<Card title="24 OOT Modules" icon="add-document">
Curated catalog with gr-osmosdr, gr-satellites, gr-lora_sdr, and more
</Card>
<Card title="Dynamic Registration" icon="setting">
Runtime tools load on-demand to minimize context usage
</Card>
</CardGrid>
## Quick Example
@ -113,4 +113,14 @@ launch_flowgraph(
[Follow the tutorial →](/getting-started/first-flowgraph/)
</Card>
<Card title="Block Development" icon="seti:python">
Generate blocks, analyze protocols, export to OOT
[Start building →](/guides/block-development/)
</Card>
<Card title="OOT Modules" icon="add-document">
Install and combine Out-of-Tree modules
[Browse the catalog →](/guides/oot-modules/)
</Card>
</CardGrid>

View File

@ -6,16 +6,20 @@ draft: false
import { CardGrid, Card, Aside } from '@astrojs/starlight/components';
GR-MCP exposes tools in two groups: **platform tools** (always available) for flowgraph
design, and **runtime tools** (loaded on demand) for container control.
GR-MCP exposes tools in three groups: **platform tools** (always available) for flowgraph
design, **block development tools** (loaded on demand) for code generation and protocol analysis,
and **runtime tools** (loaded on demand) for container control.
## Tool Organization
<CardGrid>
<Card title="29 Platform Tools" icon="puzzle">
<Card title="34 Platform Tools" icon="puzzle">
Always available for flowgraph building, validation, and code generation.
No Docker required.
</Card>
<Card title="~18 Block Dev Tools" icon="seti:python">
Loaded via `enable_block_dev_mode()`. Generate blocks, analyze protocols, export to OOT.
</Card>
<Card title="~40 Runtime Tools" icon="rocket">
Loaded via `enable_runtime_mode()`. Requires Docker for container features.
</Card>
@ -83,6 +87,61 @@ design, and **runtime tools** (loaded on demand) for container control.
| [`evaluate_expression`](/reference/tools/codegen#evaluate_expression) | Evaluate Python expression |
| [`create_embedded_python_block`](/reference/tools/codegen#create_embedded_python_block) | Create embedded Python block |
## Block Development Tools (Enable with `enable_block_dev_mode()`)
<Aside>
Block dev tools provide code generation and protocol analysis. No Docker required
for generation — only `test_block_in_docker` needs Docker.
</Aside>
### Block Dev Mode Control
| Tool | Description |
|------|-------------|
| [`get_block_dev_mode`](/reference/tools/block-dev#get_block_dev_mode) | Check block dev mode status |
| [`enable_block_dev_mode`](/reference/tools/block-dev#enable_block_dev_mode) | Enable block dev tools |
| [`disable_block_dev_mode`](/reference/tools/block-dev#disable_block_dev_mode) | Disable block dev tools |
### Block Generation
| Tool | Description |
|------|-------------|
| [`generate_sync_block`](/reference/tools/block-dev#generate_sync_block) | Generate `gr.sync_block` from description |
| [`generate_basic_block`](/reference/tools/block-dev#generate_basic_block) | Generate `gr.basic_block` with custom forecast |
| [`generate_interp_block`](/reference/tools/block-dev#generate_interp_block) | Generate interpolation block |
| [`generate_decim_block`](/reference/tools/block-dev#generate_decim_block) | Generate decimation block |
| [`validate_block_code`](/reference/tools/block-dev#validate_block_code) | Validate syntax, imports, signatures |
| [`parse_block_prompt`](/reference/tools/block-dev#parse_block_prompt) | Parse natural language into block spec |
### Block Testing
| Tool | Description |
|------|-------------|
| [`test_block_in_docker`](/reference/tools/block-dev#test_block_in_docker) | Test block in isolated Docker container |
### Protocol Analysis
| Tool | Description |
|------|-------------|
| [`parse_protocol_spec`](/reference/tools/block-dev#parse_protocol_spec) | Parse protocol description into structured model |
| [`generate_decoder_chain`](/reference/tools/block-dev#generate_decoder_chain) | Generate multi-block decoder pipeline |
| [`get_missing_oot_modules`](/reference/tools/block-dev#get_missing_oot_modules) | Identify OOT modules needed for a protocol |
### Signal Analysis
| Tool | Description |
|------|-------------|
| [`analyze_iq_file`](/reference/tools/block-dev#analyze_iq_file) | Analyze IQ capture characteristics |
### OOT Export
| Tool | Description |
|------|-------------|
| [`generate_grc_yaml`](/reference/tools/block-dev#generate_grc_yaml) | Generate `.block.yml` for GRC integration |
| [`generate_oot_skeleton`](/reference/tools/block-dev#generate_oot_skeleton) | Generate gr_modtool-compatible OOT scaffold |
| [`export_block_to_oot`](/reference/tools/block-dev#export_block_to_oot) | Export block to full OOT module structure |
| [`export_from_flowgraph`](/reference/tools/block-dev#export_from_flowgraph) | Export embedded block from flowgraph to OOT |
## Runtime Tools (Enable with `enable_runtime_mode()`)
<Aside>
@ -163,9 +222,19 @@ won't be registered.
## MCP Resources
In addition to tools, GR-MCP exposes resources for OOT module discovery:
In addition to tools, GR-MCP exposes resources for OOT module discovery and block development prompts:
| URI | Description |
|-----|-------------|
| `oot://directory` | Index of all OOT modules in the catalog |
| `oot://directory/{name}` | Detailed info for a specific module |
### Block Development Prompts (available when block dev mode is enabled)
| URI | Description |
|-----|-------------|
| `prompts://block-generation/sync-block` | Patterns for `gr.sync_block` generation |
| `prompts://block-generation/basic-block` | Patterns for `gr.basic_block` generation |
| `prompts://block-generation/common-patterns` | Reusable block patterns and idioms |
| `prompts://block-generation/grc-yaml` | GRC YAML `.block.yml` format guide |
| `prompts://protocol-analysis/decoder-chain` | Decoder pipeline generation patterns |

View File

@ -0,0 +1,275 @@
---
title: Block Development Tools
description: Reference for block generation, protocol analysis, and OOT export tools
draft: false
---
import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';
Block development tools are loaded dynamically via `enable_block_dev_mode()`. They provide
code generation, validation, protocol analysis, signal analysis, and OOT module export.
<Aside>
These tools register 5 MCP prompt resources for guiding code generation. Read them
via `prompts://block-generation/sync-block`, `prompts://block-generation/grc-yaml`, etc.
</Aside>
## Mode Control
### `get_block_dev_mode`
Check whether block development mode is enabled.
**Returns:** `BlockDevModeStatus` with `enabled`, `tools_registered`
### `enable_block_dev_mode`
Enable block development tools. Registers ~15 tools and 5 prompt resources.
**Returns:** `BlockDevModeStatus` with list of registered tools
### `disable_block_dev_mode`
Disable block development tools, removing them from the tool list.
**Returns:** `BlockDevModeStatus`
---
## Block Generation
### `generate_sync_block`
Generate a `gr.sync_block` from a natural language description. The 1:1 input-to-output
ratio makes this the most common block type.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `name` | string | Yes | Block name (e.g., `"configurable_gain"`) |
| `description` | string | Yes | Natural language description of block behavior |
| `input_signature` | list | Yes | Input port specs: `[{"dtype": "float", "vlen": 1}]` |
| `output_signature` | list | Yes | Output port specs |
| `parameters` | list | No | Constructor params: `[{"name": "gain", "dtype": "float", "default": 1.0}]` |
| `work_logic` | string | No | Description of the work function logic |
**Returns:** `GeneratedBlockCode` with `source_code`, `is_valid`, `validation_errors`
### `generate_basic_block`
Generate a `gr.basic_block` with custom `forecast()` and `general_work()`. Use this
when input/output rates differ in non-trivial ways.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `name` | string | Yes | Block name |
| `description` | string | Yes | Block behavior description |
| `input_signature` | list | Yes | Input port specs |
| `output_signature` | list | Yes | Output port specs |
| `parameters` | list | No | Constructor parameters |
| `forecast_logic` | string | No | How to predict input requirements |
| `work_logic` | string | No | Processing logic description |
**Returns:** `GeneratedBlockCode`
### `generate_interp_block`
Generate an interpolation block (`gr.interp_block`) that produces more output samples
than input samples.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `name` | string | Yes | Block name |
| `description` | string | Yes | Block behavior description |
| `interpolation` | int | Yes | Interpolation factor |
| `input_signature` | list | Yes | Input port specs |
| `output_signature` | list | Yes | Output port specs |
| `parameters` | list | No | Constructor parameters |
**Returns:** `GeneratedBlockCode`
### `generate_decim_block`
Generate a decimation block (`gr.decim_block`) that produces fewer output samples
than input samples.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `name` | string | Yes | Block name |
| `description` | string | Yes | Block behavior description |
| `decimation` | int | Yes | Decimation factor |
| `input_signature` | list | Yes | Input port specs |
| `output_signature` | list | Yes | Output port specs |
| `parameters` | list | No | Constructor parameters |
**Returns:** `GeneratedBlockCode`
---
## Validation
### `validate_block_code`
Validate generated block code without execution. Checks syntax (`ast.parse`), required
imports, class hierarchy, `work()` method signature, and I/O signature consistency.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `source_code` | string | Yes | Python source code to validate |
**Returns:** `ValidationResult` with `is_valid`, `errors`, `warnings`
### `parse_block_prompt`
Parse a natural language description into a structured block specification. Useful for
multi-step workflows where you want to review the spec before generating code.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `prompt` | string | Yes | Natural language block description |
**Returns:** Structured block specification with inferred name, I/O, parameters
---
## Block Testing
### `test_block_in_docker`
Test a generated block in an isolated Docker container. Creates a test harness flowgraph
with `vector_source` → block → `vector_sink`, runs it, and collects output.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `source_code` | string | Yes | Block source code |
| `test_input` | list | No | Input samples (e.g., `[1.0, 2.0, 3.0]`) |
| `parameters` | dict | No | Constructor args (e.g., `{"gain": 2.0}`) |
| `timeout` | int | No | Max execution time in seconds (default: 30) |
**Returns:** `DockerTestResult` with `success`, `output_data`, `errors`, `duration`
<Aside type="caution">
Requires Docker. The `gnuradio-runtime` base image must be built first.
</Aside>
---
## Protocol Analysis
### `parse_protocol_spec`
Parse a protocol description (natural language or structured) into a `ProtocolModel`.
Identifies modulation scheme, framing, encoding, and relevant parameters.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `spec` | string | Yes | Protocol description or specification |
**Returns:** `ProtocolModel` with `modulation`, `framing`, `encoding` details
### `generate_decoder_chain`
Generate a complete multi-block decoder pipeline from a protocol specification.
Selects existing GNU Radio blocks where possible, generates custom blocks for gaps.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `protocol` | string | Yes | Protocol name or specification |
| `sample_rate` | float | No | Target sample rate |
| `center_freq` | float | No | Center frequency |
**Returns:** `DecoderPipelineModel` with `blocks`, `connections`, and required OOT modules
### `get_missing_oot_modules`
Identify which OOT modules are needed for a protocol but aren't installed.
Cross-references the protocol's block requirements against the OOT catalog.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `protocol` | string | Yes | Protocol name |
**Returns:** List of missing module names with install instructions
---
## Signal Analysis
### `analyze_iq_file`
Analyze a captured IQ file to determine signal characteristics. Performs FFT analysis,
estimates bandwidth, detects signal presence, and estimates modulation parameters.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `file_path` | string | Yes | Path to IQ capture file |
| `sample_rate` | float | Yes | Sample rate of the capture |
| `dtype` | string | No | Data type (default: `"complex64"`) |
**Returns:** Analysis results including bandwidth, center frequency offset, SNR estimate
---
## OOT Export
### `generate_grc_yaml`
Generate a GRC block definition (`.block.yml`) file for a block. This is required for
blocks to appear in GNU Radio Companion's graphical editor.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `source_code` | string | Yes | Block Python source code |
| `block_name` | string | Yes | Block name |
| `module_name` | string | No | Module prefix (default: `"custom"`) |
| `inputs` | list | No | Input port specs |
| `outputs` | list | No | Output port specs |
| `parameters` | list | No | Block parameters with types and defaults |
| `category` | string | No | GRC palette category |
**Returns:** `GrcYamlResult` with `yaml_content`, `filename`, `block_id`, `notes`
<Aside type="tip">
The generated YAML includes `flags: [ python ]`, parameter dtype mapping (Python `float` →
GRC `real`), setter method detection for callbacks, and `asserts` from parameter min/max values.
</Aside>
### `generate_oot_skeleton`
Generate a gr_modtool-compatible Out-of-Tree module skeleton with `CMakeLists.txt`,
Python package structure, and `grc/` directory.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `module_name` | string | Yes | Module name (e.g., `"custom"`, not `"gr-custom"`) |
| `output_dir` | string | Yes | Where to create the module directory |
| `author` | string | No | Module author name |
**Returns:** `OOTSkeletonResult` with `success`, `module_name`, `path`
### `export_block_to_oot`
Export a generated block into a full OOT module structure. Creates the Python source file,
GRC YAML block definition, and updates `__init__.py`. Creates the OOT skeleton if it
doesn't exist.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `source_code` | string | Yes | Block source code |
| `block_name` | string | Yes | Block name |
| `module_name` | string | Yes | Target OOT module name |
| `output_dir` | string | Yes | OOT module root directory |
**Returns:** `ExportResult` with `success`, file paths created
### `export_from_flowgraph`
Export an embedded Python block from the current flowgraph into an OOT module.
Extracts the block's source code and metadata, then calls `export_block_to_oot`.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `block_id` | string | Yes | Block ID in the flowgraph (e.g., `"epy_block_0"`) |
| `module_name` | string | Yes | Target OOT module name |
| `output_dir` | string | Yes | OOT module root directory |
**Returns:** `ExportResult`