check-manifests.mjs requires every manifest's top-level description to
match plugin.json. Codex renders its card from `interface`, so the short
card copy belongs in interface.shortDescription only.
Claude-Session: https://claude.ai/code/session_01Ez6AMbXYvU16LJHUSE7eSq
Hosts cache manifest metadata by version, so the shortened card
description from the previous commit needs a version change to
propagate to installed plugins.
Claude-Session: https://claude.ai/code/session_01Ez6AMbXYvU16LJHUSE7eSq
The old 132-char description truncated to "Upstash MCP server and
skills for ever..." in the marketplace card, telling a scanner nothing.
Replace it with "Redis and other Upstash products", which fits the
~33-char budget in both the full-width and two-column layouts and
matches the sentence-case register of neighbouring cards.
Shortening it drops the only mention of QStash, Vector, Workflow, Box
and Search from most manifests, so widen keywords with search, box,
cache and queue to keep those terms findable. The codex longDescription
still carries the full product list.
Claude-Session: https://claude.ai/code/session_01Ez6AMbXYvU16LJHUSE7eSq
* DX-2996 surface the MCP in plugin descriptions and ship the Codex icon
The manifests gained an MCP server but kept their skills-only descriptions,
and Codex installed the plugin with no Upstash icon because
`.codex-plugin/plugin.json` had an incomplete `interface` block.
- Descriptions across all six manifests (and the Claude/Cursor marketplace
entries) now lead with the MCP server, and are identical everywhere. They
had drifted into two different wordings before this.
- `.codex-plugin/plugin.json` gains the required `longDescription` and
`capabilities`, plus `logo`/`composerIcon` pointing at
`assets/upstash-icon-white-bg.png`, `brandColor` (#00C98D, sampled from the
icon), `defaultPrompt`, and the privacy/terms URLs. Drops the non-spec
`interface.repository`. This mirrors the asset layout redis/agent-skills
uses — Codex is the only client with an icon field, so the other manifests
cannot carry one.
- Category is "Developer Tools" for Codex and the .agents marketplace entry.
- Fills the gaps the icon audit turned up: `skills: "./skills/"` stated
explicitly for Claude/Codex/Cursor, `displayName`, `author.url`, and the
full metadata set (version, author, homepage, license, keywords, category,
tags) on both marketplace entries. Version bumped to 1.2.0 in lockstep.
Adds `scripts/check-manifests.mjs`, run by `npm run check`, so this drift
fails CI instead of shipping: it pins version/description/repository/license
across manifests, requires the description to mention MCP, requires every
client to point at https://mcp.upstash.com/mcp, and requires the Codex
interface block to be complete with logo files that actually exist.
Gitignores `opencode.json`. OpenCode reads it from the project root, so a
committed one would only configure OpenCode for people working inside a clone
of this repo — a personal dev setting the repo has no reason to ship.
Claude-Session: https://claude.ai/code/session_01FPx9e82XCTxDH1msNUAV1q
* DX-2996 title the plugin "Upstash Redis" for marketplace search
The skills and MCP cover every Upstash product and the descriptions still list
them all, but the title now leads with the flagship. Marketplace search is
largely name-driven, so a plugin called "Upstash" does not surface for people
browsing for "redis".
Sets `displayName` to "Upstash Redis" in the Claude and Cursor plugin.json and
in both marketplace entries, and `interface.displayName` for Codex. Cursor's
plugin.json had no display name at all, so it fell back to the slug.
Deliberately unchanged, and now asserted by the check script:
- `"name": "upstash"` — the install identifier behind
`/plugin install upstash@upstash` and `codex plugin marketplace add`.
Renaming it would break every install command in the README.
- `author.name` / `owner.name` — the company, not the plugin.
- The marketplace-level displayName, which names the vendor's marketplace
rather than the plugin inside it.
- Skill names, which AGENTS.md already rules out renaming for ranking.
AGENTS.md documents the title and the three things adjacent to it that must
not be renamed, including why this does not contradict the skills rule.
Claude-Session: https://claude.ai/code/session_01FPx9e82XCTxDH1msNUAV1q
* DX-2996 conform the Cursor manifests to their real schema, add $schema refs
Answering "does every client actually accept displayName?" turned up a bug I
introduced two commits ago. Cursor publishes real JSON Schemas
(github.com/cursor/plugins/schemas) and both are additionalProperties:false.
- `.cursor-plugin/marketplace.json` entries accept only name, source,
description and minClientVersions. The earlier commit added nine fields
Cursor rejects — displayName, version, author, homepage, repository,
license, keywords, category, tags — plus owner.url. All removed; the entry
now matches the shape Cursor's own marketplace uses.
- That metadata belongs in `.cursor-plugin/plugin.json`, which does take it.
Moved category and tags there.
- Cursor has a `logo` field, so the icon works there too. Earlier commits
claimed Codex was the only client with one; that was wrong, and the README
and AGENTS.md are corrected. Cursor's own plugins use a bare relative path
("assets/logo.png", no "./"), so ours matches.
$schema is added only where it is accepted:
- `.claude-plugin/plugin.json` — verified with `claude plugin validate`, which
passes with the key present. marketplace.json already had one.
- Cursor takes none: its schemas declare no $schema property under
additionalProperties:false, and none of Cursor's 65 official manifests carry
one. The check script now fails if someone adds it.
- Codex and Gemini CLI publish no schema URL, so neither gets one.
- plugin.json and mcp.json keep the agent-plugins.org URLs, the only ones that
actually serve JSON rather than a docs page.
AGENTS.md gains a per-client schema table and the two Cursor traps, so the
next person copies fields between manifests only after checking.
Claude-Session: https://claude.ai/code/session_01FPx9e82XCTxDH1msNUAV1q
* DX-2996 wire the remote Upstash MCP into the plugin manifests
Rather than a new skill, declare the hosted remote MCP server
(https://mcp.upstash.com/mcp, streamable HTTP, OAuth on first use — no
credentials in the manifest) so installing the plugin also registers the
MCP:
- Claude (.claude-plugin/plugin.json): mcpServers, type http + url
- Codex (.codex-plugin/plugin.json): mcpServers, type http + url
- Cursor (.cursor-plugin/plugin.json): mcpServers, url
- Gemini (gemini-extension.json): mcpServers, httpUrl
- Agent Plugins (agent-plugins.org): a sibling mcp.json, type streamable-http
+ url — plugin.json has no mcpServers field in its schema
Claude-Session: https://claude.ai/code/session_018mhLhJnvV8APHJfj2bF3gz
* DX-2996 overhaul the README to cover the MCP + skills surface
Explain the Upstash agent surface (remote MCP at mcp.upstash.com, local
stdio @upstash/mcp-server, and the per-SDK skills) with links to the docs;
describe the repo contents (skill sources, generated combined skill,
plugin manifests) and note the plugins now bundle the remote MCP over
OAuth so installing a plugin sets up skills + MCP together; add remote-MCP
connect snippets for popular clients and link the /clients docs page.
Claude-Session: https://claude.ai/code/session_018mhLhJnvV8APHJfj2bF3gz
Ratelimit was the one Upstash product with a skill but no matching keyword
in the plugin manifests. Added to all four so marketplace search and
keyword-based activation reach it.
* feat: add Agent Plugins portable manifest
Add a root plugin.json conforming to the Agent Plugins 1.0.0 spec
(https://agent-plugins.org). Skills are auto-discovered from skills/,
so no other changes are needed; there is no MCP server, so no mcp.json.
* chore(manifests): reorder product list in plugin descriptions
List products as Redis, QStash, Workflow, Box, Ratelimit, Vector,
Search in every manifest description. Also add the missing Ratelimit
to the Codex interface.shortDescription, and drop the undocumented
displayName and redundant skills override from the Cursor manifest.