{"id":"2c3e38b1-f83e-4508-a3b3-1e4f0e97b155","shortId":"HSnMJF","kind":"skill","title":"mdma-integration","tagline":"Integrate MDMA into an application and build features with it — wire up parsing, the runtime store, React rendering, LLM streaming, custom components, prompts, and CI validation. Use this skill when the user asks to add MDMA to an app, build a chat that streams MDMA, author or ma","description":"This skill guides integration of MDMA (Markdown Document with Mounted Applications) into real applications. MDMA is published as a set of composable npm packages under the `@mobile-reality` org — `mdma-spec`, `mdma-parser`, `mdma-runtime`, `mdma-renderer-react`, `mdma-attachables-core`, `mdma-prompt-pack`, `mdma-validator`, `mdma-cli`, `mdma-mcp`. A good integration picks the narrowest set of packages for the task, follows the parse → store → render contract, and uses the authoring and validation tooling rather than rolling its own. The goal is to make it obvious to a developer — or an agent — how to plug MDMA into their stack with minimum ceremony and maximum correctness.\n\nThe user provides an integration task: \"add MDMA to this React chat app\", \"stream MDMA from the LLM and re-render as chunks arrive\", \"write a domain prompt for a clinical intake\", \"validate our MDMA docs in CI\", \"register a custom chart renderer\", \"expose MDMA to our agent via MCP\", or \"migrate our form rendering to MDMA\". They may specify framework (React is first-class), LLM provider, validation rules, or PII constraints.\n\n## Integration Thinking\n\nBefore editing code, establish what \"integrate MDMA\" actually means for this request:\n\n- **Shape of the integration**: One of — *static document rendering* (ship pre-written MDMA, parse+render once), *LLM-streamed chat* (assistant streams MDMA, reparse as chunks arrive, preserve store state across reparses), *CI validation* (lint `*.md` files against the spec), *custom prompt authoring* (build a domain-specific `customPrompt` that feeds `buildSystemPrompt`), *MCP exposure* (let an agent call `get-spec` / `build-system-prompt` / `validate-prompt`), or *custom component* (register a Zod schema + renderer for a non-builtin type). Each has a different package footprint.\n- **Package footprint**: Install only what the integration needs. A chat app needs `mdma-parser` + `mdma-runtime` + `mdma-renderer-react` + `mdma-prompt-pack`. A CI validator needs *only* `mdma-validator`. An agent harness may need *only* `mdma-mcp`. Don't install the full matrix \"just in case\" — the dependency graph is structured so you never have to.\n- **Constraints**: Which components are in scope? Which fields must be `sensitive`? Which environment policies apply (allow/deny actions, redaction mode)? Which LLM provider is streaming? Does the host app already own state management, or will `createDocumentStore` be the source of truth for document state?\n- **Where prompts live**: A domain prompt is a *maintained artifact*, not a one-off string. Decide where it lives (a `prompts/` directory, exported from a package, generated via the CLI prompt builder) and how it's versioned, before writing it.\n\n**CRITICAL**: Integrate with the smallest valid surface area. Prefer the provided `MdmaDocument` + `createDocumentStore` pairing over hand-rolled rendering. Prefer `buildSystemPrompt({ customPrompt })` over concatenating strings yourself. Prefer the `validator` package over ad-hoc regex. The packages encode invariants (binding graph, PII redaction, audit log, policy) that are painful to re-derive.\n\n## MDMA Integration Guidelines\n\nFocus on:\n\n- **Package selection & dependency chain**: The core chain is `spec → parser → runtime → attachables-core → renderer-react`. `prompt-pack`, `validator`, `cli`, `mcp` are leaves that depend only on `spec`. Install the minimum footprint for the task:\n\n  ```bash\n  # Parse + run MDMA documents (headless)\n  npm install @mobile-reality/mdma-parser @mobile-reality/mdma-runtime\n\n  # Add React rendering\n  npm install @mobile-reality/mdma-renderer-react\n\n  # LLM authoring — domain system prompts\n  npm install @mobile-reality/mdma-prompt-pack\n\n  # CI / static analysis\n  npm install @mobile-reality/mdma-validator\n  ```\n\n  Never reinstall peers that are already pulled transitively.\n\n- **Parse → Store → Render**: The contract is non-negotiable. Build a `unified().use(remarkParse).use(remarkMdma)` processor *once* (module-level singleton), feed it markdown, pass the AST to `createDocumentStore`, pass both to `<MdmaDocument>`:\n\n  ```tsx\n  import { unified } from 'unified';\n  import remarkParse from 'remark-parse';\n  import { remarkMdma } from '@mobile-reality/mdma-parser';\n  import { createDocumentStore } from '@mobile-reality/mdma-runtime';\n  import { MdmaDocument } from '@mobile-reality/mdma-renderer-react';\n  import '@mobile-reality/mdma-renderer-react/styles.css';\n  import type { MdmaRoot } from '@mobile-reality/mdma-spec';\n\n  const processor = unified().use(remarkParse).use(remarkMdma); // singleton\n\n  const tree = processor.parse(markdown);\n  const ast = (await processor.run(tree)) as MdmaRoot;\n  const store = createDocumentStore(ast, {\n    documentId: 'my-doc',\n    sessionId: crypto.randomUUID(),\n  });\n\n  return <MdmaDocument ast={ast} store={store} />;\n  ```\n\n- **LLM streaming**: The hard part of chat integrations is that the LLM emits MDMA token-by-token, but you can't re-`createDocumentStore` on every chunk (you'd wipe user state). The right pattern: throttle reparse (~150ms), and on each reparse call `existingStore.updateAst(newAst)` instead of building a fresh store. This preserves `bindings`, focus, and in-flight form edits across reparses.\n\n  ```ts\n  // On each ~150ms tick while streaming:\n  const tree = processor.parse(message.content);\n  const newAst = (await processor.run(tree)) as MdmaRoot;\n  if (existingStore) {\n    existingStore.updateAst(newAst); // preserves user state\n  } else {\n    existingStore = createDocumentStore(newAst, { documentId, sessionId });\n  }\n  ```\n\n  Copy this shape; do not invent a replacement.\n\n- **Prompts — build, don't concatenate**: Use `buildSystemPrompt({ customPrompt })` from `@mobile-reality/mdma-prompt-pack`. It sandwiches your domain rules between the MDMA spec and a reinforcement tail — the ordering matters for model adherence. Your `customPrompt` should *name the domain, allowed components, required fields, sensitive fields, trigger conditions, and business rules*. A vague \"help the user\" prompt produces generic forms; a prompt that encodes the domain produces documents that fit the product. When the prompt grows non-trivial, use the CLI prompt builder (`npx @mobile-reality/mdma-cli`) to generate it structurally, then commit the result as a maintained file.\n\n  ```ts\n  import { buildSystemPrompt } from '@mobile-reality/mdma-prompt-pack';\n\n  const systemPrompt = buildSystemPrompt({\n    customPrompt: `Domain: clinical intake.\n  Allowed components: form, approval-gate, callout.\n  All PII fields (name, email, phone, DOB, MRN) MUST be sensitive: true.\n  Generate MDMA when the user describes a patient visit or symptom.`,\n  });\n  ```\n\n- **Prompt maintenance rules**: Treat every custom prompt as code. Version it. Keep it in a file, not inline. Re-run the evals after changes. When updating, prefer adding a constraint to rewriting the prompt — additive changes preserve prior eval coverage. Name the file after the domain (e.g. `prompts/clinical-intake.ts`), not the author.\n\n- **Validation**: In CI, call `validate(markdown, { autoFix: false })` from `@mobile-reality/mdma-validator` and fail the job on `!result.ok`. For local DX, wire `npx @mobile-reality/mdma-cli validate \"docs/**/*.md\" --fix`. Do not write custom YAML-regex linters — the validator already covers YAML correctness, schema conformance, ID uniqueness, binding resolution, and PII sensitivity.\n\n  ```ts\n  import { validate } from '@mobile-reality/mdma-validator';\n\n  const result = await validate(markdown, { autoFix: false });\n  if (!result.ok) {\n    for (const issue of result.issues) console.error(issue);\n    process.exit(1);\n  }\n  ```\n\n- **Custom components**: To add a non-builtin component type, define a Zod schema, pass it to the parser via `customSchemas`, and register a React renderer via `customizations.components.<type>` on `MdmaDocument`. The same slot overrides built-ins (e.g. swap the default table-fallback chart for a recharts renderer).\n\n  ```tsx\n  import { z } from 'zod';\n  import { ComponentBaseSchema } from '@mobile-reality/mdma-spec';\n\n  const ProgressSchema = ComponentBaseSchema.extend({\n    type: z.literal('progress'),\n    value: z.number().min(0).max(100),\n  });\n\n  const processor = unified()\n    .use(remarkParse)\n    .use(remarkMdma, { customSchemas: new Map([['progress', ProgressSchema]]) });\n\n  <MdmaDocument\n    ast={ast}\n    store={store}\n    customizations={{\n      components: {\n        progress: ProgressRenderer,\n        chart: MyRechartsRenderer, // overrides the built-in table fallback\n      },\n    }}\n  />;\n  ```\n\n- **Actions & events**: Subscribe to the event bus via `store.getEventBus().onAny(handler)` to observe user actions without coupling to React state. Dispatch programmatically with `store.dispatch({ type: 'FIELD_CHANGED' | 'ACTION_TRIGGERED' | ... })`. Multi-step flows listen for `ACTION_TRIGGERED` and advance the conversation (e.g. inject the next assistant message when a button fires).\n\n- **Agent integrations via MCP**: When an agent (Claude Desktop, Cursor, a custom harness) needs to produce MDMA, wire `@mobile-reality/mdma-mcp` instead of bundling prompts into the agent. Its tools — `get-spec`, `get-prompt`, `build-system-prompt`, `validate-prompt`, `list-packages` — collapse the discovery phase so the agent gets the spec, packages, and ready-made prompts in a handful of tool calls. The integration is three lines of JSON in the agent's MCP config:\n\n  ```json\n  {\n    \"mcpServers\": {\n      \"mdma\": { \"command\": \"npx\", \"args\": [\"@mobile-reality/mdma-mcp\"] }\n    }\n  }\n  ```\n\n- **Blueprints as starting points**: The upstream MDMA repository ships five production-shaped blueprints (change-management, clinical-ops, customer-escalation, incident-triage, kyc-case). When scaffolding a new domain, copy the nearest blueprint from the upstream repo and adapt — don't start from a blank file. They encode real component mixes, field choices, and flow shapes.\n\nNEVER ship these integration anti-patterns:\n\n- Re-creating `createDocumentStore(ast)` on every streamed chunk instead of calling `store.updateAst(ast)` — wipes user input mid-typing\n- Rebuilding the `unified` processor on every render — it's expensive; make it a module-level singleton\n- Concatenating system prompt strings by hand instead of calling `buildSystemPrompt` — breaks the spec + reinforcement sandwich the model relies on\n- Writing regex-based validators instead of calling `validate()` — misses binding-graph and schema-conformance issues the package already catches\n- Installing every `@mobile-reality/mdma-*` package when the integration only needs two or three\n- Copy-pasting the MDMA spec into your system prompt instead of importing `MDMA_AUTHOR_PROMPT` / calling `buildSystemPrompt` — the spec evolves with the package\n- Registering custom components only as renderers, without a matching Zod schema — the parser will reject the block or silently drop it\n- Letting sensitive fields through unmarked because the prompt didn't require them — add `\"All PII fields must be marked sensitive\"` to every domain prompt by default\n- Hardcoding a chart library into a fork of `renderer-react` — use `customizations.components.chart` instead\n- Treating the generated prompt from `mdma-cli` as ephemeral — it's the domain spec; commit it\n\nInterpret pragmatically and pick the shallowest integration that satisfies the requirement. A one-page demo that renders a static MDMA file needs three imports and ten lines. A production chat with streaming, custom components, and CI validation needs the full stack. Don't converge on a default kitchen-sink wiring across integrations.\n\n**IMPORTANT**: Match integration depth to the app's vision. A static document viewer wants *parser + renderer-react* and nothing else — no store events, no prompt pack, no validator. A domain chat platform wants the full sequence: streaming reparse, domain `customPrompt` committed to the repo, custom components with Zod + renderer, CI validation, and MCP exposure for the agent author. Elegance comes from executing the chosen depth well, not from using every package in every app.\n\nRemember: MDMA's whole point is that the packages already solve the hard parts — binding graphs, audit logs, PII redaction, policy, prompt assembly, validation. A good integration trusts them and composes them; a bad integration reinvents them. Compose, don't reinvent.","tags":["mdma","integration","mobilereality","agent-skills","ai-agents","claude-skill","generative-ui","interactive-markdown","llm","mcp","mcp-server","model-context-protocol"],"capabilities":["skill","source-mobilereality","skill-mdma-integration","topic-agent-skills","topic-ai-agents","topic-claude-skill","topic-generative-ui","topic-interactive-markdown","topic-llm","topic-mcp","topic-mcp-server","topic-mdma","topic-model-context-protocol","topic-react","topic-remark-plugin"],"categories":["mdma"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/MobileReality/mdma/mdma-integration","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add MobileReality/mdma","source_repo":"https://github.com/MobileReality/mdma","install_from":"skills.sh"}},"qualityScore":"0.455","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 11 github stars · SKILL.md body (12,399 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-24T07:03:22.825Z","embedding":null,"createdAt":"2026-04-23T13:04:04.129Z","updatedAt":"2026-04-24T07:03:22.825Z","lastSeenAt":"2026-04-24T07:03:22.825Z","tsv":"'/mdma-':1528 '/mdma-cli':940,1077 '/mdma-mcp':1306,1376 '/mdma-parser':597,689 '/mdma-prompt-pack':621,866,960 '/mdma-renderer-react':610,703 '/mdma-renderer-react/styles.css':708 '/mdma-runtime':601,696 '/mdma-spec':716,1191 '/mdma-validator':630,1062,1112 '0':1201 '1':1130 '100':1203 '150ms':789,818 'across':287,813,1692 'action':423,1234,1248,1261,1269 'actual':251 'ad':523,1026 'ad-hoc':522 'adapt':1420 'add':38,174,602,1134,1595 'addit':1033 'adher':885 'advanc':1272 'agent':154,216,313,380,1285,1291,1313,1338,1363,1751 'allow':892,968 'allow/deny':422 'alreadi':435,636,1092,1521,1778 'analysi':624 'anti':1443 'anti-pattern':1442 'app':42,180,355,434,1700,1768 'appli':421 'applic':8,62,65 'approv':972 'approval-g':971 'area':498 'arg':1372 'arriv':192,283 'artifact':459 'ask':36 'assembl':1791 'assist':277,1279 'ast':666,730,739,748,749,1217,1218,1449,1458 'attach':97,561 'attachables-cor':560 'audit':534,1785 'author':49,133,299,612,1049,1552,1752 'autofix':1056,1118 'await':731,828,1115 'bad':1802 'base':1504 'bash':586 'bind':530,805,1100,1512,1783 'binding-graph':1511 'blank':1426 'block':1578 'blueprint':1377,1390,1414 'break':1492 'build':10,43,300,319,648,799,855,1323 'build-system-prompt':318,1322 'builder':482,935 'buildsystemprompt':308,511,860,955,963,1491,1555 'built':1166,1230 'built-in':1165,1229 'builtin':337,1138 'bundl':1309 'bus':1240 'busi':901 'button':1283 'call':314,794,1053,1353,1456,1490,1508,1554 'callout':974 'case':396,1405 'catch':1522 'ceremoni':164 'chain':552,555 'chang':1022,1034,1260,1392 'change-manag':1391 'chart':210,1175,1225,1611 'chat':45,179,276,354,758,1670,1725 'choic':1434 'chosen':1758 'chunk':191,282,778,1453 'ci':28,206,289,372,622,1052,1676,1744 'class':234 'claud':1292 'cli':108,480,570,933,1630 'clinic':199,966,1395 'clinical-op':1394 'code':246,1006 'collaps':1332 'come':1754 'command':1370 'commit':946,1638,1735 'compon':25,327,409,893,969,1132,1139,1222,1431,1564,1674,1740 'componentbaseschema':1186 'componentbaseschema.extend':1194 'compos':73,1799,1806 'concaten':514,858,1482 'condit':899 'config':1366 'conform':1097,1517 'console.error':1127 'const':717,725,729,736,822,826,961,1113,1123,1192,1204 'constraint':241,407,1028 'contract':129,643 'converg':1684 'convers':1274 'copi':846,1411,1539 'copy-past':1538 'core':98,554,562 'correct':167,1095 'coupl':1250 'cover':1093 'coverag':1038 'creat':1447 'createdocumentstor':441,503,668,691,738,775,842,1448 'critic':491 'crypto.randomuuid':745 'cursor':1294 'custom':24,209,297,326,1003,1085,1131,1221,1296,1398,1563,1673,1739 'customer-escal':1397 'customizations.components':1158 'customizations.components.chart':1621 'customprompt':305,512,861,887,964,1734 'customschema':1151,1211 'd':780 'decid':466 'default':1171,1608,1687 'defin':1141 'demo':1655 'depend':398,551,575 'depth':1697,1759 'deriv':543 'describ':992 'desktop':1293 'develop':151 'didn':1591 'differ':342 'directori':472 'discoveri':1334 'dispatch':1254 'dob':981 'doc':204,743,1079 'document':59,263,448,590,919,1705 'documentid':740,844 'domain':195,303,454,613,870,891,917,965,1044,1410,1605,1636,1724,1733 'domain-specif':302 'drop':1581 'dx':1071 'e.g':1045,1168,1275 'edit':245,812 'eleg':1753 'els':840,1714 'email':979 'emit':764 'encod':528,915,1429 'environ':419 'ephemer':1632 'escal':1399 'establish':247 'eval':1020,1037 'event':1235,1239,1717 'everi':777,1002,1451,1470,1524,1604,1764,1767 'evolv':1558 'execut':1756 'existingstor':834,841 'existingstore.updateast':795,835 'expens':1474 'export':473 'expos':212 'exposur':310,1748 'fail':1064 'fallback':1174,1233 'fals':1057,1119 'featur':11 'feed':307,661 'field':414,895,897,977,1259,1433,1585,1598 'file':293,952,1013,1041,1427,1661 'fire':1284 'first':233 'first-class':232 'fit':921 'five':1386 'fix':1081 'flight':810 'flow':1266,1436 'focus':547,806 'follow':124 'footprint':344,346,582 'fork':1615 'form':222,811,911,970 'framework':229 'fresh':801 'full':392,1680,1729 'gate':973 'generat':477,942,987,1625 'generic':910 'get':316,1317,1320,1339 'get-prompt':1319 'get-spec':315,1316 'goal':143 'good':113,1794 'graph':399,531,1513,1784 'grow':927 'guid':54 'guidelin':546 'hand':507,1350,1487 'hand-rol':506 'handler':1244 'har':381,1297 'hard':755,1781 'hardcod':1609 'headless':591 'help':905 'hoc':524 'host':433 'id':1098 'import':673,677,683,690,697,704,709,954,1106,1181,1185,1550,1664,1694 'in':1167 'in-flight':808 'incid':1401 'incident-triag':1400 'inject':1276 'inlin':1015 'input':1461 'instal':347,390,579,593,606,617,626,1523 'instead':797,1307,1454,1488,1506,1548,1622 'intak':200,967 'integr':3,4,55,114,172,242,249,259,351,492,545,759,1286,1355,1441,1532,1646,1693,1696,1795,1803 'interpret':1640 'invari':529 'invent':851 'issu':1124,1128,1518 'job':1066 'json':1360,1367 'keep':1009 'kitchen':1689 'kitchen-sink':1688 'kyc':1404 'kyc-cas':1403 'leav':573 'let':311,1583 'level':659,1480 'librari':1612 'line':1358,1667 'lint':291 'linter':1089 'list':1330 'list-packag':1329 'listen':1267 'live':452,469 'llm':22,185,235,274,427,611,752,763 'llm-stream':273 'local':1070 'log':535,1786 'ma':51 'made':1346 'maintain':458,951 'mainten':999 'make':146,1475 'manag':438,1393 'map':1213 'mark':1601 'markdown':58,663,728,1055,1117 'match':1570,1695 'matrix':393 'matter':882 'max':1202 'maximum':166 'may':227,382 'mcp':111,218,309,387,571,1288,1365,1747 'mcpserver':1368 'md':292,1080 'mdma':2,5,39,48,57,66,83,86,89,92,96,100,104,107,110,158,175,182,203,213,225,250,269,279,358,361,364,368,377,386,544,589,765,874,988,1301,1369,1383,1542,1551,1629,1660,1770 'mdma-attachables-cor':95 'mdma-c':106,1628 'mdma-integr':1 'mdma-mcp':109,385 'mdma-pars':85,357 'mdma-prompt-pack':99,367 'mdma-renderer-react':91,363 'mdma-runtim':88,360 'mdma-spec':82 'mdma-valid':103,376 'mdmadocu':502,698,747,1160,1216 'mdmaroot':711,735,832 'mean':252 'messag':1280 'message.content':825 'mid':1463 'mid-typ':1462 'migrat':220 'min':1200 'minimum':163,581 'miss':1510 'mix':1432 'mobil':79,595,599,608,619,628,687,694,701,706,714,864,938,958,1060,1075,1110,1189,1304,1374,1526 'mobile-r':78,594,598,607,618,627,686,693,700,705,713,863,937,957,1059,1074,1109,1188,1303,1373,1525 'mode':425 'model':884,1498 'modul':658,1479 'module-level':657,1478 'mount':61 'mrn':982 'multi':1264 'multi-step':1263 'must':415,983,1599 'my-doc':741 'myrechartsrender':1226 'name':889,978,1039 'narrowest':117 'nearest':1413 'need':352,356,374,383,1298,1534,1662,1678 'negoti':647 'never':404,631,1438 'new':1212,1409 'newast':796,827,836,843 'next':1278 'non':336,646,929,1137 'non-builtin':335,1136 'non-negoti':645 'non-trivi':928 'noth':1713 'npm':74,592,605,616,625 'npx':936,1073,1371 'observ':1246 'obvious':148 'onani':1243 'one':260,463,1653 'one-off':462 'one-pag':1652 'op':1396 'order':881 'org':81 'overrid':1164,1227 'pack':102,370,568,1720 'packag':75,120,343,345,476,520,527,549,1331,1342,1520,1529,1561,1765,1777 'page':1654 'pain':539 'pair':504 'pars':16,126,270,587,639,682 'parser':87,359,558,1149,1574,1708 'part':756,1782 'pass':664,669,1145 'past':1540 'patient':994 'pattern':786,1444 'peer':633 'phase':1335 'phone':980 'pick':115,1643 'pii':240,532,976,1103,1597,1787 'platform':1726 'plug':157 'point':1380,1773 'polici':420,536,1789 'pragmat':1641 'pre':267 'pre-written':266 'prefer':499,510,517,1025 'preserv':284,804,837,1035 'prior':1036 'process.exit':1129 'processor':655,718,1205,1468 'processor.parse':727,824 'processor.run':732,829 'produc':909,918,1300 'product':923,1388,1669 'production-shap':1387 'programmat':1255 'progress':1197,1214,1223 'progressrender':1224 'progressschema':1193,1215 'prompt':26,101,196,298,321,324,369,451,455,471,481,567,615,854,908,913,926,934,998,1004,1032,1310,1321,1325,1328,1347,1484,1547,1553,1590,1606,1626,1719,1790 'prompt-pack':566 'prompts/clinical-intake.ts':1046 'provid':170,236,428,501 'publish':68 'pull':637 'rather':137 're':188,542,774,1017,1446 're-creat':1445 're-der':541 're-rend':187 're-run':1016 'react':20,94,178,230,366,565,603,1155,1252,1619,1711 'readi':1345 'ready-mad':1344 'real':64,1430 'realiti':80,596,600,609,620,629,688,695,702,707,715,865,939,959,1061,1076,1111,1190,1305,1375,1527 'rebuild':1465 'rechart':1178 'redact':424,533,1788 'regex':525,1088,1503 'regex-bas':1502 'regist':207,328,1153,1562 'reinforc':878,1495 'reinstal':632 'reinvent':1804,1809 'reject':1576 'reli':1499 'remark':681 'remark-pars':680 'remarkmdma':654,684,723,1210 'remarkpars':652,678,721,1208 'rememb':1769 'render':21,93,128,189,211,223,264,271,332,365,509,564,604,641,1156,1179,1471,1567,1618,1657,1710,1743 'renderer-react':563,1617,1709 'repars':280,288,788,793,814,1732 'replac':853 'repo':1418,1738 'repositori':1384 'request':255 'requir':894,1593,1650 'resolut':1101 'result':948,1114 'result.issues':1126 'result.ok':1068,1121 'return':746 'rewrit':1030 'right':785 'roll':139,508 'rule':238,871,902,1000 'run':588,1018 'runtim':18,90,362,559 'sandwich':868,1496 'satisfi':1648 'scaffold':1407 'schema':331,1096,1144,1516,1572 'schema-conform':1515 'scope':412 'select':550 'sensit':417,896,985,1104,1584,1602 'sequenc':1730 'sessionid':744,845 'set':71,118 'shallowest':1645 'shape':256,848,1389,1437 'ship':265,1385,1439 'silent':1580 'singleton':660,724,1481 'sink':1690 'skill':32,53 'skill-mdma-integration' 'slot':1163 'smallest':495 'solv':1779 'sourc':444 'source-mobilereality' 'spec':84,296,317,557,578,875,1318,1341,1494,1543,1557,1637 'specif':304 'specifi':228 'stack':161,1681 'start':1379,1423 'state':286,437,449,783,839,1253 'static':262,623,1659,1704 'step':1265 'store':19,127,285,640,737,750,751,802,1219,1220,1716 'store.dispatch':1257 'store.geteventbus':1242 'store.updateast':1457 'stream':23,47,181,275,278,430,753,821,1452,1672,1731 'string':465,515,1485 'structur':401,944 'subscrib':1236 'surfac':497 'swap':1169 'symptom':997 'system':320,614,1324,1483,1546 'systemprompt':962 'tabl':1173,1232 'table-fallback':1172 'tail':879 'task':123,173,585 'ten':1666 'think':243 'three':1357,1537,1663 'throttl':787 'tick':819 'token':767,769 'token-by-token':766 'tool':136,1315,1352 'topic-agent-skills' 'topic-ai-agents' 'topic-claude-skill' 'topic-generative-ui' 'topic-interactive-markdown' 'topic-llm' 'topic-mcp' 'topic-mcp-server' 'topic-mdma' 'topic-model-context-protocol' 'topic-react' 'topic-remark-plugin' 'transit':638 'treat':1001,1623 'tree':726,733,823,830 'triag':1402 'trigger':898,1262,1270 'trivial':930 'true':986 'trust':1796 'truth':446 'ts':815,953,1105 'tsx':672,1180 'two':1535 'type':338,710,1140,1195,1258,1464 'unifi':650,674,676,719,1206,1467 'uniqu':1099 'unmark':1587 'updat':1024 'upstream':1382,1417 'use':30,131,651,653,720,722,859,931,1207,1209,1620,1763 'user':35,169,782,838,907,991,1247,1460 'vagu':904 'valid':29,105,135,201,237,290,323,373,378,496,519,569,1050,1054,1078,1091,1107,1116,1327,1505,1509,1677,1722,1745,1792 'validate-prompt':322,1326 'valu':1198 'version':487,1007 'via':217,478,1150,1157,1241,1287 'viewer':1706 'vision':1702 'visit':995 'want':1707,1727 'well':1760 'whole':1772 'wipe':781,1459 'wire':14,1072,1302,1691 'without':1249,1568 'write':193,489,1084,1501 'written':268 'yaml':1087,1094 'yaml-regex':1086 'z':1182 'z.literal':1196 'z.number':1199 'zod':330,1143,1184,1571,1742","prices":[{"id":"50e5121e-6ba5-4034-80f8-9f99dddb57d4","listingId":"2c3e38b1-f83e-4508-a3b3-1e4f0e97b155","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"MobileReality","category":"mdma","install_from":"skills.sh"},"createdAt":"2026-04-23T13:04:04.129Z"}],"sources":[{"listingId":"2c3e38b1-f83e-4508-a3b3-1e4f0e97b155","source":"github","sourceId":"MobileReality/mdma/mdma-integration","sourceUrl":"https://github.com/MobileReality/mdma/tree/main/skills/mdma-integration","isPrimary":false,"firstSeenAt":"2026-04-23T13:04:04.129Z","lastSeenAt":"2026-04-24T07:03:22.825Z"}],"details":{"listingId":"2c3e38b1-f83e-4508-a3b3-1e4f0e97b155","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"MobileReality","slug":"mdma-integration","github":{"repo":"MobileReality/mdma","stars":11,"topics":["agent-skills","ai-agents","claude-skill","generative-ui","interactive-markdown","llm","mcp","mcp-server","mdma","model-context-protocol","react","remark-plugin","typescript"],"license":"mit","html_url":"https://github.com/MobileReality/mdma","pushed_at":"2026-04-21T11:52:19Z","description":"Interactive documents from Markdown. Extends MD with forms, approvals, webhooks, and more — built for next gen apps","skill_md_sha":"d4cb2d5a49111b9863c92fe752e0d0c07a226bc2","skill_md_path":"skills/mdma-integration/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/MobileReality/mdma/tree/main/skills/mdma-integration"},"layout":"multi","source":"github","category":"mdma","frontmatter":{"name":"mdma-integration","license":"MIT","description":"Integrate MDMA into an application and build features with it — wire up parsing, the runtime store, React rendering, LLM streaming, custom components, prompts, and CI validation. Use this skill when the user asks to add MDMA to an app, build a chat that streams MDMA, author or maintain a custom prompt, validate MDMA documents, register a custom component, or expose MDMA to an agent via MCP. Generates focused, correct wiring that uses the right packages for the job instead of reinventing them."},"skills_sh_url":"https://skills.sh/MobileReality/mdma/mdma-integration"},"updatedAt":"2026-04-24T07:03:22.825Z"}}