feat: value-add curation layer (OpenAI Apps resubmission)#3
Open
lucaperret wants to merge 1 commit into
Open
Conversation
Additive layer to clear OpenAI's "thin wrapper / pass-through" rejection —
without changing any existing CLI command or MCP tool.
New module `src/curation/`:
- respond.ts — appResponse(): cross-client tool result (clean text + structuredContent
for Claude; _meta outputTemplate for ChatGPT widgets, ignored by Claude)
- aggregate.ts — analyze_library: playlist sizes/staleness, saved composition, cross-playlist
duplicates, "forgotten gems" (saved-but-in-no-playlist)
- resolve.ts — resolve engine: search -> best-match -> dedupe -> audio-quality flags
(LOSSLESS/HI-RES via mediaTags) -> lossless-only / deep-cuts filters; 45s deadline
- register.ts — 4 tools: analyze_library, curate_playlist, playlist_from_text (read-only
previews), create_playlist (the only write, non-destructive)
- components.ts — ChatGPT UI resources (ui://tidal/library-insights, ui://tidal/playlist-preview),
vanilla JS, served as MCP resources (text/html;profile=mcp-app)
Gating via TIDAL_MCP_PROFILE at the registration call sites:
full (default) -> existing 32 tools + prompts, UNCHANGED
app -> only the 4 curation tools (the scoped OpenAI submission surface)
all -> both
LLM-as-orchestrator: the host model does the taste/curation reasoning; the server only shapes
data, enforces constraints (lossless-only), resolves on Tidal, and writes. No server-side LLM,
only the official Tidal v2 API.
Cross-client: same tools work on Claude (text + structuredContent) and ChatGPT (widgets via _meta).
Additive-only: default profile is byte-identical to before (32 tools); curation excluded from the
npm CLI tarball. 42 new vitest tests (aggregate, resolve, MCP-protocol round-trip incl. resource
serving). Validated on real data: analyze_library + audiophile curate work; Tidal mediaTags carry
"LOSSLESS" so the lossless filter works without extra calls.
Note: the mcpb (stdio/Claude Desktop) gating exists locally but is not in this PR (mcpb/ is untracked
WIP). This PR targets the HTTP (Vercel) surface = the OpenAI submission endpoint.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
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.
Why
Our ChatGPT app was rejected (May 2026) as a thin wrapper / pass-through — it ported ~40 low-level Tidal tools. This adds a value-add curation layer so it clears OpenAI's bar, without changing any existing CLI command or MCP tool.
What (additive only)
New
src/curation/module + gating viaTIDAL_MCP_PROFILE:full(default) → the existing 32 tools + prompts, UNCHANGEDapp→ only the 4 value-add tools (the scoped OpenAI submission surface)all→ bothThe 4 tools
analyze_librarycurate_playlistaudiophile= lossless/hi-res only (the generic-chat-can't differentiator),deep_cuts,energy_arcplaylist_from_textcreate_playlistDesign
appResponse()→ clean text +structuredContent(Claude) +_metaoutput template (ChatGPT widgets, ignored by Claude). Widgets served as MCP resources (ui://tidal/library-insights,ui://tidal/playlist-preview,text/html;profile=mcp-app).structuredContent; the model-facing summary stays clean.Non-regression (verified)
app= exactly the 4 curation tools;all= 36.next build(site, with curation) succeeds; curation excluded from the npm CLI tarball.mediaTagscarry"LOSSLESS"→ lossless filter works with no extra calls.Scope notes
mcpb/is untracked WIP).app(would drop the 32 tools for current Claude/Smithery users). Deploy the OpenAI app as a separateapp-profile endpoint (seeDEPLOY_CHATGPT.md).OPENAI_RESUBMISSION.md(resubmission notes),DEPLOY_CHATGPT.md(deploy + ChatGPT test guide).🤖 Generated with Claude Code