Skip to main content

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, creates manifest.json, mcurpc_api.h, mcurpc_api.c and mcurpc_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:

  1. Create or edit an API YAML file.
  2. Export or create a target project layout.
  3. Generate API-specific C files from the YAML description.
  4. Implement the generated application callbacks in the target firmware.
  5. Register the manifest on the host side.
  6. 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 and MCURPC stream wrapper.
  • cmake: runtime files below an mcurpc/ 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

mcurpc-0.3.0.tar.gz (119.2 kB view details)

Uploaded Source

Built Distribution

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

mcurpc-0.3.0-py3-none-any.whl (165.9 kB view details)

Uploaded Python 3

File details

Details for the file mcurpc-0.3.0.tar.gz.

File metadata

  • Download URL: mcurpc-0.3.0.tar.gz
  • Upload date:
  • Size: 119.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.15

File hashes

Hashes for mcurpc-0.3.0.tar.gz
Algorithm Hash digest
SHA256 9f0707b493be0315be0942d1ab938b28bf53838e42086c284cf9c7bb78689af8
MD5 e3415e5bcf2a4612872f16ed94530fb9
BLAKE2b-256 8ba21646eff4c4e848dbfa869df453719f123f2b41d3857feed693637e52ac63

See more details on using hashes here.

File details

Details for the file mcurpc-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: mcurpc-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 165.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.15

File hashes

Hashes for mcurpc-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ba85748e3704f54d42958deb0e6148753f360f2e16abac5e8c3f1cbe18301cb4
MD5 180f7b95213aeca3b6c57ef08a9d58ad
BLAKE2b-256 b703eb843d20455e524af4079856ba11ef00057924a881dfdba1df23e099b067

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.4

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page