Skip to main content
Glama
dbonomo
by dbonomo

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
PEBBLE_API_TOKENNoOptional API token for authenticated operations (Tier 4). Required for token-gated, network-mutating operations. If not set, Tier 4 tools are not available.

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
capabilitiesA

Report which pebble-mcp capability tiers are available in this environment.

tier1_appstore is always true (pure HTTPS). tier2_design requires Pillow. tier3_devloop requires the pebble CLI on PATH. tier4_auth requires PEBBLE_API_TOKEN to be set. Also reports the server version.

store_appA

Full metadata for one appstore app or watchface by its id.

Returns hearts, author, description, the list of compatible hardware platforms (with a has_emery convenience flag), the latest release (version + date + notes), the direct .pbw download URL, and screenshot/header image URLs.

store_collectionA

List a named store collection, paginated, as compact summaries.

slug examples: most-loved, all, recently-updated, or a collection slug from a home row. type_string must be one of apps, watchapps-and-companions, faces, watchfaces. Each result row is id/title/type/author/hearts plus a compatible flag for the requested hardware. has_more indicates further pages; raise offset by limit to page.

store_categoryA

List apps in a store category (e.g. faces, games, tools), paginated, as compact id/title/type/author/hearts summaries with a compatible flag for the requested hardware. has_more indicates further pages.

store_developerA

List every app published by one developer, paginated, as compact id/title/type/author/hearts summaries with a compatible flag for the requested hardware. has_more indicates further pages.

store_searchA

Search the store by keyword — CLIENT-SIDE, with real limits.

The live appstore API has NO search endpoint, so this does not do a true full-text search. Instead it fetches a bounded candidate pool from the relevant store listings (the all and most-loved collections for type_string, paged up to a few hundred apps) and ranks them by case-insensitive substring/token matches on each app's title, author, and description. Results carry a score.

Consequences to keep in mind:

  • Coverage is only what those listings return: an obscure app outside the all/most-loved pool can be missed entirely.

  • It matches on stored listing text, not on-device behavior or tags.

  • type_string must be one of apps, watchapps-and-companions, faces, watchfaces. For an exact app you already know, prefer store_app by id.

store_compareA

Bulk-fetch several apps by id and return a side-by-side comparison table for competitive research.

rows has one entry per found app with: hearts, type, the list of compatible platforms, a has_emery flag, the latest release date, and the .pbw URL. Any ids that don't resolve come back in missing_ids rather than failing the whole call.

store_download_pbwA

Download an app's latest-release .pbw to dest_dir.

Creates dest_dir if needed, writes the file, and returns its path and byte size (plus the app title and version). The on-disk filename is derived from the (untrusted) appstore response but always sanitized to a single basename inside dest_dir — a hostile id/version cannot traverse out. Refuses with a clear error if: the app has no published .pbw; dest_dir exists as a non-directory; the body is empty (0 bytes); or the body exceeds a 32 MiB safety cap (real .pbw files are well under a megabyte). Sends the polite pebble-mcp User-Agent. This feeds the install/emulator flow — hand the returned path to a Tier 3 install tool.

image_quantizeA

Quantize an image to the Pebble 64-color palette; return stats + preview.

Args: source: a filesystem path, a base64 string, or a data: URI of the source image (hosts without a filesystem send base64). dither: "floyd-steinberg" (default), "none", or "ordered". corrected: preview in the sunlight-corrected display values instead of the bright uncorrected palette (reporting is unaffected).

Returns a stats object (colors used, per-pixel distance) plus the quantized preview image (2× nearest-neighbor upscale when small).

image_prepA

Resize/letterbox an image to a named target, quantize, and preview it.

Args: source: filesystem path, base64, or data: URI of the source image. target: "emery" (200×228), "menu-icon" (25×25), "appstore-banner" (720×320), or any platform name. fit: "contain" (letterbox) or "cover" (center-crop). dither: "floyd-steinberg" (default), "none", or "ordered". corrected: preview in sunlight-corrected display values.

Returns a stats object (target size, colors used, distance) plus the prepared preview image (2× nearest-neighbor upscale when small).

color_nearestA

Nearest of the 64 Pebble GColors to an arbitrary color.

Args: color: a hex string ("#RRGGBB" / "RRGGBB" / shorthand) or an "r,g,b" triple. background: optional background color; when given, the contrast ratio and legibility of the matched color on it are also reported.

Returns the matched GColor name, hex, C constant, packed ARGB8 byte, sunlight-corrected display hex, and sRGB distance to the input.

palette_swatchA

Render a labeled grid of color swatches to a PNG for eyeballing.

Args: colors: hex strings and/or "r,g,b" triples (1..64 of them). labels: optional captions, one per color; defaults to each color's palette name (or its hex when off-palette).

