Appearance
Driver Manifest Reference
The driver manifest describes an OS-local driver package. It tells Haptique OS how to render the setup form, wire inputs and outputs, map environment variables, and expose commands to the runtime.
This reference covers the uploadable OS-local ZIP path. External WebSocket drivers use a different SDK path and do not use this manifest.
Package structure
A valid uploaded driver package is a ZIP file containing:
text
my-driver.zip
├── my-driver.driver.json ← manifest (required, exactly one root *.driver.json)
├── driver.js ← runtime implementation (required, one root .js / .py / .lua file)
└── requirements.txt ← optional, Python onlyNotes:
- The runtime ZIP does not accept README or test files.
__MACOSX,.DS_Store, and AppleDouble._*metadata are treated as ignored metadata during inspection and extraction.- The ZIP must not contain absolute paths, path traversal, or NUL bytes.
- ZIP timestamps are normalized to
1980-01-01 00:00:00and compression uses level 9.
Canonical manifest schema
The canonical manifest fields are:
keynameversiondriverTypedriverFilepropertiescommandsioenvMap
Optional fields:
vendordescriptioniotClasscapabilitieseventsmetadata
Top-level example
json
{
"key": "EXAMPLE_AUDIO_MIXER",
"name": "Audio Mixer Driver",
"version": "1.2.0",
"driverType": "python",
"driverFile": "example_audio_mixer.py",
"vendor": "Example Community",
"description": "Controls a sample audio mixer over a local protocol.",
"iotClass": "local_push",
"capabilities": ["audio.mixing", "audio.volume", "audio.mute"],
"properties": [
{
"key": "host",
"label": "Host",
"type": "string",
"required": true,
"defaultValue": "192.0.2.10",
"placeholder": "192.0.2.10",
"description": "IP address or host name for the device"
},
{
"key": "port",
"label": "Port",
"type": "number",
"required": true,
"defaultValue": 443
},
{
"key": "mute",
"label": "Mute on startup",
"type": "boolean",
"defaultValue": false
},
{
"key": "inputSource",
"label": "Input Source",
"type": "select",
"defaultValue": "line-in",
"options": ["line-in", "usb", "bluetooth"]
}
],
"commands": [
{
"key": "setVolume",
"label": "Set Volume",
"description": "Set the master volume level",
"category": "audio",
"entityDomain": "media_player",
"payloadHint": "volume_level",
"payloadSchema": {
"type": "object",
"properties": {
"level": {"type": "number", "minimum": 0, "maximum": 100}
},
"required": ["level"],
"additionalProperties": false
},
"resultSchema": {
"type": "object",
"properties": {
"success": {"type": "boolean"}
},
"required": ["success"],
"additionalProperties": false
},
"idempotent": true,
"timeoutMs": 5000,
"aliases": ["volume", "vol"]
},
{
"key": "toggleMute",
"label": "Toggle Mute",
"idempotent": false,
"timeoutMs": 2000
}
],
"io": {
"inputs": [
{"key": "audio-in", "label": "Audio Input", "signal": "audio"},
{"key": "control-in", "label": "Control Input", "signal": "control"}
],
"outputs": [
{"key": "audio-out", "label": "Audio Output", "signal": "audio"},
{"key": "status", "label": "Device Status", "signal": "network"}
]
},
"envMap": {
"host": "EXAMPLE_AUDIO_MIXER_HOST",
"port": "EXAMPLE_AUDIO_MIXER_PORT",
"mute": "EXAMPLE_AUDIO_MIXER_MUTE",
"inputSource": "EXAMPLE_AUDIO_MIXER_INPUT_SOURCE"
}
}Field reference
key
Required. Uppercase reverse product key for the driver family. The builder accepts uppercase letters, digits, and underscores.
name
Required. Human-readable display name.
version
Required. Semver string.
driverType
Required. One of:
pythonluajavascript
driverFile
Required. File name of the runtime entrypoint. The extension must match driverType:
python→.pylua→.luajavascript→.js
properties
Required. Array of setup fields shown to the user.
Each property object supports:
key— requiredlabel— requiredtype— required, one ofstring | number | boolean | selectrequired— optional booleandefaultValue— optional; used at runtime when presentplaceholder— optional stringdescription— optional stringoptions— optional array forselect
Notes:
defaultValueis optional in schema and should be documented as a policy convenience, not a mandatory field.- Legacy
textandpasswordproperty types are not canonical.
commands
Required. Array of command descriptors.
Each command object supports:
key— requiredlabel— requireddescriptioncategoryentityDomainpayloadHintpayloadSchemaresultSchemaidempotenttimeoutMsaliases
io
Required. Object with inputs and outputs arrays.
Each port object supports:
key— requiredlabel— requiredsignal— required, one of:audiovideocontrolnetworkpower
envMap
Required. Object mapping property keys to environment variable names.
Example:
json
{
"host": "EXAMPLE_AUDIO_MIXER_HOST",
"port": "EXAMPLE_AUDIO_MIXER_PORT"
}envMap should contain string-to-string mappings only.
Packaging notes
- The manifest must live at the root of the ZIP as exactly one
*.driver.jsonfile. - The ZIP may contain exactly one runtime file at the root and, for Python only, an optional
requirements.txt. - README, tests, and other documentation stay in the source repository, not the installable ZIP.
- Unsafe ZIP content is rejected before activation.
Validation
- Builder schema validation:
npm run test --workspace=apps/mcp-driver-builder - ZIP safety and installer validation are enforced by the server-side driver package tests.
Cross reference
- Haptique Kitchen — source-only vs installable publication flow