Skip to content

Commit 10593df

Browse files
committed
Initial v0.3 commit: DCP — Device Context Protocol
A protocol that lets LLM agents safely control physical devices, scaling down to commodity microcontrollers. Complementary to MCP — a reference Bridge translates DCP <-> MCP so any MCP host works zero-config. What ships in this commit: * Spec (SPEC.md): wire format, manifest schema, capability tokens, optional per-frame HMAC-SHA256. v0.3 draft. * Python Bridge (`src/dcp/`): five transports (loopback, UART with COBS+CRC, MQTT, BLE GATT, in-process simulator), MCP server wrapper, capability token mint/verify, CLI with serve/inspect/codegen/token subcommands. * ESP32 reference firmware (`firmware/esp32/`): Arduino-compatible C++, hand-rolled CBOR subset, self-contained SHA-256, COBS framing, intent dispatch with constexpr DCP_ID(name) macro, optional BLE peripheral via NimBLE-Arduino. * Conformance suite (`tests/conformance/`): language-neutral YAML golden frames + Python runner; 88 tests total all green. * Hardware-validated: ESP32-WROOM-32 / CH340 / 115200 baud, 10/10 round-trip tests pass against real silicon. * Docs: README, SPEC.md, RATIONALE.md (vs MCP/WoT/Matter/Sparkplug/OpenAPI), ADDING_FEATURES.md, paper draft with figures, QUICKSTART_VIDEO script. * Landing site (`docs/site/`): Vue 3 + Vite 7 + Tailwind v4 (CSS-first). * Release prep: MIT, CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, issue and PR templates, GitHub Actions CI (Linux + Windows × Python 3.11-3.13).
0 parents  commit 10593df

86 files changed

Lines changed: 8322 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Bug report
2+
description: Report something that doesn't work
3+
labels: [bug]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Thanks for taking the time to file a bug. Please fill in as much
9+
as you can — vague reports tend to sit unhandled.
10+
11+
- type: input
12+
id: dcp-version
13+
attributes:
14+
label: DCP version
15+
placeholder: "0.2.0 (or `git describe`)"
16+
validations:
17+
required: true
18+
19+
- type: dropdown
20+
id: component
21+
attributes:
22+
label: Which component
23+
multiple: true
24+
options:
25+
- Wire format / framing
26+
- Bridge
27+
- MCP server wrapper
28+
- CLI
29+
- UART transport
30+
- MQTT transport
31+
- BLE transport
32+
- ESP32 firmware
33+
- Codegen
34+
- Manifest parser
35+
- Docs / examples
36+
validations:
37+
required: true
38+
39+
- type: textarea
40+
id: what-happened
41+
attributes:
42+
label: What happened
43+
description: Include the full error message and tracebacks.
44+
render: shell
45+
validations:
46+
required: true
47+
48+
- type: textarea
49+
id: expected
50+
attributes:
51+
label: What you expected
52+
validations:
53+
required: true
54+
55+
- type: textarea
56+
id: reproduce
57+
attributes:
58+
label: Minimal reproduction
59+
description: Smallest possible commands or code that triggers it.
60+
render: shell
61+
validations:
62+
required: true
63+
64+
- type: input
65+
id: env
66+
attributes:
67+
label: Environment
68+
placeholder: "Windows 11 · Python 3.13 · ESP32-WROOM (CH340)"
69+
70+
- type: checkboxes
71+
id: checks
72+
attributes:
73+
label: Pre-flight
74+
options:
75+
- label: I have searched existing issues
76+
required: true
77+
- label: This is not a security report (those go to SECURITY.md)
78+
required: true

