Skip to content

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 only

Notes:

  • 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:00 and compression uses level 9.

Canonical manifest schema

The canonical manifest fields are:

  • key
  • name
  • version
  • driverType
  • driverFile
  • properties
  • commands
  • io
  • envMap

Optional fields:

  • vendor
  • description
  • iotClass
  • capabilities
  • events
  • metadata

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:

  • python
  • lua
  • javascript

driverFile

Required. File name of the runtime entrypoint. The extension must match driverType:

  • python.py
  • lua.lua
  • javascript.js

properties

Required. Array of setup fields shown to the user.

Each property object supports:

  • key — required
  • label — required
  • type — required, one of string | number | boolean | select
  • required — optional boolean
  • defaultValue — optional; used at runtime when present
  • placeholder — optional string
  • description — optional string
  • options — optional array for select

Notes:

  • defaultValue is optional in schema and should be documented as a policy convenience, not a mandatory field.
  • Legacy text and password property types are not canonical.

commands

Required. Array of command descriptors.

Each command object supports:

  • key — required
  • label — required
  • description
  • category
  • entityDomain
  • payloadHint
  • payloadSchema
  • resultSchema
  • idempotent
  • timeoutMs
  • aliases

io

Required. Object with inputs and outputs arrays.

Each port object supports:

  • key — required
  • label — required
  • signal — required, one of:
    • audio
    • video
    • control
    • network
    • power

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.json file.
  • 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