Commit graph ext-apps/README.md
Author SHA1 Message Date
Olivier Chafik
853c9f749c Migration guide fixes and editor-visible deprecation for the 1.x handler form
Guide: name @modelcontextprotocol/express in the server-author row, say
the two SDKs share no types rather than "do not interoperate" (they speak
the same wire protocol), note zod 4.0/4.1 lack ~standard.jsonSchema, list
the full 1.x-shaped extra, cover tool callbacks in the handler-context
bullet, document that the double-registration guard now covers the base
Protocol's notifications/progress and notifications/cancelled handlers,
mention ResourceNotFoundError, add the Express row to the import map, and
add a "What stays the same" section.

The @deprecated tag on the legacy setRequestHandler / setNotificationHandler
overload sat on the parameter inside an intersection type, which TypeScript
does not report. The overload now comes from LegacyRequestHandlerSetter /
LegacyNotificationHandlerSetter, named types with a documented call
signature, so editors flag the 1.x call and not the 2.x forms.

README links to the quickstart use the lowercase slug typedoc emits.
2026-09-08 18:01:18 +01:00
Olivier Chafik
6d083cd69f Address review: MCPB build, guard the SDK's own handlers, doc fixes
- pdf-server build-mcpb.mjs packs the ext-apps build from this checkout
  into the staging dir instead of asking the registry for ^2.0.0, which
  is not published yet; CI's "Build MCPB bundle" step failed on ETARGET.
- Claim notifications/cancelled and notifications/progress in the
  MethodRegistry right after super() so a direct setNotificationHandler
  cannot silently replace the base Protocol's own handlers.
- Migration guide and add-app-to-server skill: custom methods use the
  three-argument setRequestHandler("m", { params }, handler) form (the
  two-argument form is only for spec methods); zod schemas live in
  @modelcontextprotocol/core, not client/server; it is
  toolInfo.tool.outputSchema that loosened in schema.json, and the
  recursive JSON-value def is nested under three definitions; core is a
  required peer that client already depends on.
- app-bridge.ts: fix "forthe"/"forresult" typos in @see links, update
  three JSDoc examples to the method-string setNotificationHandler form,
  move the UntypedHandlerSetter type below the import block (same in
  app.ts).