.github/ISSUE_TEMPLATE/config.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
blank_issues_enabled: false
2+
contact_links:
3+
- name: Security vulnerability
4+
url: https://github.com/device-context-protocol/dcp/security/policy
5+
about: Report security issues privately. Do not open a public issue.
6+
- name: Design discussion
7+
url: https://github.com/device-context-protocol/dcp/discussions
8+
about: Ideas and open-ended design questions belong here.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Feature request
2+
description: Suggest a new capability or improvement
3+
labels: [enhancement]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
DCP is intentionally small. Features that move us toward
9+
"real devices controlled by real LLMs" go to the top; features
10+
that add abstraction without a concrete user wait.
11+
12+
- type: textarea
13+
id: problem
14+
attributes:
15+
label: What problem does this solve
16+
description: Describe the user / scenario, not the proposed code.
17+
validations:
18+
required: true
19+
20+
- type: textarea
21+
id: proposal
22+
attributes:
23+
label: Proposed approach
24+
validations:
25+
required: true
26+
27+
- type: textarea
28+
id: alternatives
29+
attributes:
30+
label: Alternatives considered
31+
description: Including "do nothing".
32+
33+
- type: dropdown
34+
id: scope
35+
attributes:
36+
label: Scope
37+
options:
38+
- Spec / wire format
39+
- Bridge / Python lib
40+
- CLI
41+
- Firmware
42+
- Docs
43+
- Tooling / CI
44+
validations:
45+
required: true
46+
47+
- type: checkboxes
48+
id: checks
49+
attributes:
50+
label: Pre-flight
51+
options:
52+
- label: I have read RATIONALE.md and this isn't already addressed
53+
required: true
54+
- label: I have searched existing issues
55+
required: true

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!--
2+
Thanks for the contribution. A short PR is easier to review than a careful
3+
one — please prefer "one logical change per PR" even when that means splitting.
4+
-->
5+
6+
## What
7+
8+
<!-- one or two sentences -->
9+
10+
## Why
11+
12+
<!-- the user / scenario this serves; link any related issue -->
13+
14+
## Spec impact
15+
16+
- [ ] No spec impact (just code / docs / tests)
17+
- [ ] Changes wire format, manifest schema, or safety model — see RATIONALE.md
18+
for what we expect from this kind of change
19+
20+
## Checklist
21+
22+
- [ ] Tests added or updated
23+
- [ ] `ruff check src tests` passes locally
24+
- [ ] `pytest` passes locally
25+
- [ ] CHANGELOG.md updated under `## [Unreleased]`
26+
- [ ] If a public API or CLI changed, the README and `docs/RATIONALE.md` are
27+
consistent with the new behavior

.github/workflows/test.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: tests
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
pull_request:
7+
8+
jobs:
9+
test:
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
os: [ubuntu-latest, windows-latest]
15+
python: ["3.11", "3.12", "3.13"]
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- uses: actions/setup-python@v5
21+
with:
22+
python-version: ${{ matrix.python }}
23+
cache: pip
24+
25+
- name: Install
26+
run: |
27+
python -m pip install --upgrade pip
28+
python -m pip install -e ".[mcp,serial,dev]"
29+
30+
- name: Lint
31+
run: ruff check src tests
32+
33+
- name: Test
34+
run: pytest -v

.gitignore

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
__pycache__/
2+
*.py[cod]
3+
*.egg-info/
4+
.pytest_cache/
5+
.ruff_cache/
6+
.venv/
7+
venv/
8+
dist/
9+
build/
10+
*.egg
11+
.coverage
12+
htmlcov/
13+
.mypy_cache/
14+
.DS_Store
15+
16+
# LaTeX build artifacts
17+
*.aux
18+
*.bbl
19+
*.blg
20+
*.fdb_latexmk
21+
*.fls
22+
*.log
23+
*.out
24+
*.synctex.gz
25+
*.toc
26+
docs/paper/main.pdf
27+
28+
# Local MCP / Claude Desktop configs (user-specific paths and ports)
29+
.mcp.json
30+
**/claude_desktop_config.json.bak-dcp
31+
32+
# Node / Vite (site)
33+
node_modules/
34+
.vite/
35+
36+
# Tools install dir created by Arduino CLI setup
37+
**/dcp-tools/

.mcp.json.example

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"_comment": "Copy this file to .mcp.json and edit the manifest path + serial port. Then restart Claude Code (or whatever MCP host) in this directory. The MCP host will spawn `dcp serve` and expose the lamp's intents as tools.",
3+
"mcpServers": {
4+
"dcp-lamp": {
5+
"command": "dcp",
6+
"args": [
7+
"serve",
8+
"examples/lamp_manifest.yaml",
9+
"--simulator"
10+
]
11+
},
12+
"dcp-lamp-real-hardware-example": {
13+
"command": "dcp",
14+
"args": [
15+
"serve",
16+
"examples/lamp_manifest.yaml",
17+
"--serial",
18+
"COM5"
19+
]
20+
}
21+
}
22+
}

