mcurpc
Lightweight RPC framework for microcontrollers and Python.
MCURPC provides a small RPC stack for embedded targets together with Python tooling for API creation, code generation, runtime export, probing and interactive communication. APIs are described in YAML, resolved into a versioned JSON manifest and then used to generate C integration files for the embedded side.
The root README gives only a project-level overview and the most common commands. More detailed
implementation notes belong in the Sphinx documentation under docs/.
What is included
- API model and generator (
mcurpc_gen): validates YAML API descriptions, resolves IDs and options, createsmanifest.json,mcurpc_api.h,mcurpc_api.candmcurpc_config.h. - Embedded C runtime (
mcurpc_runtime): fixed MCURPC runtime sources for request dispatch, responses, events, logs and link framing. - Python runtime/client (
mcurpc): link/message/payload handling, transports, registry lookup, device probing and manifest-driven client calls. - Command line interface (
mcurpc_cli): project start, generation, runtime export, registry management, probing and interactive shell. - Optional GUI prototype (
mcurpc_gui): early project-oriented GUI components. - Tests and CI helpers: Python unit tests, C/C++ unit tests, CLI system tests, CMake integration checks, coverage and Sphinx build commands.
Repository layout
ci_commands/ Local CI command implementations
configs/ Project/tool configuration, when present
docs/ Sphinx documentation
src/ Python packages and packaged runtime resources
tests/ Python, C/C++ and CLI system tests
The most relevant source packages are:
src/mcurpc/ Python runtime, client, transports and registry support
src/mcurpc_cli/ Unified `mcurpc` command line interface
src/mcurpc_gen/ YAML model, resolver and C source generator
src/mcurpc_runtime/ Packaged embedded runtime files and starter examples
src/mcurpc_gui/ GUI prototype modules
Requirements
The Python package requires Python 3.11 or newer. Runtime dependencies include pydantic, pyyaml,
pyserial, platformdirs, cmd2 and cikit.
For the native C tests and CMake-based example checks, a working C/C++ toolchain, CMake and Ninja are expected. The repository currently uses CMake for native runtime tests and compile checks.
Installation for development
A typical local setup with uv is:
uv sync
uv run mcurpc --help
Alternatively, use an editable install in an existing virtual environment:
python -m pip install -e .
mcurpc --help
Basic workflow
A normal embedded workflow is:
- Create or edit an API YAML file.
- Export or create a target project layout.
- Generate API-specific C files from the YAML description.
- Implement the generated application callbacks in the target firmware.
- Register the manifest on the host side.
- Probe the device or open the interactive shell.
For a new starter project, the start command combines the first generation steps.
Creating a starter project
The start command creates a project from one of the packaged examples, exports the selected runtime
layout and generates the API-specific files.
mcurpc start build/my_ping --example ping --layout arduino
mcurpc start build/my_counter --example counter --layout cmake
mcurpc start build/my_api --example custom --layout flat
The available layouts are:
arduino: flattened Arduino-oriented project with the C runtime andMCURPCstream wrapper.cmake: runtime files below anmcurpc/subdirectory with a CMake target.flat: all runtime and generated files in one project directory.
Useful options:
mcurpc start PROJECT_DIR --example ping --layout arduino
mcurpc start PROJECT_DIR --example custom --layout cmake --name my_api
mcurpc start PROJECT_DIR --example counter --layout flat --force
Generating API files
Use generate when the project already exists and only the files derived from the API YAML should be
updated.
mcurpc generate api.yaml -o path/to/project
This writes:
manifest.json
mcurpc_api.c
mcurpc_api.h
mcurpc_config.h
The generated files are project-specific. The fixed runtime files are exported separately through
runtime or indirectly through start.
Exporting the runtime
Use runtime to copy only the fixed MCURPC runtime files into an existing project.
mcurpc runtime path/to/project --layout arduino
mcurpc runtime path/to/project --layout cmake
mcurpc runtime path/to/project --layout flat --force
The runtime export does not generate mcurpc_api.c, mcurpc_api.h, mcurpc_config.h or
manifest.json. Those files come from the API generator.
API YAML at a glance
A minimal API can look like this:
name: garage_api
uuid: 11111111-1111-4111-8111-111111111111
version: 1
options:
endpoint_count: 1
tx_queue_length: 2
requests:
- name: open_door
request:
- name: duration_ms
type: u32
events:
- name: state_changed
payload:
- name: state
type: u8
errors:
- name: invalid_state
The resolver adds internal system requests such as API identity probing. Application request IDs are kept separate from those system entries.
Registry and probing
The host-side registry maps API UUID and version to a resolved manifest. This lets tools probe a connected device without requiring the user to manually select a manifest.
Register an API YAML or resolved manifest:
mcurpc register api.yaml
mcurpc register manifest.json
mcurpc register api.yaml --registry ./registry --force
Show the default registry path:
mcurpc registry
Probe a device and print the matching manifest summary:
mcurpc probe serial -p /dev/ttyACM0 -b 115200
mcurpc probe --registry ./registry serial -p /dev/ttyACM0 -b 115200
The CLI also contains UDP frame transport support for host-side and test scenarios.
Interactive shell
The interactive shell probes the connected device, resolves the matching manifest and exposes manifest-driven commands.
mcurpc shell serial -p /dev/ttyACM0 -b 115200
Typical shell commands include:
info Show API summary
requests List application requests
rpc <name> [options] Call one manifest request
events Show received events
logs Show received log messages
help Show command help
quit Exit the shell
The rpc command is generated from the manifest, so request parameters follow the fields declared in
the API YAML.
Python client usage
The Python side can also be used directly. A manifest-driven client exposes generic calls and dynamic request methods built from the manifest.
from mcurpc.client import build_client
from mcurpc.registry import ManifestRegistry
from mcurpc.transport import SerialTransport
transport = SerialTransport("/dev/ttyACM0", baudrate=115200)
transport.open()
manifest = ManifestRegistry().find_by_uuid_version(
"11111111-1111-4111-8111-111111111111",
1,
)
client = build_client(manifest, transport)
client.start()
try:
response = client.call("open_door", {"duration_ms": 1000})
finally:
client.stop()
transport.close()
Check the current Python API before relying on helper names in external scripts, because the command line interface is the more stable integration surface at this stage.
Embedded integration
On the embedded side, generated request declarations are implemented by the application. The runtime calls these functions when matching request frames are received.
For Arduino projects, the packaged MCURPC wrapper connects the runtime to an Arduino Stream:
#include "MCURPC.hpp"
#include "mcurpc_api.h"
MCURPC mcurpc(Serial);
void setup(void)
{
Serial.begin(115200);
mcurpc.begin();
}
void loop(void)
{
mcurpc.process();
}
For plain C/CMake projects, call mcurpc_setup() once and mcurpc_loop() cyclically. Transport
integration feeds RX bytes or frames into the runtime and consumes pending TX bytes or frames through
the public transport functions.
Tests and local CI
The repository contains several test layers:
- Python unit tests in
tests/pyunittests/ - CLI/system tests in
tests/systemtests/ - native C/C++ runtime tests in
tests/cunittests/ - generated-code compile checks in the system test cases
Common commands:
uv run pytest tests/pyunittests
uv run pytest tests/systemtests
uv run cikit ctest . --alias cunittests
uv run cikit all
cikit all runs the local workflow, including linting, Python tests, system tests, C tests, coverage
steps and the Sphinx documentation build.
Documentation
The Sphinx documentation lives in docs/.
uv run cikit sphinx docs
Use the Sphinx docs for detailed runtime behavior, generator model details and build reports. The root README should stay focused on orientation and first-use workflows.
License
MCURPC is licensed under GPL-3.0-or-later.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mcurpc-0.2.0.tar.gz.
File metadata
- Download URL: mcurpc-0.2.0.tar.gz
- Upload date:
- Size: 115.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.7.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e98e17cb16657acd96ec381a90f6e4429c9103e844c0175d9cfd18b5e4e5de2c
|
|
| MD5 |
edf7af9e3e4062ef43742bf34dbfb72e
|
|
| BLAKE2b-256 |
7c7ac7f0c5c8ea14ad4c7774e36b93d66282fc4219cb7b27490dc4015cb92ca2
|
File details
Details for the file mcurpc-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mcurpc-0.2.0-py3-none-any.whl
- Upload date:
- Size: 156.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.7.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c748d8b0563c68eb49e1ff84c5292862c74fb246bd7ab303d982fff3bd7a9529
|
|
| MD5 |
ae8b03c04c07372eea76e193148f50b4
|
|
| BLAKE2b-256 |
02216c8b3986772ba0ac878ae4899af2ce3cabe8c274ab8abc3a8fa288abe0a3
|