feat(prompts): prompt browser MCP App - search, preview, argument forms, run from chat#1026
Merged
Conversation
…ms, run from chat (#1011) Adds the built-in prompt-browser MCP App, embedded in the binary and bound to the manage_prompt tool via the mcpapps registry. In an MCP Apps-capable host, a prompt discovery call renders an interactive library browser: search-as-you-type over the ranked query, My Prompts / Library buckets, collection and tag facets, usage sorting, and cards with version, approval provenance, and run counts. The detail view shows full prompt content with live placeholder substitution and an argument form generated from the prompt's argument specs; Run resolves through manage_prompt use with an mcp:prompt:<id> handle and inserts the rendered prompt into the conversation via ui/message where the host supports it, falling back to a copy affordance otherwise. The bridge speaks both host protocol generations: the 2026-01-26 MCP Apps spec (tools/call with JSON-RPC responses, hostCapabilities feature detection) and the legacy 2025-01-09 protocol (ui/call-tool with notification-delivered results, correlated by expectation predicates with at most one list call in flight). manage_prompt list and search responses now batch-apply audit-derived usage (run_count, last_run_at) per prompt and include the shared portal collections list, so app-capable and plain-JSON clients see the same organization model; the app holds no app-local state. Built-in app registration is factored into shared builtinAppDefinition / registerBuiltinApp helpers used by both platform-info and prompt-browser, and the dev test harness gains a prompt-browser entry with a command-aware use responder. The host-capability gating check required by the ticket is documented on the issue before implementation.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1026 +/- ##
=======================================
Coverage 89.33% 89.34%
=======================================
Files 469 469
Lines 51789 51830 +41
=======================================
+ Hits 46268 46306 +38
- Misses 3669 3670 +1
- Partials 1852 1854 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1011. Part 4 of the prompt-library overhaul (#1008 stable invocation identity, #1009 versioning and provenance, #1010 portal library reorg).
What this adds
A built-in
prompt-browserMCP App, embedded in the binary and bound to themanage_prompttool through themcpappsregistry (_meta.uiinjection, no new tool). In an MCP Apps-capable host, a prompt discovery call renders an interactive prompt library browser in the conversation; in every other client the same tool calls keep returning complete structured JSON, so the app is presentation only.Host-capability gating check
Done and documented on the issue before implementation, per the ticket's acceptance criteria: #1011 (comment)
tools/callis in the SEP-1865 allowed message subset, and the shippedplatform-infoapp proves the legacyui/call-toolvariant works in claude.ai today.ui/message) is defined by the spec and advertised per host viahostCapabilities.messagein theui/initializeresult; per-host support is not publicly documented, so the app feature-detects it at runtime.prompts/getfrom an app iframe is not permitted by the spec and is ruled out.Run therefore uses the guaranteed channel (
manage_prompt use) with conversation insertion as a feature-detected enhancement, so the app is not browse-only and ships.The app (
apps/prompt-browser/index.html)Self-contained vanilla JS, no external dependencies, embedded via
apps/embed.goand registered as a second built-in alongsideplatform-info.Browse and search. Search-as-you-type debounces into the ranked
list query=...mode (hybrid semantic + lexical server-side); an empty query lists the caller's full visible set. Facets follow the portal model from #1010: All / My Prompts / Library buckets, a collection filter fed by the shared collection list, tag chips, and sorting by usage, recency, name, or relevance. Cards show display name, scope and status badges, version, description, run count, approval provenance, collection, and tags.Preview and argument forms. A card expands to a detail view with a provenance panel (invoke-as name, version, status, approver and approval date, owner, runs, last run, collection, tags), a form generated from the prompt's structured argument specs (required markers, description hints, client-side required validation), and the full prompt content with
{arg}and{{arg}}placeholders highlighted and live-substituted as values are typed, so the user verifies exactly what will run.Run. Submits
manage_prompt usewith the stablemcp:prompt:<id>handle and the filled arguments; the server substitutes arguments, records theprompt_serveaudit event, and returns the rendered content with provenance. The app then attemptsui/messageinsertion of the rendered prompt (full timeout when the host advertised themessagecapability, a short attempt otherwise, since a host may support insertion without advertising it); on rejection or timeout it falls back to showing the rendered content with a copy affordance.Dual-protocol bridge. The postMessage bridge supports both host generations: 2026-01-26 spec hosts (
tools/callwith JSON-RPC id-correlated responses,hostCapabilitiesfeature detection) and legacy 2025-01-09 hosts such as current claude.ai (ui/call-toolwith results delivered asui/notifications/tool-resultand no capabilities object). Legacy results carry no request id, so correlation scans pending waiters oldest-first with per-call shape predicates, at most one list call is in flight (superseded searches are canceled), and stale search responses are dropped by sequence. Non-JSON-RPC postMessage traffic (which claude.ai is known to inject) is ignored. All server-controlled strings render throughtextContent/createTextNode; there is no HTML injection path.Server-side changes
manage_promptlistand search responses now batch-apply audit-derived usage (run_count,last_run_at) to every returned prompt in onePromptUsageread, and include the sharedcollectionslist when the store has the prompts: portal library reorganization - collections, facets, versions, two-bucket model #1010 collection capability. This satisfies the shared-organization-model criterion (the app consumes the same collection and facet data as the portal, with no app-local model) and enriches plain-JSON clients equally.internal/platform/promptlayerexportsToolNameManagePromptso the composition root binds the app without a duplicated string.pkg/platformis factored into sharedbuiltinAppDefinition/registerBuiltinAppfree functions used by bothplatform-infoandprompt-browser(operator config merge andassets_pathoverride behave identically for both; the frozen Platform method budget is unchanged).apps/test-harness.html) gains aprompt-browserentry with sample library data and a command-awareuseresponder so the run flow is testable end to end.Acceptance criteria
tools/call+ui/message) and the repo's legacy-mode harness (ui/call-tool+ notification results), in light and dark modes.manage_promptresponses, which now expose the same store capabilities the portal REST layer uses (prompt.CollectionStore,prompt.UsageReader); no app-local organization model exists.Testing
make verifygreen (full CI-equivalent suite including race tests, coverage and patch-coverage gates, lint, gosec, govulncheck, semgrep, CodeQL, GoReleaser dry run).internal/platform/promptlayer/browse_test.gocovers batch usage population, usage read failure, collections inclusion, collections absence without the capability, collection read failure, and the search path with usage and collections;pkg/platform/platform_test.goasserts prompt-browser default registration (tool binding, resource URI, tool-to-app resolution) and operator config merge for the built-in.