Owns the product
Question and answer contract, API client, status wording, fonts, branding, attribution treatment, HTTP configuration and platform entry points.
diff --git a/apps/mcp/README.md b/apps/mcp/README.md index 539400d5..b983f99b 100644 --- a/apps/mcp/README.md +++ b/apps/mcp/README.md @@ -4,7 +4,7 @@ A standalone MCP application. `answer_islamic_question` calls the Ansari API and ## How it works -[Explore the interactive walkthrough](docs/show-me-ansari-mcp.html) for the complete question-to-card flow, UI states, code ownership and build process. Its hosted lifecycle addendum compares Alexa+, ChatGPT and Claude from build and deployment through discovery, requests, rendering and teardown. Download the self-contained HTML and open it in a browser; GitHub displays its source. The walkthrough uses synthetic content and makes no live requests. +[Explore the interactive walkthrough](docs/show-me-ansari-mcp.html) for the complete question-to-card flow, UI states, code ownership, build process and why it builds on SAGA. Download the self-contained HTML and open it in a browser; GitHub displays its source. The walkthrough uses synthetic content and makes no live requests. ## Screenshots diff --git a/apps/mcp/docs/show-me-ansari-mcp.html b/apps/mcp/docs/show-me-ansari-mcp.html index 11cdbb0d..3799d81b 100644 --- a/apps/mcp/docs/show-me-ansari-mcp.html +++ b/apps/mcp/docs/show-me-ansari-mcp.html @@ -41,10 +41,10 @@ .tabs{grid-template-columns:repeat(6,minmax(0,1fr));gap:8px;padding:10px;background:var(--greenbg);border:1px solid var(--green);border-top:4px solid var(--green);border-radius:12px}.tabs button{display:flex;align-items:center;gap:8px;white-space:normal;min-height:56px;background:var(--surface);border:1px solid var(--green);color:var(--green);text-align:left;line-height:1.3}.tabnum{font-size:11px;opacity:.65}.tabs button[aria-selected=true]{background:var(--green);color:var(--surface)}.covernote{max-width:880px}.panel{animation:appear .18s ease-out}@keyframes appear{from{opacity:.7}to{opacity:1}}.flowowner{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:12px}.flowowner .tag{font-size:11px}.sourcebox{margin-top:16px;border-top:1px solid var(--line);padding-top:14px}summary{cursor:pointer;font-size:12px;color:var(--green);font-weight:650}details pre{margin-top:12px;max-height:360px;overflow:auto}.sourcepath{font-size:11px;color:var(--muted);overflow-wrap:anywhere}.sourcepath code{font-size:inherit}.map .mapbox{text-align:left;cursor:default}.source-exact{display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;font-size:11px;margin-top:8px;color:var(--muted)}.mapbox:focus-visible{outline:3px solid var(--gold)}.tabhint{font-size:11px;color:var(--muted);display:block;margin-bottom:9px}.sectionlead{max-width:820px;color:var(--muted);font-size:14px;margin-bottom:20px}.scenario-note{background:var(--goldbg);color:var(--gold);font-size:11px;padding:6px 10px;border-radius:5px;margin-bottom:18px}.answerdemo h3{font-size:26px}.answerdemo ul{padding-inline-start:25px}.answerdemo .demobody{min-height:175px}.answerdemo[dir=rtl] .cardheading img{margin-left:0;margin-right:auto}.answerdemo[dir=rtl] .cardheading h3{max-width:none}.answerdemo[dir=rtl] .demoftr{direction:ltr;text-align:left}.demoftr .signature{font-size:14px}.questionbar{display:flex;gap:12px;align-items:flex-start}.questionbar img{width:62px;height:62px;margin-inline-start:auto}.consentbox{background:var(--bluebg);padding:12px;border:1px solid var(--line);border-radius:8px;font:13px/1.5 system-ui;margin-top:14px}.consentbox button{margin-top:8px}.minirow{display:grid;grid-template-columns:1fr 1fr;gap:12px}.minicard{padding:17px;border-radius:9px;background:var(--surface);border:1px solid var(--line)}.minicard p{font-size:13px;color:var(--muted);margin-bottom:0}.minicard h3{font-size:15px}.responsibility{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.responsibility article{padding:20px;background:var(--surface);border:1px solid var(--line);border-radius:10px}.responsibility p{font-size:13px;color:var(--muted)}.controlrow button,.runtime-actions button,.scenario{min-height:36px}.modebuttons{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:18px}.modebuttons button{border:1px solid var(--line);border-radius:7px;background:var(--surface);padding:8px 13px;font-size:12px}.modebuttons button[aria-pressed=true]{border-color:var(--green);background:var(--greenbg);color:var(--green)}.runtime-lane pre{font-size:11px}.runtime-counter strong{font-size:25px}.trace{min-height:116px}.tablewrap{overflow:auto}.lifecards{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}.lifecards article{border:1px solid var(--line);background:var(--surface);border-radius:10px;padding:19px}.lifecards p{color:var(--muted);font-size:13px}.lifecards h3{font-size:15px}.hostproof{display:flex;gap:8px;flex-wrap:wrap;margin:15px 0}.hostproof span{font-size:11px;border:1px solid var(--line);border-radius:6px;padding:6px 9px;background:var(--surface)}.listclean{padding-left:20px;font-size:13px;color:var(--muted)}.listclean li{margin-bottom:8px}.captionline{font-size:12px;color:var(--muted);margin-top:13px}.tabbodyfoot{font-size:12px;color:var(--muted);margin-top:18px}.top h1{max-width:900px}.statusbox{padding:24px;background:var(--surface);border:1px solid var(--line);border-radius:12px}.statusbox h3{font-family:Kitab,Georgia,serif;font-size:25px}.scopegrid{display:grid;grid-template-columns:1fr 1fr;gap:18px}.footerlicense{margin:18px 0;font-size:11px}.footerlicense pre{font-size:10px;max-height:180px;overflow:auto}button[disabled]{opacity:.4;cursor:default}.jump{border:0;background:none;color:var(--green);font:inherit;text-decoration:underline;padding:0}.lede-rule{height:3px;width:40px;background:var(--gold);margin:16px 0}.sourceindex{display:grid;grid-template-columns:1fr 1fr;gap:7px}.sourceindex button{text-align:left;border:1px solid var(--line);border-radius:6px;background:var(--surface);padding:9px;overflow-wrap:anywhere;font-size:11px;color:var(--green)}dialog{width:min(900px,95vw);max-height:86vh;border:1px solid var(--line);border-radius:12px;background:var(--surface);color:var(--ink);padding:24px}dialog::backdrop{background:#07160e80}dialog pre{max-height:65vh;overflow:auto}.dialogtop{display:flex;gap:15px;justify-content:space-between;margin-bottom:12px;align-items:center}.dialogtop button{border:1px solid var(--line);background:var(--bg);color:var(--ink);border-radius:6px;padding:7px 12px} @media(max-width:900px){.tabs{grid-template-columns:repeat(3,1fr)}.responsibility,.lifecards{grid-template-columns:1fr 1fr}.journey{grid-template-columns:220px 1fr}} @media(max-width:600px){.tabs{grid-template-columns:repeat(2,1fr);gap:7px}.tabs button{min-height:46px}.top{flex-wrap:wrap}.theme{margin-left:auto}.top .titleblock{order:2;width:100%}.top>.mark{width:46px}.journey{grid-template-columns:1fr}.minirow,.scopegrid,.responsibility,.lifecards,.sourceindex{grid-template-columns:1fr}.questionbar img{width:48px;height:48px}.steps{grid-template-columns:1fr 1fr}.step{font-size:12px;padding:8px;min-height:44px}.detailgrid{grid-template-columns:1fr}.groupbuttons{grid-template-columns:1fr 1fr}.map{grid-template-columns:1fr}.map>.arrow{display:none}.map>.mapbox:nth-child(5){grid-column:auto}.mapbox{margin-bottom:7px}.runtime-counter{min-width:0}.runtime-counter strong{font-size:23px}.source-exact{line-height:1.6}header,main,footer{padding-left:18px;padding-right:18px}pre{font-size:11px}.detail{padding:18px}} -
+.whycards{grid-template-columns:repeat(3,1fr)}@media(max-width:850px){.whycards{grid-template-columns:1fr}}@media(min-width:951px){.tabs{grid-template-columns:repeat(7,minmax(0,1fr))}}From a question in a conversation to a complete, attributed answer in a branded card. Explore the whole application: its data flow, rendering contract, hosting boundaries and release lifecycle.
The answer service owns the answer. Ansari owns the application. The SAGA stack connects that meaning to an MCP card.
The application supplies the presentation and every user-facing status sentence. The stack supplies the shared rendering and interaction mechanics.
Kitab Regular and Bold are embedded as bytes and loaded through FontFace. Font readiness has its own failure sentence; no device font is silently substituted for an answer.
readingProfile comes from the stack. Ansari maps host colors, reading tokens and direction without changing answer data or applying a second root scale.
The card renders the full answer once. Ansari watches the rendered closing block to style the attribution; the optional framework credit is separate.
The browser imports one public stack. Hosting adapters inject their platform-specific inputs into one fetch application. Explore a module to see its real source and its boundary.
Question and answer contract, API client, status wording, fonts, branding, attribution treatment, HTTP configuration and platform entry points.
Host bridge, held/latest results, Markdown content, document policy, image consent, host links, own sizing and teardown. Server exports own view linkage and request-lifetime attachment.
Tool selection, permissions, discovery/cache behavior, card sandbox and external-navigation experience. The app does not dictate host refresh timing.
The root lockfile is authoritative. Frozen workspace installation and a root-context Docker smoke check protect packaging; they do not establish an actual host connection.
| Setting | Where it belongs | Why it matters |
|---|---|---|
| Upstream URL, client label, optional auth | Node environment / Worker bindings | Same client contract; secrets stay out of source. |
| Allowed Host and Origin | Named deployment environment | Validation matches the selected public endpoint. |
| Dev / Beta / Production | Distinct native Wrangler environment configuration | Select an explicit target and keep release/rollback decisions separate. |
| Application, SDK and resource identity | Built and served card metadata | Inspect the card actually loaded by the host, rather than assuming its cache is current. |
A server release, a host catalog, a request and an embedded view each have a different owner and lifetime. Keeping them distinct explains refreshes, retries and teardown.
Install exact packages, build artifacts, configure a named target, start the application and prepare immutable view bytes.
Register an MCP endpoint and discover its tool and UI association. After a release, verify the host sees the current resource identity.
Send a question, call the API, return one full result and release the per-request server lifetime. Calls remain independent.
Connect the bridge, wait for fonts, present the latest result and apply host context. Teardown releases owned browser resources.
It explains checked application source, using real names and exact excerpts. The interactive diagrams and card examples are synthetic and make no network requests.
0.16.6 as it is committed in this folder.0.7.6 is installed from the public npm registry as one exact release; the root lockfile record its registry integrity.Rendering inside ChatGPT, Claude and Alexa+ is a separate host acceptance. Neither this document nor this repository’s automated checks establish it.
Each path links to its exact source commit on GitHub. The embedded source remains available offline through “Read embedded source”.
A server release, a host catalog, a request and an embedded view each have a different owner and lifetime. Keeping them distinct explains refreshes, retries and teardown.
Install exact packages, build artifacts, configure a named target, start the application and prepare immutable view bytes.
Register an MCP endpoint and discover its tool and UI association. After a release, verify the host sees the current resource identity.
Send a question, call the API, return one full result and release the per-request server lifetime. Calls remain independent.
Connect the bridge, wait for fonts, present the latest result and apply host context. Teardown releases owned browser resources.
It explains checked application source, using real names and exact excerpts. The interactive diagrams and card examples are synthetic and make no network requests.
0.16.6 as it is committed in this folder.0.7.6 is installed from the public npm registry as one exact release; the root lockfile records its registry integrity.Rendering inside ChatGPT, Claude and Alexa+ is a separate host acceptance. Neither this document nor this repository’s automated checks establish it.
Each path links to its exact source commit on GitHub. The embedded source remains available offline through “Read embedded source”.
Ansari could build this card directly on the MCP Apps SDK. Building on SAGA instead means Ansari starts from A2UI’s published protocol and a complete answer component, so its own code deals with answers and branding rather than MCP Apps wiring.
A2UI specifies how component properties bind to data-model paths and how model updates converge. SAGA uses the upstream A2UI processor and React surface rather than a second binding engine. Ansari’s card binds two fields: the contract version and the answer Markdown.
FaithfulCard renders the whole answer: nested lists, quotes, code, mixed-direction text, labelled scrollable tables, and links that open through the host with their hostname shown. It also handles answer replacement and view readiness. Ansari styles its documented surface with its own theme.css.
An MCP App has two ends of one iframe channel: the view’s App and the host’s AppBridge, with mirrored methods. A view can ask with requestTeardown(), but only the host’s AppBridge.teardownResource() tears the view down. The specification describes wire messages, with host and view rules side by side, and names neither class. AppBridge’s host role appears only in the overview diagram and its API reference, so a view author has to work out which half applies. Ansari’s source imports nothing from @modelcontextprotocol/ext-apps.
Rough estimate for the same card built on ext-apps, React and a maintained Markdown renderer:
Tests are not counted. No direct version has been built, so these figures are order-of-magnitude estimates, not measured savings.
In exchange, fixes to parsing, the card and delivery arrive from upstream with their regression tests (saga-a2ui, Apache-2.0).