probing… | version | spec | tools online
Æ klappy / appbuilder-mcp · FOLIO II · MMXXVI
MCP · ACT II · DISTRIBUTION AS A SERVICE Cloudflare-native MCP server · probing…

Build a scripture app
from a prompt.

A decade of Scripture App Builder craft — compressed into three async tools an AI agent can call. Submit a build job. Poll for status. Cancel if it overruns. Get an installable .apk (or .ipa) back.

POSThttps://appbuilder.klappy.dev/mcp GEThttps://appbuilder.klappy.dev/health
submit_build
project: guahibo-nt
books: 61
audio: 42 hr
target: android · ios
9:24 100%
G
Guahibo · El Nuevo Testamento
Editorial Mundo Hispano · 2026
Marcos · 1 · 1–8

Principio del evangelio

1Tsane bajara apo bitsobinajitsi Jesucristo Dioso pe-aje pe-jubureta-jume.

2Bajaraponi ata janepa-najamatsi profeta Isaías-yajawa, jume:

"Ata pe-jubureta-jume, Pa-tsabia jane bajaraponi…"

3Pa-yawene-najamatsi: ¡Tsajumpajitsia pe-jubureta-tane Diosone…

01:42 / 04:31
Read Listen Search More
build complete
artifact: guahibo-nt.apk
size: 148.2 MB
signed: release · v1
● cache hit — instant
live observation
Server probing…
Version · Spec ·
Latency
Last checked
§ I.The pitch

A thin, opinionless layer over a profoundly opinionated craft.

Scripture App Builder is the SIL-built tool translation teams have used since 2015 to package Paratext projects, MP3 audio, timing files, color schemes, splash screens and signing keys into a real Android or iOS application — shipped to the playstore, sideloaded, or carried into a village on a microSD card. It's free, it's astonishing, and it has hundreds of opinionated settings the agent has no business pretending to know. The MCP server here doesn't pretend to know any of that either. It exposes filesystem-shaped IO, content-addressed job submission, and gets out of the way.

The opinions live next door, in a canon repository served by oddkit. The agent talks to one MCP — this one. The docs(query) tool proxies canon retrieval upstream, so the agent's loop is ask docs · understand · act · observe across a single connection.

i.

For translation teams

Hand a translation agent your Paratext project — any language, any script, any audio bundle — and get a real, signed, installable app back. The agent knows when to ask, what to tweak, and when to stop.

ii.

For agent builders

Three async tools. No domain quiz to pass. Submit a build, poll for status, cancel if it overruns. The server takes care of Gradle, the Android SDK, signing, audio sync, splash variants, and surfacing failures in language a model can reason about.

iii.

For systems people

Cloudflare Worker dispatches via service binding into a Container running SAB + Gradle + Android SDK + aeneas (audio sync). Durable Objects hold per-job state. R2 stores content-addressed .apk / .ipa outputs. SHA-256 of the canonical payload is the cache key.

"I am very grateful for the app of our culture, the New Testament app. I love this because God gives each ethnic group their culture to value." Pastor Arcesio · Guahibo people group · on a Scripture app in his language
§ II.Live demo

Submit a build. Get a real, signed APK.

Both demo payloads are checked-in smoke fixtures from the repo's smoke/ directory and have already been built once, so they cache-hit and return instantly — zero container CPU. The artifact card below is a real R2-served APK.

browser ⇌ appbuilder.klappy.dev/mcp · idle
guahibo-nt cuiba-jonah tewa-luke amharic-psalms
android ios epub
aeneas · auto timing-files none
debug release · signed
Click tools/list to call /mcp live. Build tools are illustrative — the SAB container ships in the next phase.
protocol · JSON-RPC 2.0 / MCP 2025-06-18 identifies as x-appbuilder-client: appbuilder-mcp-homepage
artifact · ready to install ● cache hit — instant
G
Guahibo · NT
com.sil.guahibo.nt · v1.0.4
artifact .apk · release
size 148.2 MB
signed SIL · 2026 cert
sha256 4a17b9c2…
⤓ download from R2
tools advertised by /mcp
probing…
§ III.The canon, live

Ask the docs tool anything.

The MCP server's docs(query) tool searches the project's canon — prose articles, build manifests, app.json schemas, and governance documents that give an agent enough context to drive Scripture App Builder. Type a question; see the actual answer plus the canon URIs that backed it.

docs(query, audience=headless)

Aeneas needs a phonetic profile to align audio to text. For a language with no eSpeak voice, SAB falls back to "sentence-level forced alignment" using a graphemic surrogate (closest eSpeak language) plus the language's own SFM verse markers as anchor points.

The agent should set audio.sync = "sentence" and provide a per-book timings/{book}.{chapter}.csv if greater precision is required. The build will not fail without timings — it will warn and proceed with verse-level highlighting only.

§ IV.The contract

Three tools. One contract.

A signed Android build for a New Testament with audio takes 8–25 minutes. iOS with provisioning takes longer. Synchronous tools collide with every chat-shaped surface in existence. So the protocol is async: submit returns immediately, status is pollable, cancellation is honored.

SPECIMEN PLATE · TOOLS/LIST
i
tool · async

submit_build

Hand it a project, an app.json, a target platform, signing config. Returns a job_id immediately and a predicted artifact URL. Identical payloads cache-hit.