CHANGELOG.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/) once
7+
it reaches 1.0. Pre-1.0 releases may break compatibility.
8+
9+
## [Unreleased]
10+
11+
### Added
12+
13+
- **Wire-level HMAC-SHA256** (`Frame.encode(wire_secret=...)` / `decode(...)`):
14+
optional 16-byte truncated signature appended to every frame. Both Bridge
15+
and device must agree; no in-band downgrade marker by design.
16+
- **Self-contained SHA-256 + HMAC-SHA256** in the ESP32 firmware
17+
(`DCPCrypto.h`/`.cpp`) — no mbedtls/ESP-IDF dependency, ~1 KB of code.
18+
- **DCPBle**: ESP32 BLE peripheral via NimBLE-Arduino. Same intent table as
19+
`DCP`; one service, c2d/d2c characteristics derived from service UUID by
20+
convention (`0xC1` / `0xD1` last byte).
21+
- **Conformance suite**: `tests/conformance/golden_frames.yaml` + Python
22+
runner. Language-neutral; ports can write equivalent runners.
23+
- **Codegen `--stubs`**: emits handler-function signatures and a
24+
`DCP_BINDINGS[]` table so the firmware author only writes business logic.
25+
- **Quickstart video script** at `docs/QUICKSTART_VIDEO.md`.
26+
27+
### Changed
28+
29+
- `Bridge` constructor takes `wire_secret=` for per-frame signing.
30+
31+
## [0.2.0] - 2026-05-12
32+
33+
### Added
34+
35+
- **HMAC-SHA256 capability tokens** (`dcp.tokens`): mint, verify, expiry.
36+
Bridge accepts `token=` + `secret=` at construction and enforces capabilities
37+
from the token on every call.
38+
- **MQTT transport** (`dcp.transports.mqtt`): `dcp/{prefix}/{c2d,d2c}` topic
39+
convention, QoS 1, paho-mqtt 2.x callback API.
40+
- **BLE GATT transport** (`dcp.transports.ble`): one service, c2d/d2c
41+
characteristics derived from service UUID by convention.
42+
- **YAML → C header codegen** (`dcp codegen`): generates intent IDs, event
43+
IDs, capability constants, and a manifest hash.
44+
- **Compile-time `DCP_ID(name)` macro** in firmware (C++14 constexpr CRC-16),
45+
removing the runtime `intent_id()` call from `setup()`.
46+
- **CLI subcommands**: `dcp codegen`, `dcp token mint`, `dcp token keygen`.
47+
- **CLI flags on `dcp serve`**: `--mqtt HOST[:PORT]`, `--mqtt-prefix`,
48+
`--ble ADDRESS`, `--ble-service UUID`.
49+
- Smarter `GenericSimulator`: read intents named `read_X` / `get_X` return
50+
the last value written by `set_X`.
51+
52+
### Changed
53+
54+
- `Bridge` constructor now optionally takes `token=` and `secret=`.
55+
- README quickstart updated to install all extras by default.
56+
57+
## [0.1.0] - 2026-05-12
58+
59+
### Added
60+
61+
- Wire format: 6-byte header + CBOR payload, CRC-16/CCITT intent IDs.
62+
- Manifest parser (YAML → dataclasses) with units, ranges, capability strings.
63+
- Safety layer: range checks, type coercion, capability gating.
64+
- Bridge orchestrator with async call/reply, event subscription, dry-run.
65+
- Transports: `LoopbackTransport` (in-memory), `UartTransport` (COBS + CRC-16
66+
over pyserial-asyncio).
67+
- `GenericSimulator` for hardware-free demos.
68+
- MCP server wrapper (`dcp serve --simulator | --serial`) exposing each
69+
intent as an MCP tool.
70+
- `dcp` CLI with `serve` and `inspect` subcommands.
71+
- ESP32 reference firmware (Arduino-compatible C++): tiny CBOR subset, COBS
72+
framing, CRC-16, intent dispatch, dry-run support. Target <16 KB flash.
73+
- Smart-lamp example: manifest, Python demo, ESP32 sketch.
74+
- Design rationale doc (`docs/RATIONALE.md`) covering MCP / WoT / Matter /
75+
Sparkplug B / OpenAPI comparisons.
76+
- GitHub Actions CI: Linux + Windows × Python 3.11–3.13, pytest + ruff.
77+
78+
[Unreleased]: https://github.com/device-context-protocol/dcp/compare/v0.2.0...HEAD
79+
[0.2.0]: https://github.com/device-context-protocol/dcp/releases/tag/v0.2.0
80+
[0.1.0]: https://github.com/device-context-protocol/dcp/releases/tag/v0.1.0

0 commit comments

Comments
 (0)