Commit graph ext-apps/src
Author SHA1 Message Date
Hryhorii (Greg) Avcharov
38e1f7af14
refactor: remove unnecessary type assertions (#471) 2026-03-06 14:35:04 +00:00
Hryhorii (Greg) Avcharov
19fe73a08a
Replace deprecated RESOURCE_URI_META_KEY usage with modern format (#457) 2026-03-06 14:32:04 +00:00
Olivier Chafik
ef8fc6e2f0
fix: make listServerResources() params optional (#528)
Follow-up to #470. Matches MCP SDK Client.listResources(params?) signature
so callers can omit the empty {} for the common case.

Also reflows a line in app-bridge.test.ts that prettier flagged.
2026-03-06 14:30:36 +00:00
Hryhorii (Greg) Avcharov
4f9a7ebc74
feat: add readServerResource() and listServerResources() api to App (#470)
* feat: add readServerResource() and listServerResources() api to App class

* test: add listServerResources and readServerResource integration tests
2026-03-06 14:20:45 +00:00
Suriya Prakash
0af4cdc305
fix: remove duplicate --color-text-ghost from McpUiStyleVariableKey (#523) 2026-03-06 13:46:04 +00:00
Mel Ludowise
26928b8622
Fix autoResize reporting viewport height when content is taller (#525)
fit-content clamps to the containing block's available size. For <html>,
that's the iframe viewport, so when content exceeds the viewport height
the SDK reported the viewport height instead of the true content height,
causing internal scrolling instead of iframe growth.

max-content has no available-space constraint and correctly reports the
intrinsic content height in both directions (shrink and grow). Width
stays fit-content to preserve responsive wrapping.
2026-03-06 13:30:13 +00:00
Anton Pidkuiko MacBook
9340bd800e
test: add App → AppBridge integration test for downloadFile 2026-02-24 16:57:18 +00:00
Anton Pidkuiko MacBook
3757271641
refactor: use MCP resource types for ui/download-file params
Replace custom {filename, content, mimeType, encoding} params with
standard MCP resource types: EmbeddedResource for inline content and
ResourceLink for host-resolved references.

New params shape:
  params: { contents: (EmbeddedResource | ResourceLink)[] }

This reuses existing MCP primitives instead of inventing new ones,
and enables hosts to show resource 'bubbles' or resolve ResourceLink
URIs via resources/read on the MCP server.
2026-02-20 12:00:35 +00:00
Anton Pidkuiko MacBook
494c73e7ca
feat: add ui/download-file method for host-mediated file downloads
Add a new ui/download-file JSON-RPC request that allows MCP App views to
request file downloads through the host. Since MCP Apps run in sandboxed
iframes where direct downloads are blocked (allow-downloads not set),
this provides a host-mediated mechanism for file exports.

Spec changes (draft):
- Add ui/download-file request to Requests (View → Host) section
- Add downloadFile capability to HostCapabilities
- Document host behavior requirements (confirmation dialog, filename
  sanitization, base64 decoding, size limits)

SDK changes:
- Add McpUiDownloadFileRequest/Result interfaces to spec.types.ts
- Add downloadFile() method to App class
- Add ondownloadfile setter to AppBridge class
- Add DOWNLOAD_FILE_METHOD constant
- Generate Zod schemas

Example:
- Add download demo to integration-server (exports JSON with server time)
- Capability check: only shows download button when host advertises
  downloadFile capability

Based on developer feedback requesting file export capabilities for
visualization tools, document editors, and data analysis apps.
2026-02-19 21:25:48 +00:00
Olivier Chafik
f615123711
Add double-connect guard to prevent protocol message handling errors (#450)
* fix: guard against double-connect in App and AppBridge (#429)

Calling connect() twice on the same transport instance caused the MCP
SDK's Protocol class to chain onmessage handlers, so each incoming
message was processed twice. This made incoming responses get consumed
by the first processing (resolving the handler) and then trigger a
spurious "Received a response for an unknown message ID" error on the
second processing pass, since the handler was already removed from the
response map.

Add an explicit guard in both App.connect() and AppBridge.connect() that
throws if the instance is already connected. This converts the silent
message-corruption into a clear, actionable error and prevents
downstream confusion.

Adds three regression tests:
- AppBridge.connect() throws when already connected
- App.connect() throws when already connected
- Demonstrates the double-processing root cause and verifies it is fixed

Fixes #429

https://claude.ai/code/session_01XU3FW1TpjBkyRbkBUH5gqR

* test: replace redundant regression test with cleaner same-transport guard check

The previous third test in "double-connect guard" never actually attempted
a double-connect — it created fresh instances and verified normal operation,
which every other test already covers. The stray bridge.onupdatemodelcontext
and bridgeTransport.close() at the top were leftover noise.

Replace it with a focused test that verifies the guard fires even when
the caller passes the *same* transport object (not just a different one),
which is the exact scenario described in #429.

https://claude.ai/code/session_01XU3FW1TpjBkyRbkBUH5gqR

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-17 18:15:24 +00:00
Olivier Chafik
666952980f
feat(app): throw helpful error when callServerTool is called with a string (#449)
Users frequently call callServerTool("tool_name", args) instead of the
correct callServerTool({ name: "tool_name", arguments: args }), resulting
in a silent/confusing failure. Detect this and throw immediately with
a message that shows the correct call shape.

Also fixes the incorrect example in examples/pdf-server/README.md that
demonstrated this same wrong usage pattern.

Fixes #386

https://claude.ai/code/session_01GqAyN4Ux7svWoU2HqsSLZF

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-13 21:05:21 +00:00
Olivier Chafik
fd8cc978d4
fix(message-transport): only ignore messages that lack jsonrpc: "2.0" (#448)
Tighten the parse-failure handler: silently ignore postMessage frames
where event.data?.jsonrpc !== "2.0" (i.e. not JSON-RPC at all — null,
undefined, a primitive, or an object from the host environment that
doesn't carry the jsonrpc field). Messages that do carry jsonrpc: "2.0"
but are otherwise malformed still surface via onerror so genuine protocol
errors aren't swallowed.

https://claude.ai/code/session_01DaJpUtSJf4hA7tnu3nJz8s

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-12 15:28:32 +00:00
Olivier Chafik
bcfffb6585
Clarify spec and SDK: accept UIResourceMeta in both resources/list and resources/read (#410)
* Clarify spec and SDK: accept UIResourceMeta in both resources/list and resources/read

The spec defines UIResource with _meta.ui, implicitly as an extension of the Resource type (resources/list), but examples and practice place _meta.ui on TextResourceContents (resources/read). The registerAppResource helper accepts _meta.ui in its config (which ends up in resources/list), but examples only return said _meta.ui from resources/read — and current hosts might be just ignoring it.

This change:
- Adds a 'Metadata Location' subsection to the draft spec explicitly stating that _meta.ui is valid on both the resource listing entry AND the content item, with content-item taking precedence.
- Updates the spec example to show _meta on the resource declaration (resources/list).
- Updates the CSP construction example to reference both locations.
- Clarifies McpUiAppResourceConfig JSDoc: _meta here appears in resources/list and serves as a listing-level fallback for when content items omit _meta.ui.
- Fixes the map-server example comment that incorrectly stated _meta must only be on the content item.

* Add McpUiReadResourceResult type for UI metadata in resources/read

* basic-host: support UIResourceMeta fallback from resources/list

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-04 14:26:09 +00:00
Jonathan Hefner
2dd56c3dce
Merge pull request #422 from jonathanhefner/everything-is-external
Replace "external" with "network" in CSP documentation
2026-02-03 10:29:52 -06:00
Anton Pidkuiko
398f5b4e4a
Merge pull request #294 from matteo8p/create-helper-functions-tool-visibility
Add `isToolVisibilityModelOnly` and `isToolVisibilityAppOnly` helper functions
2026-02-02 23:15:46 +00:00
Jonathan Hefner
c39b40e7c8
Replace "external" with "network" in CSP documentation
The term "external" is misleading for MCP Apps because developers
typically interpret it as "third-party." However, MCP App HTML runs in
a sandboxed iframe with no same-origin server, so *all* origins must be
declared—including where your own bundled JS/CSS is served from. Using
"network" instead avoids this confusion and aligns with the detailed
explanations in `patterns.md` and `spec.types.ts`.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 10:50:06 -06:00
Jonathan Hefner
13b6d06399
Add CSP and CORS section to patterns docs
Adds a new section to the patterns guide explaining how to configure
Content Security Policy and CORS for MCP Apps that make network requests:

- CSP via `_meta.ui.csp` controls browser-side permissions (`connectDomains`,
  `resourceDomains`)
- CORS via `_meta.ui.domain` provides a stable origin for API servers to
  allowlist

Includes a type-checked example showing `computeAppDomainForClaude()` helper
that hashes an MCP server URL to create a stable `*.claudemcpcontent.com`
subdomain. Also adds `@see` links to `McpUiResourceMeta` and `McpUiResourceCsp`
in `registerAppResource` JSDoc.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 14:33:57 -06:00
Jonathan Hefner
5c4f4969b1
Merge pull request #406 from jonathanhefner/extract-getUiCapability-example
Extract `getUiCapability` example to type-checked examples file
2026-01-30 13:52:31 -06:00
Jonathan Hefner
c02eb4d006
Improve documentation for CSP and permissions types
Add detailed JSDoc comments to `McpUiResourceCsp`, `McpUiResourcePermissions`,
and `McpUiResourceMeta` interfaces:

- Document CSP directive mappings for `connectDomains`, `resourceDomains`,
  `frameDomains`, and `baseUriDomains`
- Add usage examples showing typical domain patterns
- Clarify Permission Policy mappings for `camera`, `microphone`, `geolocation`,
  and `clipboardWrite`
- Explain `domain` field's host-dependent behavior with concrete examples
- Document `prefersBorder` semantics including true/false/omitted behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-30 11:44:31 -06:00
Jonathan Hefner
52cc193e1b
Extract getUiCapability example to type-checked examples file
Move the inline example from the `getUiCapability()` JSDoc to
`index.examples.ts` for type checking, following the pattern used
by other examples in the codebase.

The example now uses the correct MCP SDK API:
- `server.server.oninitialized` callback for post-initialization hook
- `server.server.getClientCapabilities()` to retrieve capabilities

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 19:55:33 -06:00
Jonathan Hefner
c6c2428e0b
Improve patterns guide with concrete examples and safe area insets
- Rename "host styling" section to "host context" and add safe area
  insets handling
- Replace abstract `renderLoadingUI`/`renderFinalUI` example with
  concrete code preview pattern for `ontoolinputpartial`
- Rename callback parameter `params` → `ctx` for clarity across all
  `onhostcontextchanged` handlers
- Add CSS snippet for fullscreen border-radius handling
- Expand display mode example to show `availableDisplayModes` check
- Fix minor typos and wording consistency

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 17:32:41 -06:00
Konstantin Konstantinov
47a5787ec3
return registered app resource from method (#370) 2026-01-27 09:58:19 +00:00
Olivier Chafik
298e884ec3
chore: stable spec release 2026-01-26 and SDK v1.0.0 (#362)
* chore: add stable spec release 2026-01-26

- Use git mv to copy specification from draft to specification/2026-01-26/apps.mdx (preserves history)
- Update status from 'Draft' to 'Stable (2026-01-26)'
- Add specification version table to README
- Update Resources section with links to both stable and draft specs

* chore: bump version to 1.0.0

- Update main package version from 0.4.2 to 1.0.0
- Update all example package versions to 1.0.0
- Regenerate package-lock.json

* prettier

* chore: align protocol version with spec release 2026-01-26

- Add 'Protocol Version: 2026-01-26' to spec header
- Update LATEST_PROTOCOL_VERSION from '2025-11-21' to '2026-01-26'
- Update spec examples to use '2026-01-26' protocol version
- Add '2025-11-21' to SUPPORTED_PROTOCOL_VERSIONS for backwards compatibility

* chore: update spec references to stable 2026-01-26

- Update typedoc.config.mjs navigation link
- Update docs/overview.md spec links (10 occurrences)
- Update plugins/mcp-apps/skills/create-mcp-app/SKILL.md spec link
- Update src/spec.types.ts @see links
- Update AGENTS.md spec path
- Regenerate src/generated/schema.ts with updated links

* chore: simplify versioning - first stable release

- Remove backwards compatibility version (2025-11-21) - this is the first stable release
- Remove redundant 'Protocol Version' header - spec version IS the protocol version

* chore: add history reference comment to stable spec
2026-01-26 17:31:33 +00:00
martinalong
89f58bf555
[MCP Apps] Add appCapabilities.availableDisplayModes documentation to spec (#331)
* Add appCapabilities.availableDisplayModes documentation to spec

Document the availableDisplayModes field in McpUiAppCapabilities that allows
apps to declare which display modes they support. This enables hosts to
compute the intersection of host and app capabilities and only offer
appropriate display mode controls.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address PR review feedback

- Change "Guest UI" to "View" terminology
- Add "View" prefix to availableDisplayModes heading for disambiguation
- Remove intersection logic - host only checks its own supported modes
- Remove assumption that apps must support inline mode
- Simplify host behavior to honor/reject based on its own capabilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Add appCapabilities.availableDisplayModes to types

- Add `availableDisplayModes` field to `McpUiAppCapabilities` so apps can
  declare which display modes they support
- Change `HostContext.availableDisplayModes` type from `string[]` to
  `McpUiDisplayMode[]` for type safety
- Regenerate schemas

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Address Olivier's feedback - consolidate display mode docs

- Remove separate "App Capabilities" section for availableDisplayModes
- Add display mode requirements to existing ui/request-display-mode section:
  - Host MUST NOT switch View to mode not in appCapabilities.availableDisplayModes
  - Host MAY decline requests from Views that didn't declare modes
  - View MUST declare supported modes during initialization

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Restore McpUiAppCapabilities docs and fix display mode clause

- Restore McpUiAppCapabilities interface documentation with availableDisplayModes
- Restore "View MUST check if the requested mode is in availableDisplayModes
  from host context" clause that was accidentally removed

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Create unified Display Modes section

Consolidate all display mode documentation into a single section:
- Display mode types (inline, fullscreen, pip)
- Declaring support from View (appCapabilities.availableDisplayModes)
- Declaring support from Host (HostContext.availableDisplayModes)
- Requesting changes (ui/request-display-mode)
- Notifying changes (ui/notifications/host-context-changed)
- All MUST/SHOULD requirements for View and Host behavior

The ui/request-display-mode in Requests section now references
the Display Modes section for behavior details.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove mode coercion clause from display modes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* Regenerate schemas with correct version

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-23 21:13:26 +00:00
Olivier Chafik
cfcbc9605f
feat(server): add getUiCapability helper for capability negotiation (#313)
* feat(server): add hasUiSupport/getUiCapability for experimental+extensions

Support double-tagging for MCP Apps capability negotiation:
- Check both experimental and extensions fields in client capabilities
- Add hasUiSupport() to easily check if client supports MCP Apps
- Add getUiCapability() to retrieve the capability settings
- Update spec to document both capability locations

This enables forward compatibility as MCP transitions from experimental
to the extensions field (SEP-1724).

Claude-Generated-By: Claude Code (cli/claude-opus-4-5=100%)
Claude-Steers: 0
Claude-Permission-Prompts: 0
Claude-Escapes: 0

* fix: update @types/node version in package-lock.json

Replace invalid 22.19.5/22.19.6/22.19.7 versions with valid 22.19.3

* docs(spec): clarify hosts SHOULD double-tag, servers SHOULD check both

- Hosts SHOULD advertise capabilities in both experimental and extensions
- Servers SHOULD check both locations, preferring extensions when present
- Updated example to show double-tagging pattern

* chore: remove double-tagging recommendation, keep hasUiSupport helper

Reverts the spec changes that recommended clients double-tag capabilities
in both experimental and extensions fields. The helper functions remain
as they're useful for checking capability in either location.

* refactor(server): simplify to only getUiCapability, remove hasUiSupport

- Remove hasUiSupport function (use getUiCapability directly)
- Remove double-tagging logic (only check extensions field)
- Add ClientCapabilitiesWithExtensions type using SDK's ClientCapabilities
- Update spec to use getUiCapability
- Simplify tests

* fix: update @see link to getUiCapability

* refactor(server): inline ClientCapabilitiesWithExtensions type in getUiCapability

* refactor: move McpUiClientCapabilities to spec.types.ts
2026-01-23 16:26:49 +00:00
Jonathan Hefner
58019a48ce
Replace {@includeCode} with synced code fences
Migrate JSDoc and markdown documentation from `{@includeCode ./file#region}`
tags to inline code fences with `source="./file#region"` attributes.
Code examples are now visible directly in source files while remaining
type-checked via their `.examples.ts` source files.

Add `scripts/sync-snippets.ts` to extract code from `//#region` blocks
and sync it into labeled fences. Run with `npm run sync:snippets`.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 07:34:56 -06:00
Liad Yosef
4fc71656a3
docs: standardize UI terminology to use "view" consistently (#325)
* docs: standardize UI terminology to use "view" consistently

Replaces "widget" and "Guest UI" terminology with "view" across
the codebase as decided in the community survey.

This change updates:
- Specification document
- SDK source code and JSDoc comments
- Example servers and documentation
- Plugin documentation and skills

Closes #71

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 04:36:52 +02:00
Jonathan Hefner
9dd995562a
Format {@link} tags with monospace display text
Add explicit backtick-wrapped display text to all `{@link}` tags for
monospace rendering in TypeDoc output. This improves readability by:

- Using monospace font for code references (types, methods, functions)
- Stripping module prefixes from display text (e.g., `app!App.connect`
  displays as `App.connect`)

Updated files across the SDK including `App`, `AppBridge`,
`PostMessageTransport`, React hooks, server helpers, types, and
documentation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 14:37:04 -06:00
Jonathan Hefner
e626b84d44 Complete "Sending large follow-up messages" pattern documentation
Add new pattern showing how to combine `updateModelContext()` with
`sendMessage()` when data exceeds message size limits. The example
demonstrates offloading a large transcript to model context first,
then sending a brief trigger message.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
89653cbb7a Complete "Passing contextual information" pattern documentation
Documents `updateModelContext` for keeping the model informed about user
interactions. The example shows a shopping cart use case with YAML frontmatter
for structured, parseable context.

Also refines the `updateModelContext` JSDoc to clarify the difference from
`sendMessage` and removes the `structuredContent` example.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
a0265f92d2 Complete "Giving errors back to model" pattern documentation
Adds JSDoc example `App_updateModelContext_reportError` showing how to
report runtime errors (e.g., microphone permission denied) back to the
model using `updateModelContext`.

Updates patterns.md with clearer framing:
- Server-side (tool handler): return `{ isError: true, ... }`
- Client-side (app): use `updateModelContext` for runtime errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
a1ae100ef0 Complete "Lowering perceived latency" pattern documentation
- Expand `App_ontoolinputpartial_progressiveRendering` example in
  `app.examples.ts` to show full state management pattern with
  `toolInputs` and `toolInputsPartial` variables
- Add healed JSON caveat to `ontoolinputpartial` JSDoc in `app.ts`
- Update `patterns.md` to reference the expanded example and document
  the streaming preview pattern
- Remove empty `lowerPerceivedLatency` placeholder from `patterns.tsx`

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
dce143e92e Complete "Entering / exiting fullscreen" pattern documentation
Add `App_onhostcontextchanged_respondToDisplayMode` example showing how to
listen for display mode changes and update UI with `classList.toggle()`.

Update `App_requestDisplayMode_fullscreen` to `App_requestDisplayMode_toggle`
to show the common toggle pattern checking `availableDisplayModes` first.

Refactor full examples (pdf-server, shadertoy-server) to use
`classList.toggle(class, condition)` instead of add/remove branches.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
566ac58ab7 Consolidate host styling patterns into unified documentation
Merge the separate "Support native host styling using CSS variables" and
"Reacting to light/dark theme changes" sections into a single "Matching
host styling (CSS variables, theme, and fonts)" pattern. This provides
clearer guidance by covering all three concerns together.

- Rename `docs/patterns.ts` to `docs/patterns.tsx` for JSX support
- Add `hostStylingVanillaJs` and `hostStylingReact` consolidated examples
- Enhance `applyHostFonts_fromHostContext` to apply initial fonts after
  `connect()`, not just on context change
- Add CSS usage examples to `applyHostStyleVariables()` JSDoc
- Update font example to use `var(--font-sans, system-ui, sans-serif)`

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
77306d1aaf Complete "Reacting to light/dark theme changes" pattern documentation
Reference existing JSDoc examples instead of maintaining a separate one in
`docs/patterns.ts`:
- Vanilla JS: `applyDocumentTheme_fromHostContext` from `styles.examples.ts`
- React: `useDocumentTheme_conditionalRender` for reactive theme reading

Expand `applyDocumentTheme_fromHostContext` example to show both the
`onhostcontextchanged` handler and initial theme application after `connect()`.

Note in the docs that `useHostStyles()` applies theme automatically, so React
apps don't need additional setup unless they want to read the theme reactively
for conditional rendering.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
fb5e96a719 Complete "Support native host styling using CSS variables" pattern documentation
References existing type-checked examples instead of a stub:
- Vanilla JS: `applyHostStyleVariables_fromHostContext` from `src/styles.examples.ts`
- React: `useHostStyles_basicUsage` from `src/react/useHostStyles.examples.tsx`

Expanded `applyHostStyleVariables_fromHostContext` to show the full pattern:
using CSS variables in styles, applying on `onhostcontextchanged`, and
applying initial styles after `connect()`.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
7c3d1e817f Complete "Tools that are private to Apps" pattern documentation
Document the `_meta.ui.visibility: ["app"]` feature in `docs/patterns.md`
by referencing the existing type-checked example from
`src/server/index.examples.ts#registerAppTool_toolVisibility`.

- Fix typo: `["apps"]` → `["app"]` (singular)
- Remove placeholder function from `docs/patterns.ts`
- Expand description to explain use cases

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 13:31:11 -06:00
Jonathan Hefner
f0c7cc1b14 Refine JSDoc examples for consistency and type safety
Follow-up to the examples extraction: pass dependencies as function
parameters instead of using global stub declarations, rename region
names to match method names (e.g., `AppBridge_guestCapabilities_*` →
`AppBridge_getAppCapabilities_*`), and simplify examples using optional
chaining.

Also clarifies `RESOURCE_URI_META_KEY` documentation to indicate it's
for tool definition metadata (from `tools/list`), not tool result
metadata, and removes the redundant `setNotificationHandler` example
in favor of the simpler event setter approach.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 20:43:47 -06:00
Jonathan Hefner
ad04e89745 Move JSDoc examples to type-checked .examples.ts files
Extract inline code examples from JSDoc comments into companion
`.examples.ts`/`.examples.tsx` files. Examples are now:

- Type-checked by wrapping them in functions
- Referenced via `{@includeCode ./file.examples.ts#regionName}` tags
- Organized using `//#region` and `//#endregion` markers

This keeps the main source files cleaner while ensuring examples
compile correctly. Updated TypeDoc config with `exampleTag: false`
to support title text on `@example` tags.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 20:41:19 -06:00
Jonathan Hefner
90dad1a86b Add "Migrate from OpenAI App" skill to Claude Code plugin
Adds a new skill (`plugins/mcp-apps/skills/migrate-oai-app/SKILL.md`)
that guides developers through migrating OpenAI Apps SDK applications
to the MCP Apps SDK. Includes API mapping tables, CSP configuration
guidance, and a "Before Finishing" checklist.

Also fixes the `registerAppResource()` JSDoc example in `src/server/index.ts`
to show CSP configuration in the correct location (on the content item,
not the resource config).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 07:59:41 -06:00
Matthew Wang
d27acc42b1 Add and helper functions 2026-01-16 21:20:10 -08:00
Copilot
c73d36343b
fix: change unknown source message log from error to debug level (#239)
* Initial plan

* Change console.error to console.debug for unknown message sources

Co-authored-by: liady <7003853+liady@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: liady <7003853+liady@users.noreply.github.com>
2026-01-15 11:51:27 +00:00
Matthew Wang
5bb0c6b4c7 Use as the input type in 2026-01-14 13:07:08 -08:00
Jonathan Hefner
d48e35d88a
Improve JSDoc comments with cross-references and clarifications (#254)
Key improvements:
- Add `{@link}` cross-references throughout the codebase to make API
  documentation navigable and help AI models understand relationships
- Use `{@link module!Export}` syntax for cross-module references
- Add backticks for inline code formatting (`ResizeObserver`, `App`, etc)
- Fix `PostMessageTransport` examples to show required two-argument form
- Clarify `onteardown` callback return type requirement
- Document React hooks cleanup behavior and Strict Mode considerations
- Add tool visibility example for `registerAppTool`
- Add CSP example for `registerAppResource`
- Fix notification direction documentation in `spec.types.ts`

TypeDoc config migrated from `typedoc.json` to `typedoc.config.mjs` to:
- Support custom `@description` block tag
- Add `intentionallyNotExported` for internal types
- Include `src/server/index.ts` entry point

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 00:41:17 +00:00
Olivier Chafik
6bb63c3bae
examples: add transcript-server example with live speech transcription (#240)
* feat: add transcript-server example with live speech transcription

- New example: transcript-server with Web Speech API transcription
  - Start/stop recording with timer display
  - Live transcript with interim results
  - Send button to send transcript as ui/message to host
  - Copy button to copy full transcript
  - Sent messages marked with divider, greyed out
  - Experimental ui/update-model-context for live context updates
  - Transparent background, respects host theme

- Enable microphone and clipboard in basic-host sandbox iframes
  - Add allow="microphone; clipboard-write" to both outer and inner iframes
  - Required for Web Speech API, audio capture, and clipboard access

- Add alert popup in basic-host for ui/message from apps

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* style: format transcript-server files

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* test: add e2e test and golden for transcript-server

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: use @types/dom-speech-recognition instead of hand-rolled types

Removes ~50 lines of manually defined Web Speech API types in favor of
the community-maintained type package.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: add newlines between transcript chunks when copying to clipboard

* refactor: unify transcript formatting with timestamps

- Add formatEntry() helper that includes [timestamp] prefix
- Add formatEntries() helper that joins entries with newlines
- Use same format for clipboard copy, send message, and model context
- DRY up duplicate code in send button handler

* fix: log model context update failures instead of silently swallowing

* fix: log model context updates for debugging

* refactor: pass permissions through loadSandboxProxy like csp

- Add permissions parameter to loadSandboxProxy in implementation.ts
- Build iframe allow attribute from permissions instead of hardcoding
- Update sandbox.ts to not hardcode allow attribute (set via notification)
- Add microphone + clipboardWrite permissions to transcript-server resource
- Update README to reflect permission configuration via resource _meta.ui

* fix(transcript-server): auto-expand instead of scroll

- Remove min-height: 100vh and overflow-y: auto
- Let content grow naturally with autoResize (default)
- Remove unnecessary scrollTop calls

* test: remove transcript timer mask (no longer dynamic)

* refactor: pass permissions through loadSandboxProxy like csp

* docs: document updateModelContext for transitional speech

* test: update e2e screenshots

* refactor: use app.updateModelContext() instead of raw request

* package-lock.json

* src/generated/schema.json

* test: update e2e screenshots from CI

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 21:27:31 +00:00
Olivier Chafik
741b1d3925
feat(basic-host): improve host UI with collapsible panels and SDK types (#244)
* refactor(basic-host): use SDK types for ModelContext and AppMessage

- Import McpUiUpdateModelContextRequest and McpUiMessageRequest from SDK
- Replace custom ModelContext with McpUiUpdateModelContextRequest['params']
- Replace custom AppMessage with McpUiMessageRequest['params']
- Pass full message params instead of extracting text
- Format messages by extracting text from content blocks in display

* feat(basic-host): handle non-text content blocks in display

- Add formatContentBlock helper for text, image, audio, resource types
- Show placeholders like <image: image/png> for non-text content
- Apply to both messages and model context display

* test: update shadertoy screenshot

* test: update screenshots from CI (linux x64)
2026-01-12 19:42:11 +00:00
Jonathan Hefner
ec3409aa91
Add shadertoy-server example for WebGL shader rendering (#226)
Introduces a new MCP App example that renders ShaderToy-compatible GLSL
fragment shaders in real-time using WebGL 2.0 and ShaderToyLite.js.

Features:
- Standard ShaderToy uniforms (`iTime`, `iResolution`, `iMouse`, etc.)
- Multi-pass rendering with buffers A-D for feedback effects
- Shader compilation error overlay

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 18:26:02 +00:00
Ido Salomon
b273279849
feat: add ui/update-model-context (#125)
---------

Co-authored-by: Olivier Chafik <ochafik@anthropic.com>
2026-01-12 15:21:45 +00:00
Ido Salomon
9acc52cb96
feat: enhance sandbox capability negotiation (#158)
* feat: enhance sandbox capability negotiation

* Update specification/draft/apps.mdx

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* add all csp and permissions to host capabilities + update SEP

* feat: add clipboard-write permission support

Adds clipboardWrite to McpUiResourcePermissions for clipboard access.
Maps to Permission Policy 'clipboard-write' feature.

* rm files added by mistake

* refactor: change McpUiResourcePermissions properties to empty objects

* chore: remove scratch files and redundant cross-env dependency

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Olivier Chafik <ochafik@anthropic.com>
2026-01-12 15:10:27 +00:00
Olivier Chafik
8b09f4278c
fix: proper CSP handling in basic-host sandboxing (HTTP headers, worker-src, document.write) (#234)
* fix: Move CSP to HTTP headers + add worker-src, frameDomains, baseUriDomains, permissions

Security improvements:
- CSP is now set via HTTP headers in serve.ts instead of meta tags
  (meta tag CSP can be tampered with by same-origin content)
- CSP passed as query param to sandbox.html for header-based enforcement

New CSP/permissions features (borrowed from PR #158):
- frameDomains: control frame-src directive for nested iframes
- baseUriDomains: control base-uri directive
- permissions: camera, microphone, geolocation via iframe allow attribute

WebGL fix:
- Use document.write() instead of srcdoc for inner iframe content
  (srcdoc creates opaque origin that breaks WebGL canvas updates)
- Add worker-src directive with blob: support (critical for WebGL apps
  like CesiumJS/Three.js that use workers for tile decoding, terrain
  processing, image processing)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* refactor: Remove permissions support (defer to PR #158)

Keep this PR focused on CSP security fixes only.
Permissions (camera, microphone, geolocation) will be
handled in #158.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* cleanup McpUiResourceCsp type usage / duplicate defs

* fix: guard against CSP injection in domain parameters

Validate CSP domain entries to reject characters that could:
- Break out of CSP directives (semicolons, newlines)
- Inject CSP keywords like 'unsafe-eval' (quotes)
- Inject multiple sources in one entry (spaces)

This prevents injection attacks where malicious domains could
override the security policy.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 14:32:48 +00:00