- wire-compat.test.ts: say the fixtures are 1.x-shaped, not captures.
2026-09-08 13:59:09 +01:00
Olivier Chafik
c5b2543115 Document the 2.x install matrix and add a migration guide
Install instructions now list the split base MCP SDK packages at ^2.0.0
by role (core comes in transitively, server only for server authors),
require Node 20+, and state that the wire protocol is unchanged so 2.x
Views and 1.x hosts interoperate. The agent skills lose the exact
prerelease wording and add-app-to-server gains a v1 to v2 import
mapping. docs/migrate-to-2.md lists the breaking changes, the peer
matrix and the host-side error deltas.
2026-09-08 13:58:37 +01:00
Olivier Chafik
1a713173cc
Migrate to MCP SDK 2.0 with official Protocol and isolated role peers (#720)
App and AppBridge extend the public Protocol from @modelcontextprotocol/client; the iframe wire protocol (ui/initialize only) is unchanged. Peers move to the split SDK 2.0 packages with client and server as optional role peers. Fixups (lockfile, peer ranges, restored handler guards, docs, wire-compat tests) follow in a separate PR.

Co-authored-by: Andrew Khadder <andrew@manufact.com>
Co-authored-by: Felix Weinberger <fweinberger@anthropic.com>
Closes #702
2026-09-08 12:44:49 +01:00
Quentin Churet
10195ad918
docs: add Alpic Playground to supported clients (#729)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-12 18:04:54 +03:00
Enrico
c847bc0887 docs: align Protocol and role-specific setup 2026-07-22 15:37:22 -07:00
Andrew Khadder
f94cb38b0b
refactor: finish MCP SDK v2 migration 2026-07-14 17:07:30 -07:00
Copilot
cf87f2a2c2
ci: fix README prettier build failure (#698)
* Initial plan

* fix: apply Prettier formatting to README table row

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-07-07 21:29:16 +03:00
Andrew Khadder
cd969dbc31
docs: add mcp-use inspector badge to supported clients (#650) 2026-07-07 21:05:17 +03:00
Ensar Gök
ea8775dcb5
docs: API Docs link for ext-apps/server (#697)
Updated API documentation link for ext-apps/server.
The link `/server.html` does not exists.
2026-07-07 20:43:37 +03:00
Den Delimarsky
a870456893
fix(readme): use picture element for theme-aware logo (#545)
* fix(readme): use picture element for theme-aware logo

The #gh-light-mode-only / #gh-dark-mode-only URL fragments only work
on github.com. On npm, VS Code preview, and other markdown renderers
both img tags render, showing two stacked logos.

Switch to <picture> with prefers-color-scheme, which GitHub recommends
and which degrades gracefully to a single logo elsewhere.

* ci: add Cloudflare Pages preview for docs PRs

Deploys a per-PR preview of the TypeDoc site to Cloudflare Pages project
mcp-ext-apps-docs-preview when docs, src JSDoc, README, or typedoc config
change. Uses the shared modelcontextprotocol/actions composite action that
injects noindex headers, posts a sticky PR comment with preview URLs, and
cleans up deployments on PR close. Fork PRs are skipped (no secret access).

* fix(docs): sync README logo with TypeDoc theme switcher

The README <picture> logo uses prefers-color-scheme, which only follows
the OS setting. TypeDoc's theme switcher sets data-theme on <html>, so
manually picking Light/Dark would show the wrong logo (e.g. white logo
on light background if OS is dark but user picked Light).

Rewrite the <picture> in the generated docs into two class-tagged <img>s
via the mcpstyle plugin, and hide the inactive one via CSS keyed on both
data-theme (explicit selection) and prefers-color-scheme (OS mode). The
README source is unchanged so GitHub/npm still get <picture>.

Also: prettier normalized mcp-theme.css (tabs to spaces, quote style).
2026-03-10 17:33:40 +00:00
Jonathan Hefner
b4642b4338
Use apps.extensions.modelcontextprotocol.io domain for docs URLs
Update all documentation links from `modelcontextprotocol.github.io/ext-apps`
to the new custom domain across README.md, docs/, and example READMEs.

Add `cname` to the `peaceiris/actions-gh-pages` deploy action in
`.github/workflows/docs.yml` so the CNAME file persists across deploys.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-24 11:38:54 -06:00
Conor Kelly
6e40513dbf Adding ChatGPT to the readme
Added ChatGPT as a supporting client in the readme. Also updated links to re-direct to the relevant MCP Apps docs on respective client pages
2026-02-21 18:09:18 -08:00
Den Delimarsky
5710a7e462
Update README.md 2026-02-21 13:03:42 -08:00
Den Delimarsky
910c417fae
Format README with prettier 2026-02-21 08:33:29 +00:00
Den Delimarsky
da4406edc2
Update skill 2026-02-21 08:22:47 +00:00
Den Delimarsky
7e0fee6b03
Use GitHub note admonition for clients note 2026-02-20 22:12:20 +00:00
Den Delimarsky
2281bcf176
Add supported clients section to README 2026-02-20 22:10:43 +00:00
Den Delimarsky
7eec75164a
Format README with prettier 2026-02-20 20:53:10 +00:00
Den Delimarsky
2af02baf46
Update README hero gif to Excalidraw, add new agent skills 2026-02-20 20:47:02 +00:00
Den Delimarsky
8543d8d5dc Lead README with agent skills for faster onboarding
Move the agent skills section to the top of the README so readers
immediately see how to install and start building. Keep Claude Code
install commands front and center with a brief pointer to the agent
skills guide for other agents. Specification section moves below
Examples.
2026-02-20 19:37:58 +00:00
Olivier Chafik
8cad9f04c0
Add PDF search feature to pdf-server (#445)
* Add PDF search feature to pdf-server

Adds full-text search functionality to the PDF viewer:

- Search button in toolbar (Ctrl/Cmd+F to open)
- Search bar with input, prev/next navigation, match count
- Text extraction and caching across all pages
- Highlight overlays using DOM Range API
- Case-insensitive search across entire document
- Keyboard shortcuts: Ctrl+F (open), Enter (next), Shift+Enter (prev), Escape (close)

Changes:
- mcp-app.html: Add search button, search bar, highlight layer
- src/mcp-app.css: Add search/highlight styles and PDF.js text layer rules
- src/mcp-app.ts: Add search state, functions, event listeners

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

* update screenshots

* Add fullscreen button to threejs-server

* Fix prettier formatting

* Move search bar below toolbar, right-aligned

* Make search bar compact and right-aligned

* Float search bar over page content

* Ctrl/Cmd+F toggles search; pass through to browser when empty

* Hide search nav controls until query is entered

* Skip scroll when search highlight is already visible

* Fix search bar right-edge alignment with container border

* Prevent browser find when our search is open with text

* Cmd+F when search input is focused passes through to browser find

* Fix prettier formatting in README

* Remove unrelated formatting and threejs changes from PR

* prettier

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 18:56:40 +00:00
Den Delimarsky
5eab6da3fc
README update 2026-02-16 23:03:52 -08:00
Den Delimarsky
62e1a5a0ae
README update 2026-02-16 23:01:59 -08:00
Den Delimarsky
512016053d
README update 2026-02-16 23:00:57 -08:00
Den Delimarsky
c2a0b5ccad
Update with media 2026-02-16 22:59:17 -08:00
Den Delimarsky
291006ab73
Update with media 2026-02-16 22:57:28 -08:00
Den Delimarsky
a427e7127d
Update with media 2026-02-16 22:52:59 -08:00
Den Delimarsky
22bffa8782
Update with media 2026-02-16 22:51:16 -08:00
Den Delimarsky
8242496f3e
Update README 2026-02-16 21:26:21 -08:00
Den Delimarsky
716d7c1c5c
Update README 2026-02-16 21:23:08 -08:00
Den Delimarsky
09e1684db4
Update README 2026-02-16 21:19:48 -08:00
Den Delimarsky
c372c1f6a1
Update README 2026-02-16 21:16:47 -08:00
Ido Salomon
0278af6a2a
examples: remove arcade (#414) 2026-01-30 22:06:50 +02:00
Ido Salomon
adf0bbd611
examples: add arcade example to servers (#399) 2026-01-29 20:55:57 +02:00
Ido Salomon
aec5240f22
docs: update MCP-UI SDK description in README (#365)
Clarified the description of the MCP-UI client SDK and its usage.
2026-01-26 19:44:48 +02: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
Olivier Chafik
d03123bb5c
docs: add local development MCP client configuration to READMEs (#361)
* docs: add local development MCP client configuration to READMEs

Add instructions for configuring MCP clients to use locally-cloned
and modified servers. This allows developers to test local changes
with MCP clients like Claude Desktop or VS Code.

- Top-level README: Added 'Local Development' section after npx config
- All TypeScript examples: Added 'Local Development' subsection with
  bash one-liner that builds and runs the server
- Python examples (qr-server, say-server): Added local path config

* docs: include all servers in local development config

* docs: use bash wrapper for Python server configs to enable tilde expansion
2026-01-26 15:22:00 +00:00
Jonathan Hefner
b695b2e9ba
Improve README structure and clarity
Add "Why MCP Apps?" section to explain the motivation upfront. Reorganize
the "How It Works" section to lead with tool definition. Rename "Overview"
to "Using the SDK" and add "For" prefix to audience headings.

Restructure the Examples section with clearer subsections for running
examples with `basic-host` vs MCP clients using stdio transport. Move the
`qr` server note outside the collapsed details block.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 16:52:19 -06:00
Jonathan Hefner
ff86ef2ec4
Expand Agent Skills guide
Add intro explaining what Agent Skills are and link to the two skill
files (`create-mcp-app`, `migrate-oai-app`). Reorganize headings and add
"Invoke a Skill" and "Test Your App" sections. Update `README.md` link
text and add tip to quickstart suggesting agent skills as an alternative.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 14:18:04 -06:00
Jonathan Hefner
655231ded0
Add Agent Skills installation guide
Add `docs/agent-skills.md` with installation instructions for multiple AI
coding agents including Claude Code, VS Code/Copilot, Gemini CLI, Cline,
and Goose. The guide provides three installation methods: Claude Code
plugin, Vercel Skills CLI (`npx skills add`), and manual installation.

Update `README.md` to link to the new guide and reframe the plugin
section around the broader "Agent Skills" concept.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 15:10:23 -06:00
Jonathan Hefner
26ae13df0f
Merge pull request #302 from jonathanhefner/checked-examples
Move JSDoc examples to type-checked `.examples.ts` files
2026-01-20 13:30:01 -06:00
Jonathan Hefner
7078f81ceb Add .claude-plugin/marketplace.json for plugin distribution
This enables users to install the `mcp-apps` plugin via:

    /plugin marketplace add modelcontextprotocol/ext-apps
    /plugin install mcp-apps@modelcontextprotocol-ext-apps

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 11:38:14 -06:00
Olivier Chafik
864bb6dc2d
docs: clarify that npm start runs examples in dev mode 2026-01-20 10:54:04 +00:00
Olivier Chafik
cba7b71e2b
docs(say-server): use raw GitHub URL for direct uv run 2026-01-20 10:42:31 +00:00
Olivier Chafik
ccd41ac721
docs: add MCP client config for say-server
- Add MCP client configuration section to say-server README
- Add say-server to combined config in top-level README
2026-01-20 10:18:19 +00:00
Olivier Chafik
5ef3120e0c
Merge remote-tracking branch 'origin/main' into ochafik/readme-mcp-config 2026-01-20 10:17:45 +00:00
Jonathan Hefner
e5c90c7385 Use absolute GitHub URLs for example links in README
Relative directory links like `](examples/map-server)` caused TypeDoc
warnings ("relative path is not a file") and resulted in broken links
in the generated API documentation. Converted all 20 example directory
links to full GitHub URLs while keeping image paths relative.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 20:36:28 -06:00
Olivier Chafik
e6983b36d0
feat(examples): add say-server - streaming Pocket TTS with karaoke highlighting (#304)
* Add say-server: streaming TTS MCP App with karaoke UI

- Streaming TTS MCP App with real-time word highlighting
- React widget with pause/resume controls
- Debounced model context updates
- Self-contained server.py for standalone uv run

Co-authored-by: Claude <noreply@anthropic.com>

* Update server.py

* fix(say-server): fix React/Zod version conflicts in widget

- Pin Zod to v3.25.1 via esm.sh deps param (fixes .custom() error)
- Add external=react,react-dom to prevent duplicate React instances
- Update React from 19.1.0 to 19.2.0
- Import React for Babel's classic JSX transform
- Consolidate imports: only use @modelcontextprotocol/ext-apps/react
- Use Babel from unpkg.com instead of esm.sh
- Simplify resource decorator with meta= parameter
- Update CSP to allow both esm.sh and unpkg.com

* fix(say-server): show play button when paused, restart when finished

* feat(say-server): add fullscreen button, remove inline scroll

- Add fullscreen toggle button (appears on hover when available)
- Remove max-height/scroll in inline mode for cleaner display
- Enable scrolling only in fullscreen mode
- Track displayMode and fullscreenAvailable state
- Handle onHostContextChanged to detect fullscreen support

* fix(say-server): fix fullscreen button visibility and prevent multiple audio streams

- Check initial host context for fullscreen availability (not just updates)
- Add audioOperationInProgressRef guard to prevent concurrent audio operations
- Prevents race conditions from rapid clicks/double-clicks

* fix(qr-server): use meta parameter instead of manual handler patching

Simplified CSP metadata handling to match say-server's approach:
- Use meta parameter on @mcp.resource decorator directly
- Removed custom _read_resource_with_meta handler and handler replacement

* fix(say-server): simplify controls to prevent multiple audio streams

- Remove onClick from text display (was conflicting with double-click)
- Always show overlay button (with pause icon when playing)
- Lower opacity (0.3) when playing, full on hover
- Button shows: ▶️ (play), ⏸️ (pause), 🔄 (restart)
- Double-click text to restart still works
- Eliminates click/dblclick race condition

* fix(say-server): only show pause button on hover

- Play/restart buttons visible normally
- Pause button hidden until hover (doesn't block karaoke text)

* fix(say-server): fix partial input handling and session management

- Add promise lock to initTTSQueue to prevent concurrent initialization
- Reset queueIdRef and lastTextRef in ontoolresult for next tool call
- Close existing AudioContext when starting new session
- Reset all playback state (chunks, timings, position) on new session
- Fixes: text deltas not sent when new tool call has shorter text

* fix(say-server): detect new sessions by text comparison, not queueIdRef reset

- Don't reset queueIdRef in ontoolresult - audio should keep playing
- Detect new sessions in ontoolinputpartial/ontoolinput by checking if
  new text starts with lastTextRef (continuation) or not (new session)
- Only reset and create new queue when genuinely new session detected
- Fixes: pause/play was creating new streams because queueIdRef was reset

* feat(say-server): add theming, floating button, and keyboard shortcuts

Theming:
- Use CSS variables (--font-sans, --color-text-primary/secondary) with fallbacks
- Apply host fonts via applyHostFonts() on connect and context changes
- Apply host style variables via applyHostStyleVariables()
- Apply document theme via applyDocumentTheme()

Floating button:
- Button follows cursor position (below current line being spoken)
- Uses invisible cursor marker element for accurate positioning
- Shows ⏸️ when playing, ▶️ when paused, 🔄 when finished
- Low opacity when playing, full on hover

Keyboard shortcuts:
- Space: toggle play/pause
- Enter: toggle fullscreen (when available)

UI changes:
- Large overlay only shown for initial play (idle state)
- Floating button used during playback for less intrusive controls

* docs(say-server): add TODO items for future improvements

* fix(say-server): simplify to fixed play button at top right

- Remove floating cursor-following button (was too complex)
- Fixed play button at top-right corner
- Low opacity when playing, full on hover
- Keep theming and keyboard shortcuts (Space/Enter)
- Add say-server to E2E tests

* test(e2e): add say-server to tests but skip in CI

Say-server requires Pocket TTS model (~500MB) and GPU support,
which isn't available in the Docker CI environment. Skip it for now.

* test(e2e): add say-server and qr-server to screenshot generation

- Remove say-server from SKIP_SERVERS (widget works without TTS model)
- Add say-server masks for play buttons
- Add both say-server and qr-server to grid screenshot generator

* fix(say-server): restore working play/pause overlay, keep theming and keyboard shortcuts

Reverted to working commit 413beca and carefully reapplied:
- CSS variables for theming (--font-sans, --color-text-primary/secondary)
- Dark mode support via @media (prefers-color-scheme)
- Host theming via applyHostStyleVariables/applyHostFonts/applyDocumentTheme
- Keyboard shortcuts: Space = play/pause, Enter = fullscreen

Preserved working behavior:
- Play overlay visible when not playing, hover to show when playing
- Pause on click works correctly
- Karaoke highlighting works

* fix(say-server): minimal CSS-only theming, no JS changes from working version

Only CSS changes from working commit 413beca:
- Added CSS variables for theming foundation
- No JavaScript changes (reverted theming calls and keyboard shortcuts)

This isolates whether the issue is CSS or JS related.

* feat(say-server): add autoPlay param and Reset button

- Add autoPlay parameter (default: true) with Pydantic Field description
  - Description visible in MCP tool schema: 'browsers may block autoplay'
- Add Reset button next to Fullscreen button (bottom right)
- Both buttons share controlBtn base styles, shown on hover
- Widget reads autoPlay from tool input params

* fix(say-server): update FastMCP API for new SDK version

Python SDK refactored transport params from constructor to run():
- Remove port, stateless_http from FastMCP() constructor
- Pass stateless_http=True to streamable_http_app() instead

* debug(say-server): add console logs to trace audio stream issue

Logging added to:
- togglePlayPause (all branches)
- initTTSQueue (entry and AudioContext creation)
- restartPlayback (entry)
- ontoolinputpartial/ontoolinput (entry and new session detection)

Open browser DevTools console and reproduce the issue - logs will show what's being called.

* feat(say-server): add play/pause buttons in top-left and bottom-right corners

- Top left: playPauseTopBtn for quick access
- Bottom right: playPauseBtn alongside reset and fullscreen
- Both show on hover with same styling as other control buttons
- Icons: ▶️ (play), ⏸️ (pause), 🔄 (restart when finished)

* fix(say-server): simplify UI and fix pause/resume audio duplication

- Remove central play overlay, use single toolbar in top-right
- Fix audio duplication on pause/resume (only defer to pendingChunks for initial autoplay)
- Remove double-click to restart (use toolbar restart button)
- Sync displayMode when host changes it externally
- Click on text to play/pause

* feat(say-server): add voice selection support

- Add list_voices tool to show available voices
- Add voice parameter to say tool (predefined names, HuggingFace URLs, or local paths)
- Predefined voices: alba, marius, javert, jean, cosette, eponine, azelma, fantine
- Update README with voice documentation

* docs(say-server): improve tool description for better LLM triggering

- Add English-only constraint prominently in first line and note
- List common trigger patterns (say, speak, read aloud, etc.)
- Update text parameter description to mention English
- Keep description concise for quick LLM scanning

* feat(say-server): add speak lock for multi-widget coordination

When multiple TTS widgets exist, only one plays at a time:
- Widget announces to localStorage when starting playback
- Playing widgets poll localStorage every 200ms
- If another widget starts, previous one pauses automatically
- Lock is cleared on pause/finish/teardown

Uses _meta.widgetUUID in tool result for widget identification.

* update package.json of say

* feat(say-server): add screenshots and update README gallery

- Add say-server to demo gallery with 300x300 grid-cell.png
- Fix qr-server grid-cell.png dimensions (was 672x668, now 300x300)
- Add golden snapshot for say-server E2E tests
- Add full screenshot and grid-cell thumbnail for say-server

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

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

* style(say-server): apply prettier formatting

- Add blank lines in README for better readability
- Add trailing newline to package.json

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

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

* feat(say-server): add Escape key to exit fullscreen and update docs

- Add onKeyDown handler to main element for Escape key
- Update README with full list of MCP App features:
  - Model context updates
  - Native theming
  - Fullscreen mode
  - Multi-widget speak lock
- Update server.py docstring with feature documentation

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

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

* fix(say-server): add queue timeout to prevent infinite polling

The TTS queue could hang forever if:
- The LLM stops generating mid-stream (no end signal)
- User cancels before tool completes
- Network interruption prevents end_tts_queue call

Changes:
- Add last_activity timestamp to track queue activity
- Add 30-second timeout (QUEUE_TIMEOUT_SECONDS)
- Poll with 5-second timeout, checking for stale queues
- Mark stale queues as "error" so widget stops polling
- Return error message in poll_tts_audio response
- Add error logging in widget polling loop

This prevents tool calls from running forever when queues are abandoned.

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

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

* debug(say-server): add logging to track queue lifecycle

Add console logging to debug why end_tts_queue might not be called:

Widget-side:
- Log queueId in ontoolinputpartial, ontoolinput, ontoolresult
- Log when new session is detected (queue reset)
- Log when initTTSQueue fails
- Log when end_tts_queue is called/not called

Server-side:
- Log when end_tts_queue is called
- Log warnings for unknown queues
- Log info for already-ended queues

This will help identify if the issue is:
- User interruption (ontoolresult never called)
- Session reset (queueId becomes null)
- Host bug (callback dropped)

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

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

* perf(say-server): add initial delay before polling

Add 150ms delay before first poll to give TTS model time to generate
the first audio chunk. This reduces unnecessary polling and server load.

Current backoff after that:
- 30ms if chunks received (keep streaming fast)
- 80ms if no chunks (wait longer for generation)

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

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

* fix(say-server): use adaptive polling instead of fixed initial delay

Previous approach: Always wait 150ms before first poll
Problem: Even when chunks are ready, we wait unnecessarily

New approach: Adaptive polling
- Start polling immediately (no initial delay)
- 20ms backoff when receiving chunks (fast streaming)
- Exponential backoff when no chunks: 50ms → 100ms → 150ms max
- Reset backoff when chunks start flowing

This reduces latency when TTS is fast while being polite when it's slow.

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

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

* feat(say-server): add speaker icon to server info

Uses SVG data URI for a speaker with sound waves icon.

* docs(say-server): add comprehensive third-party licensing information

- Expand License section in README with component attribution table
- Add voice collection license matrix with commercial use indicators
- Add warning about non-commercial expresso/ears voice collections
- Clarify NON-COMMERCIAL restriction in list_voices() output
- Use consistent CC-BY formatting (hyphenated)

* Update last activity to prevent timeout during active polling

* feat(say-server): add info button, SVG icons, and UI fixes

- Replace emoji play/pause buttons with neutral white SVG icons
- Add (i) info button in bottom-right with attribution popup
- Use app.openLink() API for external links in popup
- Add dynamic padding to fit popup when shown
- Make create_tts_queue async to fix AnyIO event loop error
- Add better error logging for TTS queue initialization
- Update README with openLink feature documentation
- Remove unnecessary HuggingFace login prerequisites

* docs(say-server): document multi-widget speak lock mechanism

* prettier:fix

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-01-20 00:41:50 +00:00
Olivier Chafik
ac1130cda4
style: format JSON in READMEs with prettier 2026-01-16 15:14:48 +00:00