Skip to content

feat(prompts): prompt browser MCP App - search, preview, argument forms, run from chat#1026

Merged
cjimti merged 1 commit into
mainfrom
feat/1011-prompt-browser-app
Jul 22, 2026
Merged

feat(prompts): prompt browser MCP App - search, preview, argument forms, run from chat#1026
cjimti merged 1 commit into
mainfrom
feat/1011-prompt-browser-app

Conversation

@cjimti

@cjimti cjimti commented Jul 22, 2026

Copy link
Copy Markdown
Member

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-browser MCP App, embedded in the binary and bound to the manage_prompt tool through the mcpapps registry (_meta.ui injection, 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)

  • App-initiated tool calls are the guaranteed channel: tools/call is in the SEP-1865 allowed message subset, and the shipped platform-info app proves the legacy ui/call-tool variant works in claude.ai today.
  • Conversation insertion (ui/message) is defined by the spec and advertised per host via hostCapabilities.message in the ui/initialize result; per-host support is not publicly documented, so the app feature-detects it at runtime.
  • Triggering prompts/get from 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.go and registered as a second built-in alongside platform-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 use with the stable mcp:prompt:<id> handle and the filled arguments; the server substitutes arguments, records the prompt_serve audit event, and returns the rendered content with provenance. The app then attempts ui/message insertion of the rendered prompt (full timeout when the host advertised the message capability, 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/call with JSON-RPC id-correlated responses, hostCapabilities feature detection) and legacy 2025-01-09 hosts such as current claude.ai (ui/call-tool with results delivered as ui/notifications/tool-result and 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 through textContent/createTextNode; there is no HTML injection path.

Server-side changes

  • manage_prompt list and search responses now batch-apply audit-derived usage (run_count, last_run_at) to every returned prompt in one PromptUsage read, and include the shared collections list 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/promptlayer exports ToolNameManagePrompt so the composition root binds the app without a duplicated string.
  • Built-in app registration in pkg/platform is factored into shared builtinAppDefinition / registerBuiltinApp free functions used by both platform-info and prompt-browser (operator config merge and assets_path override behave identically for both; the frozen Platform method budget is unchanged).
  • The dev test harness (apps/test-harness.html) gains a prompt-browser entry with sample library data and a command-aware use responder so the run flow is testable end to end.

Acceptance criteria

  • Capability check documented on the issue with its outcome before implementation: done (link above).
  • App-capable client renders the browser with search, filter, preview, argument forms, and run without typing a machine name: verified in Chrome against a spec-mode host harness (tools/call + ui/message) and the repo's legacy-mode harness (ui/call-tool + notification results), in light and dark modes.
  • Non-app clients get the same information: the bound tool returns the identical JSON payloads; the usage and collections enrichment lands in the tool result itself, not in the app.
  • Same search, collection, and facet APIs as the portal: the app reads collections and usage from the manage_prompt responses, which now expose the same store capabilities the portal REST layer uses (prompt.CollectionStore, prompt.UsageReader); no app-local organization model exists.
  • Provenance and usage visible before running: version, status, approver with date, and run count appear on cards and in the detail provenance panel.

Testing

  • make verify green (full CI-equivalent suite including race tests, coverage and patch-coverage gates, lint, gosec, govulncheck, semgrep, CodeQL, GoReleaser dry run).
  • New unit tests: internal/platform/promptlayer/browse_test.go covers 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.go asserts prompt-browser default registration (tool binding, resource URI, tool-to-app resolution) and operator config merge for the built-in.
  • Live browser verification of both host protocols via the test harness: initial load, search, buckets, collection and tag filters, empty states, required-argument validation, live placeholder substitution (single and double brace), run with conversation insertion on the spec host, and the copy fallback on the legacy host.

…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

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.95238% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.34%. Comparing base (7e36b97) to head (d89bfa2).

Files with missing lines Patch % Lines
pkg/platform/platform.go 64.00% 5 Missing and 4 partials ⚠️
internal/platform/promptlayer/serve.go 86.66% 1 Missing and 1 partial ⚠️
internal/platform/promptlayer/tool.go 95.65% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cjimti
cjimti merged commit b67a6ec into main Jul 22, 2026
10 checks passed
@cjimti
cjimti deleted the feat/1011-prompt-browser-app branch July 22, 2026 23:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

prompts: prompt browser MCP App - search, preview, argument forms, run from chat

1 participant