// returns immediately
{
  job_id: "4a17b9c2…",
  payload_hash: "4a17b9c2…",
  cached: true,
  predicted_artifact_url: "…/r2/…/apk",
  predicted_size_mb: 148
}
ii
tool · pollable

get_job_status

Per-stage progress, log tail, error list, gradle warning count. A human_summary string for downstream chat agents.

{
  state: "succeeded",
  stage: 7/7,
  current: "sign-and-zipalign",
  warnings: 3,
  errors: [],
  human_summary:
    "Built. Signed. 148 MB."
}
iii
tool · safety valve

cancel_job

A 25-minute Gradle build needs a kill switch. SIGTERM to the subprocess; partial outputs preserved on disk; state moves to cancelled.

{
  ok: true,
  was_running: false,
  cancelled_at: "2026-05-01T13:24:00Z",
  partial_artifacts: [
    "…/staging/manifest.xml"
  ]
}
cache

SHA-256 of the canonical payload (RFC 8785 JCS) is the only cache key.

No TTL. Identical builds cost zero CPU and return the same R2 artifact. Source of truth, not approximation.

timeout discipline

Per-job timeout in the request, default 25 min for Android, 45 for iOS.

No platform-edge timeout exposed to the caller. The Worker hands off to a Container; the Container does the long work.

progress shape

Per-stage, not per-percent.

Gradle doesn't expose useful per-percent progress for SAB. An honest "stage 4 of 7: synchronizing audio" beats fabricated bars.

// note · the three async tools are the build contract. The full live surface also exposes docs(query) for canon retrieval (proxied to oddkit) and telemetry_public · telemetry_policy · telemetry_schema for transparency (seven tools total). README and page enumerations drift — the deploy is authoritative. Ask tools/list against /mcp for the current surface.

§ V.Live telemetry

No information asymmetry.

Every tool call against appbuilder.klappy.dev writes one structural data point to appbuilder_telemetry. Same data the maintainer sees, queried over MCP from this page in your browser, right now. Identify yourself with an x-appbuilder-client header and you'll appear on the consumer leaderboard below.

tool_call leaderboard · last 30d · appbuilder SUM(_sample_interval) GROUP BY tool_name
  • isubmit_build
  • iiget_job_status
  • iiicancel_job
  • ivdocs
  • vtelemetry_public
  • vitelemetry_policy
  • viitelemetry_schema

// querying telemetry_public…

events · 30d
querying…
unique consumers
querying…
cache hit rate
querying…
avg build · cold
querying…
consumer leaderboard last 30d · this server
  • no consumers yet — set x-appbuilder-client to appear here
§ VI.Architecture

Vodka architecture.

Vodka architecture — coined in the broader klappy canon and applied across oddkit, ptxprint-mcp, and now this server — says each MCP server holds opinions about exactly one concern. The AppBuilder server holds none about translation craft, font resolution, or app design — only about subprocess lifecycle, content-addressed caching, signing-key vault access, and sandboxed file IO. Domain knowledge lives next door, in canon. Agents see one MCP; AppBuilder delegates canon retrieval to oddkit upstream when serving docs().

CALLER

Agent

CLAUDE / GEMMA
GPT / OSS

CONTAINER

SAB Builder

SAB · Gradle
Android SDK · Xcode
aeneas · eSpeak

STATE

DO + R2

per-job state
SHA-256 cache key
signed APK / IPA

VAULT · INTERNAL

Signing keys

Worker secrets
per-project release certs
iOS provisioning

UPSTREAM · INTERNAL

oddkit MCP

canon retrieval
(invisible to agent)

AGENT'S LOOP

ask docs · understand · act · observe

One server. One concern.
Two services in concert —
one of them invisible to the agent.

agent-visible MCP traffic internal · agent never sees
Opinionless server

No app.json validation. No font tables. No splash compositing rules. The server treats every file as opaque text and every subprocess as opaque action.

Content-addressed

Cache keys are SHA-256 hashes (RFC 8785 JCS) of the canonical payload. No TTL. No staleness. Two identical builds share one APK.

Async by design

Cloudflare's 30s Worker timeout collides with 25-minute Gradle builds. The two-step contract is the only honest answer.

Canon-governed

Every architectural decision is encoded in OLDC+H artifacts and stored under canon/. The repo is the spec.

§ VII.Stack

Built on the shoulders of two giants.

edge runtime

Cloudflare

  • WorkersMCP transport, auth, dispatch via service binding
  • ContainersSAB + Gradle + Android SDK + aeneas (standard-3: 2 vCPU, 12 GiB)
  • Durable Objectsper-job state, cancellation, polling
  • R2content-addressed APK / IPA / build-log storage
  • Secretssigning keys, provisioning profiles, vault
  • Analytics Enginepublic usage telemetry · zero asymmetry
distribution craft

SIL & Paratext

  • Scripture App BuilderSIL Global · pinned at v14.0 (released 24 Apr 2026) · headless build mode
  • ParatextUSFM source, project conventions, scripture identifiers
  • aeneasforced audio-text alignment for synchronized highlighting
  • eSpeak NGphonetic surrogate engine for unsupported languages
  • SIL Charis / Andikascript-aware fonts bundled by default
  • BCP 47 + LFFlanguage tag → font + voice resolution
appbuilder & oddkit

Built in canon-governed sessions for translation teams who need the shop floor to move at the speed of a conversation.

repository
endpoints