font_planA

Recommend Pebble system fonts for a UI role or a literal string.

Pass a role like "hero numerals", "body label", "title", "timer", "clock face numerals", "hint", or "button label" (curated from this project's DESIGN.md type scale) to get an ordered list of FONT_KEY_* candidates -- no resource cost, they're baked into firmware.

Pass literal text instead (e.g. "15:37" or "Rest 90s") to check it against every system font's glyph coverage: numbers-only fonts (the LECO family, and the Bitham/Roboto "_NUMBERS"/"_SUBSET" variants) that can't render the text are flagged with fits: false and missing_glyphs instead of being silently recommended. Either way, the response includes minimal_character_regex -- the tight characterRegex for a custom TTF font that ships only the glyphs actually used (the classic "[0-9:]" clock-digit trick from developer.repebble.com/guides/app-resources/fonts/).

size_hint (pixels) sorts candidates by closeness to that size. style filters/prefers a weight substring, e.g. "bold".

Zero-argument sharp edge: this never touches the network or a toolchain -- it's pure lookup, always available regardless of capability tier.

pdc_convertA

Convert an SVG icon/vector to a Pebble Draw Command (.pdc) file.

Validates PDC's known constraints before attempting conversion, so a bad SVG comes back as a structured violation list -- never a broken or silently-wrong .pdc. Supported SVG elements: g, layer, path (straight-line commands M/L/H/V/Z only -- flatten curves first), rect, polyline, polygon, line, circle. Not supported: gradients, masks, clip paths, filters, embedded text/images, and any transform other than translate(x, y).

On success, returns the .pdc file as base64 (pdc_base64) plus size_bytes, image width/height, num_commands, and any non-fatal warnings (e.g. odd coordinates -- PDC recommends an even-integer coordinate grid for crisp rendering). On failure, valid is false, pdc_base64 is absent, and violations lists exactly what to fix, one entry per offending element/attribute.

Next move on failure: fix the listed elements/attributes in the SVG (flatten curves to polylines, remove gradients/masks, replace text with outlined paths) and call again -- this tool never guesses at a lossy conversion.

flow_runA

Run a gallery-style flow spec against the emery emulator and return every screenshot.

Parses flow_text (see pebble_mcp.flow for the line format), installs each app/pbw onto the emulator with the kill+wipe-first discipline, drives the buttons/waits, and captures the shot steps. Project dirs in app steps resolve against the repo root (parent of the pebble-mcp package dir, overridable via PEBBLE_MCP_REPO_ROOT). out_dir defaults to a fresh tempdir.

Returns a JSON metadata block — flow name, out_dir, per-shot {app, name, path, duration_s}, plus retries and wedge_recoveries — followed by one MCP image per shot.

Refuses any flow requesting more than 40 shots (runaway guard).

SAFETY — live-write hazard. flow_run drives REAL apps that can fire REAL network POSTs. A flow against an app with server-mutating screens must NEVER confirm a live-send action (e.g. press select on a "submit" / "send" screen or inside a value picker that commits on confirm). The convention is a # SAFETY RULES (live-write hazards — DO NOT TRIGGER): comment block at the top of every flow file; the bundled example flows under pebble_mcp/examples/flows/ show the pattern — follow their rules. Capturing those screens is fine; confirming them is not.

flow_validateA

Parse a flow spec WITHOUT running it — a cheap pre-check.

Returns a step summary (step_count, shot_count, steps_by_type, and whether it exceeds the 40-shot flow_run cap) on success, or a clear parse error naming the offending 1-based line. Needs no emulator, so it is the right tool to validate a flow before spending an emulator run.

emu_screenshotA

Capture one screenshot of the running emery emulator as an image.

Optional name sets the file basename (.png appended if absent). Errors clearly if no emulator is running or the emulator is wedged.

emu_inputA

Send one input to the running emulator.

action is 'press', 'longpress', or 'tap'. 'press'/'longpress' require button (one of back/up/select/down); 'longpress' also requires duration_ms (> 0). 'tap' fires an accelerometer tap and takes no button or duration. Button and action names are validated.

emu_logsA

Capture emulator logs, bounded — never a firehose.

Streams pebble logs for at most seconds, optionally cutting at the first line containing until_pattern (matched), and clamps the result to the last max_bytes bytes (truncated).

pebble_buildA

Build a Pebble app project and return structured results.

Runs pebble build in project_dir (absolute, or relative to the workspace root). Returns success, the produced .pbw path, and compiler errors/warnings as structured file:line diagnostics. Requires the pebble CLI on PATH (see capabilities()).

pebble_installA

Install an app into the emulator, starting it if needed.

target is either a project directory (built first if needed) or a path to a prebuilt .pbw file; relative paths resolve against the workspace root. The emulator is killed and wiped first — the reliable-launch lesson — so expect a few seconds of startup. Requires the pebble CLI on PATH.

emu_startA

Boot the Pebble emulator for the given platform (default emery).

Idempotent-ish: if one is already running this reconnects/restarts. Requires the pebble CLI on PATH.

emu_stopA

Shut down the running emulator; wipe=True also clears its storage.

Wiping is the fix for most emulator flakiness (apps not launching, stale state). Requires the pebble CLI on PATH.

project_newA

Scaffold a new, immediately buildable Pebble project.

Writes the files directly (pure Python -- no pebble new-project shell-out), so it works on hosts without the CLI. The result compiles to a .pbw with pebble build as-is.

kind -- "watchface" (default; sets watchapp.watchface) or "watchapp". language -- "c" (default) emits src/c/<name>.c (a working digital-clock TextLayer for a watchface, or a Window+TextLayer for a watchapp) + wscript; "javascript" emits an Alloy project (projectType: "moddable", the modern on-watch JS engine): src/c/mdbl.c glue + src/embeddedjs/main.js

  • manifest.json + src/pkjs/index.js.

platforms -- defaults to all seven for C (aplite/basalt/chalk/diorite/emery/flint/gabbro). Alloy runs only on the Moddable-XS platforms emery (Time 2) and gabbro (Round 2), so JavaScript projects default to and are clamped to those (dropped platforms are reported in warnings).

companion adds a phone-side src/pkjs/index.js (implied for Alloy). config adds a pebble-clay settings page (src/pkjs/config.js + the dependency + companion). dest_dir is the parent directory; the project is created in <dest_dir>/<slug(name)>.

Returns path, uuid (a fresh uuid4), kind, language, platforms, files_created, warnings, and next_steps.

project_infoA

Summarize an existing Pebble project from its package.json.

Returns name, displayName, uuid, kind/watchface, detected language (C vs JavaScript/Alloy, inferred from projectType and src/ layout), project_type, platforms, capabilities, messageKeys, resources (the media list), and sdkVersion. Raises a clear error if dir has no package.json or no pebble block.

project_add_resourceA

Add a resource to a project and register it in package.json.

Copies source into <dir>/resources/ (created if missing) and appends/updates a resources.media entry with the given name and resource_type ("bitmap" | "font" | "raw"). For bitmaps, source may also be base64 / a data: URI, and passing prep_target (e.g. "emery", "menu-icon") routes the image through the design tier -- resize/letterbox + palette quantize -- before writing it. Returns the updated media list and the written file.

project_set_metaA

Edit a project's pebble metadata block in place.

uuid sets a specific UUID (or the literal "new" to generate a fresh uuid4). add_platforms / remove_platforms adjust targetPlatforms (validated against the seven known platforms, kept in canonical order). capabilities and message_keys replace those lists wholesale. Returns the updated pebble block.

design_reviewA

Critique a Pebble screenshot against the design system.

Analyzes one screenshot and returns an actionable, compact critique: palette adherence (what fraction of pixels are exact GColors, and the most-common off-palette colors with their nearest GColor), per-region contrast/legibility judged against the sunlight-corrected display values (the reflective LCD reads duller than sRGB), role guidance vs the pebble://colors house roles, and a prioritized suggestion list.

source is a filesystem path, base64, or a data: URI of the image — OR the literal 'emulator' to capture and analyze the running emery screen (needs the pebble CLI; see capabilities()). regions sets the N×N contrast grid (default 3).

This is a heuristic, not a human designer: it reasons about color statistics, never glyphs — it flags pairs that look illegible and colors that are off-palette or role-inappropriate; confirm the hero-value hierarchy by eye.

Returns a JSON critique block plus the analyzed image.

project_smoke_testA

Build, install, and screenshot a project — the one-call "does it run?".

Builds dir (relative to the workspace root, or absolute); if it builds, installs the fresh .pbw onto the emulator (kill+wipe-first) and captures the launch screen. Returns {built, installed, errors[], warnings[], pbw_path, launch_shot, notes} plus the launch screenshot as an image.

A failed build returns built=false with the compiler errors and skips install — so this is also the fastest "did my change compile" check. Requires the pebble CLI on PATH (see capabilities()).

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription
platformsPer-platform Pebble display specs (emery, basalt, chalk, diorite).
colorsThe 64-color Pebble palette table plus our house role guidance.
fontsSystem font keys/sizes/usage guidance distilled from DESIGN.md.
wire_conventionsThe reusable delimited wire-string pattern for a Pebble companion protocol.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dbonomo/pebble-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server