From fff1f488d27366bcedf0a7812e0f27e5f4e436a7 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Fri, 11 Sep 2026 15:41:30 +1000 Subject: [PATCH 01/22] claude md --- claude/README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 claude/README.md diff --git a/claude/README.md b/claude/README.md new file mode 100644 index 0000000..584f776 --- /dev/null +++ b/claude/README.md @@ -0,0 +1,29 @@ +# ReadMe Plugin for Claude Code + +This repository provides an official Claude Code plugin that bundles: +- **ReadMe Skills** that teach Claude how to work intelligently inside your ReadMe project +- The ReadMe MCP Server, which enabled Claude to securely search, read, and update your ReadMe projects + +This plugin allows Claude Code users to install everything β€” Skills + MCP server β€” with **one click**. + +--- + +## πŸš€ Features +βœ… Fully packaged ReadMe Skills +βœ… Integrated ReadMe MCP Server + +--- + +## Installation (Claude Code) +### 1. Add this plugin's marketplace +In Claude Code, run: +`/plugin marketplace add readmeio/readme-claude-plugin` +### 2. Install the plugin +`/plugin install readme@readme +### 3. Restart Claude Code +This ensures the MCP server starts correctly. + +--- + +## πŸ”‘ Authentication +The ReadMe MCP server supports per project **API key**. \ No newline at end of file From fe99a061bad89ff940c8d403544f5fe220dbe6f7 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Fri, 11 Sep 2026 15:44:02 +1000 Subject: [PATCH 02/22] plugin configs --- claude/.claude-plugin/marketplace.json | 14 ++++++++++++++ claude/.claude-plugin/plugin.json | 10 ++++++++++ claude/.mcp.json | 11 +++++++++++ 3 files changed, 35 insertions(+) create mode 100644 claude/.claude-plugin/marketplace.json create mode 100644 claude/.claude-plugin/plugin.json create mode 100644 claude/.mcp.json diff --git a/claude/.claude-plugin/marketplace.json b/claude/.claude-plugin/marketplace.json new file mode 100644 index 0000000..8dd9f82 --- /dev/null +++ b/claude/.claude-plugin/marketplace.json @@ -0,0 +1,14 @@ +{ + "name": "readme", + "description": "ReadMe plugins for Claude Code", + "owner": { "name": "ReadMe", "url": "https://readme.com" }, + "plugins": [ + { + "name": "readme", + "description": "ReadMe MCP server packaged as a plugin. Search, read, and update your ReadMe docs and API reference from your editor.", + "category": "productivity", + "source": "./", + "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server" + } + ] +} diff --git a/claude/.claude-plugin/plugin.json b/claude/.claude-plugin/plugin.json new file mode 100644 index 0000000..43025bf --- /dev/null +++ b/claude/.claude-plugin/plugin.json @@ -0,0 +1,10 @@ +{ + "name": "readme", + "version": "0.1.0", + "description": "ReadMe MCP server packaged as a plugin. Search, read, and update your ReadMe docs and API reference from your editor.", + "author": { "name": "ReadMe", "url": "https://readme.com" }, + "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server", + "repository": "https://github.com/readmeio/readme-claude-plugin", + "license": "MIT", + "keywords": ["readme", "documentation", "mcp", "openapi"] +} diff --git a/claude/.mcp.json b/claude/.mcp.json new file mode 100644 index 0000000..11cd740 --- /dev/null +++ b/claude/.mcp.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "readme": { + "type": "http", + "url": "https://docs.readme.com/mcp", + "headers": { + "Authorization": "Bearer ${README_API_KEY:-}" + } + } + } +} From f1f42f2d5d824e02fd4a80cfe7827bc1ef8c0c94 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Fri, 11 Sep 2026 16:33:38 +1000 Subject: [PATCH 03/22] skills --- claude/skills/onboarding/SKILL.md | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 claude/skills/onboarding/SKILL.md diff --git a/claude/skills/onboarding/SKILL.md b/claude/skills/onboarding/SKILL.md new file mode 100644 index 0000000..72f33a3 --- /dev/null +++ b/claude/skills/onboarding/SKILL.md @@ -0,0 +1,49 @@ +--- +name: onboarding +description: Get a new customer from zero to a live ReadMe developer hub. Use when someone is new to ReadMe, asks what ReadMe is, wants to sign up, create a project, publish their first API reference or guide, or needs an API key for this plugin. Explains the product and walks the web-UI setup flow. +--- + +# ReadMe onboarding + +> Onboarding endpoints are coming soon. Until then this skill only covers the web-UI flow and ReadMe basics. + +## What ReadMe is + +ReadMe hosts a developer hub for your API at `{subdomain}.readme.io` or a custom domain. One hub contains: + +| Section | Content | +| --- | --- | +| Guides | Markdown pages in categories, with a sidebar | +| API Reference | Interactive docs generated from an OpenAPI or Swagger definition, with a Try It console | +| Recipes | Step-by-step code walkthroughs | +| Changelog | Release notes, shared across versions | +| Custom Pages | Free-form Markdown or HTML pages | + +Guides, reference, recipes and custom pages live on a **branch** (a version such as `1.0` or `stable`). The changelog does not. Ask AI and the project's MCP server answer questions from the hub content. Metrics track page views, search, page quality, and, with SDK setup, API calls. + +Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and Developer Metrics API reads. + +## Quick Start + +1. Sign up at `https://dash.readme.com/signup`. +2. Click **Create New Project**. Set a name, upload a logo (ReadMe picks brand colors from it), and choose the subdomain. +3. Add the API definition under **API Reference**: upload an OpenAPI file, import a URL, build one from scratch, or run `npx rdme openapi upload ` from a terminal. ReadMe validates the file and renders every endpoint. +4. Write the first guide under **Guides**. Use the AI Agent for a draft or the editor for a blank page. A "Getting Started" page is the usual first one. +5. Generate an API key at **Configuration β†’ API Keys**, URL `https://dash.readme.com/project/{subdomain}/v{version}/api-key`. +6. Export it as `README_API_KEY` in the shell that starts the editor, then restart the editor so the plugin picks it up. +7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. A 500 titled `An unknown error has occurred.` means the key is missing or wrong; go back to step 5. + +After step 7, load the `readme-api` skill for anything else in the project. + +## Reading the docs meanwhile + +Use `readme:search` for a question, then `readme:fetch` with the returned id. Useful pages: + +| Id | Page | +| --- | --- | +| `main/quickstart` | Three-step setup | +| `main/creating-a-project` | Project settings on creation | +| `main/openapi-upload-and-management` | Upload, sync, and re-sync an OpenAPI file | +| `main/branches` | How branches and versions work | +| `ref:main/intro-to-the-readme-api` | API v2 overview and auth | +| `main/sdks` | Metrics SDKs for API logs | From 8017d45b5ea8d604aef7b035d8488bd36101fe0a Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Fri, 11 Sep 2026 16:36:45 +1000 Subject: [PATCH 04/22] onboarding: mention claude in chrome --- claude/skills/onboarding/SKILL.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/claude/skills/onboarding/SKILL.md b/claude/skills/onboarding/SKILL.md index 72f33a3..89a6dda 100644 --- a/claude/skills/onboarding/SKILL.md +++ b/claude/skills/onboarding/SKILL.md @@ -35,6 +35,10 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D After step 7, load the `readme-api` skill for anything else in the project. +## Doing it with Claude in Chrome + +Steps 1 to 5 are all browser work. If the Claude in Chrome extension is connected (`mcp__claude-in-chrome__*` tools are available), offer to drive them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. + ## Reading the docs meanwhile Use `readme:search` for a question, then `readme:fetch` with the returned id. Useful pages: From 7342db92502f85ed1394682871d25d9d520ceb1d Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:07:31 +1000 Subject: [PATCH 05/22] address comments --- claude/.claude-plugin/marketplace.json | 2 +- claude/.mcp.json | 5 +--- claude/README.md | 41 +++++++++++++++++++++++--- claude/skills/onboarding/SKILL.md | 21 ++++++++++++- 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/claude/.claude-plugin/marketplace.json b/claude/.claude-plugin/marketplace.json index 8dd9f82..3907c53 100644 --- a/claude/.claude-plugin/marketplace.json +++ b/claude/.claude-plugin/marketplace.json @@ -1,6 +1,6 @@ { "name": "readme", - "description": "ReadMe plugins for Claude Code", + "description": "ReadMe plugins for Claude", "owner": { "name": "ReadMe", "url": "https://readme.com" }, "plugins": [ { diff --git a/claude/.mcp.json b/claude/.mcp.json index 11cd740..59156bc 100644 --- a/claude/.mcp.json +++ b/claude/.mcp.json @@ -2,10 +2,7 @@ "mcpServers": { "readme": { "type": "http", - "url": "https://docs.readme.com/mcp", - "headers": { - "Authorization": "Bearer ${README_API_KEY:-}" - } + "url": "https://docs.readme.com/mcp" } } } diff --git a/claude/README.md b/claude/README.md index 584f776..abcb861 100644 --- a/claude/README.md +++ b/claude/README.md @@ -1,10 +1,10 @@ -# ReadMe Plugin for Claude Code +# ReadMe Plugin for Claude -This repository provides an official Claude Code plugin that bundles: +This repository provides an official Claude plugin that bundles: - **ReadMe Skills** that teach Claude how to work intelligently inside your ReadMe project - The ReadMe MCP Server, which enabled Claude to securely search, read, and update your ReadMe projects -This plugin allows Claude Code users to install everything β€” Skills + MCP server β€” with **one click**. +This plugin allows Claude users to install everything β€” Skills + MCP server β€” with **one click**. --- @@ -23,7 +23,40 @@ In Claude Code, run: ### 3. Restart Claude Code This ensures the MCP server starts correctly. +The **Code** tab of the Claude Desktop app is Claude Code, so these steps apply there too. + +--- + +## Installation (Claude Desktop Chat, Cowork, claude.ai) +The Chat and Cowork tabs of Claude Desktop and claude.ai share one plugin system. There is no `/plugin` command; plugins are managed from the **Customize** menu. Plugins need a paid plan (Pro, Max, Team or Enterprise). +### 1. Open the Plugins page +Click **Customize** in the left sidebar, then **Plugins**. In Cowork, open the **Cowork** tab first. +### 2. Add this plugin's marketplace +Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/readme-plugins`. +### 3. Install the plugin +Find **readme** in the list and click **Install**. Open it afterwards to see its skills and the ReadMe connector; each one can be toggled individually. +### 4. Use it +Type `/` in a chat or click **+** to pick a ReadMe skill. No restart is needed. Click **Update** on the marketplace to pull new versions. + +Notes: +- The ReadMe connector runs from Anthropic's cloud, not your machine, so an API key exported in your shell is not picked up here. Read tools work on public projects. Write tools need an authenticated connection, which this plugin cannot provide on these surfaces yet. +- On Team and Enterprise plans an owner may have turned off personal marketplaces. Ask them to add this marketplace under **Organization settings β†’ Plugins**. +- Claude cannot install the plugin for you on these surfaces. If you paste a ReadMe skill into a chat before installing, it will walk you through the steps above. + --- ## πŸ”‘ Authentication -The ReadMe MCP server supports per project **API key**. \ No newline at end of file +The plugin connects to the ReadMe MCP server anonymously. Read tools work on public projects without any setup. Write tools such as `update-docs` need your project's **API key**, found under **Configuration β†’ API Keys** in your ReadMe dashboard. + +The plugin cannot read the key itself. In Claude Code, register the server once under the same name, which replaces the plugin's anonymous one: + +``` +export README_API_KEY=rdme_… +claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}' +``` + +Keep the single quotes so Claude Code expands the variable at startup instead of writing the key into its config. Export `README_API_KEY` in the shell that launches Claude Code, then restart it. The skills keep working because the server name is unchanged. + +One key maps to one project. To switch projects, change the exported key and restart. + +Claude Desktop Chat, Cowork and claude.ai cannot take an API key, so the plugin stays read-only there. \ No newline at end of file diff --git a/claude/skills/onboarding/SKILL.md b/claude/skills/onboarding/SKILL.md index 89a6dda..81e6b0d 100644 --- a/claude/skills/onboarding/SKILL.md +++ b/claude/skills/onboarding/SKILL.md @@ -30,7 +30,14 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D 3. Add the API definition under **API Reference**: upload an OpenAPI file, import a URL, build one from scratch, or run `npx rdme openapi upload ` from a terminal. ReadMe validates the file and renders every endpoint. 4. Write the first guide under **Guides**. Use the AI Agent for a draft or the editor for a blank page. A "Getting Started" page is the usual first one. 5. Generate an API key at **Configuration β†’ API Keys**, URL `https://dash.readme.com/project/{subdomain}/v{version}/api-key`. -6. Export it as `README_API_KEY` in the shell that starts the editor, then restart the editor so the plugin picks it up. +6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server with the same name at user scope, which replaces the plugin's one, then exports the key in the shell that starts the editor and restarts it. In Claude Code: + + ``` + export README_API_KEY=rdme_… + claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}' + ``` + + Keep the single quotes: Claude Code expands `${README_API_KEY}` when it starts, so the key never lands in a config file. In Codex: `codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY`. Not possible in Claude Desktop Chat, Cowork or claude.ai; see the section below. 7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. A 500 titled `An unknown error has occurred.` means the key is missing or wrong; go back to step 5. After step 7, load the `readme-api` skill for anything else in the project. @@ -39,6 +46,18 @@ After step 7, load the `readme-api` skill for anything else in the project. Steps 1 to 5 are all browser work. If the Claude in Chrome extension is connected (`mcp__claude-in-chrome__*` tools are available), offer to drive them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. +## When you cannot install anything yourself + +In Claude Desktop Chat, Cowork and claude.ai you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands. If the `readme:*` tools are missing, the user has to install the plugin by hand. Give them these steps exactly: + +1. Click **Customize** in the left sidebar, then **Plugins**. In Cowork, open the **Cowork** tab first. +2. Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/readme-plugins`. +3. Find **readme** in the list and click **Install**, then start a new chat so the tools load. + +Plugins need a paid Claude plan. On Team and Enterprise an owner may have disabled personal marketplaces, in which case they add it under **Organization settings β†’ Plugins**. + +Once installed, the ReadMe connector on these surfaces is read-only: `readme:search`, `readme:fetch` and the endpoint tools work on public projects, but there is no way to supply `README_API_KEY`, so steps 6 and 7 of the Quick Start do not apply and write tools such as `readme:update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in Claude Code, Codex or Cursor with the server registered as in step 6. + ## Reading the docs meanwhile Use `readme:search` for a question, then `readme:fetch` with the returned id. Useful pages: From 964f3b8d186afc8d4aadcd1e3a8fc943149641de Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Tue, 15 Sep 2026 07:46:53 +1000 Subject: [PATCH 06/22] point the marketplace at agent-plugins Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01KDoRbmzuRVJ6Ev9MPEmLm5 --- claude/README.md | 2 +- claude/skills/onboarding/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/claude/README.md b/claude/README.md index abcb861..fb286e4 100644 --- a/claude/README.md +++ b/claude/README.md @@ -32,7 +32,7 @@ The Chat and Cowork tabs of Claude Desktop and claude.ai share one plugin system ### 1. Open the Plugins page Click **Customize** in the left sidebar, then **Plugins**. In Cowork, open the **Cowork** tab first. ### 2. Add this plugin's marketplace -Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/readme-plugins`. +Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/agent-plugins`. ### 3. Install the plugin Find **readme** in the list and click **Install**. Open it afterwards to see its skills and the ReadMe connector; each one can be toggled individually. ### 4. Use it diff --git a/claude/skills/onboarding/SKILL.md b/claude/skills/onboarding/SKILL.md index 81e6b0d..3c989b7 100644 --- a/claude/skills/onboarding/SKILL.md +++ b/claude/skills/onboarding/SKILL.md @@ -51,7 +51,7 @@ Steps 1 to 5 are all browser work. If the Claude in Chrome extension is connecte In Claude Desktop Chat, Cowork and claude.ai you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands. If the `readme:*` tools are missing, the user has to install the plugin by hand. Give them these steps exactly: 1. Click **Customize** in the left sidebar, then **Plugins**. In Cowork, open the **Cowork** tab first. -2. Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/readme-plugins`. +2. Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/agent-plugins`. 3. Find **readme** in the list and click **Install**, then start a new chat so the tools load. Plugins need a paid Claude plan. On Team and Enterprise an owner may have disabled personal marketplaces, in which case they add it under **Organization settings β†’ Plugins**. From 078215fbe34c617aa1b5b789db3ef408fe31e673 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Tue, 15 Sep 2026 07:56:20 +1000 Subject: [PATCH 07/22] serve the marketplace from the repo root Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01KDoRbmzuRVJ6Ev9MPEmLm5 --- {claude/.claude-plugin => .claude-plugin}/marketplace.json | 2 +- claude/.claude-plugin/plugin.json | 2 +- claude/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename {claude/.claude-plugin => .claude-plugin}/marketplace.json (93%) diff --git a/claude/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json similarity index 93% rename from claude/.claude-plugin/marketplace.json rename to .claude-plugin/marketplace.json index 3907c53..2b2161a 100644 --- a/claude/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -7,7 +7,7 @@ "name": "readme", "description": "ReadMe MCP server packaged as a plugin. Search, read, and update your ReadMe docs and API reference from your editor.", "category": "productivity", - "source": "./", + "source": "./claude", "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server" } ] diff --git a/claude/.claude-plugin/plugin.json b/claude/.claude-plugin/plugin.json index 43025bf..4cc58b9 100644 --- a/claude/.claude-plugin/plugin.json +++ b/claude/.claude-plugin/plugin.json @@ -4,7 +4,7 @@ "description": "ReadMe MCP server packaged as a plugin. Search, read, and update your ReadMe docs and API reference from your editor.", "author": { "name": "ReadMe", "url": "https://readme.com" }, "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server", - "repository": "https://github.com/readmeio/readme-claude-plugin", + "repository": "https://github.com/readmeio/agent-plugins", "license": "MIT", "keywords": ["readme", "documentation", "mcp", "openapi"] } diff --git a/claude/README.md b/claude/README.md index fb286e4..e20ef8f 100644 --- a/claude/README.md +++ b/claude/README.md @@ -17,7 +17,7 @@ This plugin allows Claude users to install everything β€” Skills + MCP server ## Installation (Claude Code) ### 1. Add this plugin's marketplace In Claude Code, run: -`/plugin marketplace add readmeio/readme-claude-plugin` +`/plugin marketplace add readmeio/agent-plugins` ### 2. Install the plugin `/plugin install readme@readme ### 3. Restart Claude Code From 9a792f3ff675260da6b6bed9da33153e1163cdb4 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Wed, 16 Sep 2026 14:40:35 +1000 Subject: [PATCH 08/22] fix(claude): close the install command backtick and release as 1.0.0 The install line rendered as raw text. Versions now agree across the three plugin manifests, matching the 1.0.0 the Cursor changelog already documents. --- claude/.claude-plugin/plugin.json | 2 +- claude/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/claude/.claude-plugin/plugin.json b/claude/.claude-plugin/plugin.json index 4cc58b9..a5c880b 100644 --- a/claude/.claude-plugin/plugin.json +++ b/claude/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "readme", - "version": "0.1.0", + "version": "1.0.0", "description": "ReadMe MCP server packaged as a plugin. Search, read, and update your ReadMe docs and API reference from your editor.", "author": { "name": "ReadMe", "url": "https://readme.com" }, "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server", diff --git a/claude/README.md b/claude/README.md index e20ef8f..8ae4d7e 100644 --- a/claude/README.md +++ b/claude/README.md @@ -19,7 +19,7 @@ This plugin allows Claude users to install everything β€” Skills + MCP server In Claude Code, run: `/plugin marketplace add readmeio/agent-plugins` ### 2. Install the plugin -`/plugin install readme@readme +`/plugin install readme@readme` ### 3. Restart Claude Code This ensures the MCP server starts correctly. From 7e9d47164d882fb3ca220813eb10e62e5cf9e70a Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Thu, 17 Sep 2026 13:03:01 +1000 Subject: [PATCH 09/22] docs(onboarding): drop the pointer to a skill this plugin does not ship Co-Authored-By: Claude Opus 5 --- claude/skills/onboarding/SKILL.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/claude/skills/onboarding/SKILL.md b/claude/skills/onboarding/SKILL.md index 3c989b7..d5a0167 100644 --- a/claude/skills/onboarding/SKILL.md +++ b/claude/skills/onboarding/SKILL.md @@ -40,8 +40,6 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D Keep the single quotes: Claude Code expands `${README_API_KEY}` when it starts, so the key never lands in a config file. In Codex: `codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY`. Not possible in Claude Desktop Chat, Cowork or claude.ai; see the section below. 7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. A 500 titled `An unknown error has occurred.` means the key is missing or wrong; go back to step 5. -After step 7, load the `readme-api` skill for anything else in the project. - ## Doing it with Claude in Chrome Steps 1 to 5 are all browser work. If the Claude in Chrome extension is connected (`mcp__claude-in-chrome__*` tools are available), offer to drive them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. From de9cf13abd30c59517dead94a611a0f0942194c3 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Fri, 11 Sep 2026 16:43:59 +1000 Subject: [PATCH 10/22] codex plugin --- .agents/plugins/marketplace.json | 12 ++++++++ codex/LICENSE | 21 +++++++++++++ codex/README.md | 27 ++++++++++++++++ codex/mcp.json | 9 ++++++ codex/plugin.json | 30 ++++++++++++++++++ codex/skills/onboarding/SKILL.md | 53 ++++++++++++++++++++++++++++++++ 6 files changed, 152 insertions(+) create mode 100644 .agents/plugins/marketplace.json create mode 100644 codex/LICENSE create mode 100644 codex/README.md create mode 100644 codex/mcp.json create mode 100644 codex/plugin.json create mode 100644 codex/skills/onboarding/SKILL.md diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json new file mode 100644 index 0000000..800546b --- /dev/null +++ b/.agents/plugins/marketplace.json @@ -0,0 +1,12 @@ +{ + "name": "readme", + "interface": { "displayName": "ReadMe" }, + "plugins": [ + { + "name": "readme", + "source": { "source": "local", "path": "./codex" }, + "policy": { "installation": "AVAILABLE" }, + "category": "Productivity" + } + ] +} diff --git a/codex/LICENSE b/codex/LICENSE new file mode 100644 index 0000000..5cb285b --- /dev/null +++ b/codex/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 ReadMe + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/codex/README.md b/codex/README.md new file mode 100644 index 0000000..7725051 --- /dev/null +++ b/codex/README.md @@ -0,0 +1,27 @@ +# ReadMe plugin for ChatGPT and Codex + +Connects ChatGPT and Codex to the [ReadMe MCP server](https://docs.readme.com/main/docs/readmes-mcp-server) so the model can search, read, and update your ReadMe docs and API reference. + +## Install + +The repository root is a Codex plugin marketplace. Add it, then install the plugin: + +``` +codex plugin marketplace add readmeio/readme-plugins +codex plugin add readme@readme +``` + +For a local checkout, pass the checkout path to `codex plugin marketplace add` instead. Start a new Codex session after installing so the skills and MCP server load. + +## Authentication + +Public read access works without any setup. + +Write tools such as `update-docs` need your ReadMe API key. Codex strips `Authorization` headers from plugin MCP configs, so register the server yourself once with the key read from an environment variable: + +``` +export README_API_KEY=rdme_… +codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY +``` + +Your `readme` entry replaces the plugin's anonymous one. The skills keep working because the server name is unchanged. Find your key under **Configuration β†’ API Keys** in your ReadMe project dashboard. diff --git a/codex/mcp.json b/codex/mcp.json new file mode 100644 index 0000000..7abb4ee --- /dev/null +++ b/codex/mcp.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json", + "mcpServers": { + "readme": { + "type": "streamable-http", + "url": "https://docs.readme.com/mcp" + } + } +} diff --git a/codex/plugin.json b/codex/plugin.json new file mode 100644 index 0000000..08b9188 --- /dev/null +++ b/codex/plugin.json @@ -0,0 +1,30 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "readme", + "version": "0.1.0", + "description": "ReadMe MCP server packaged as a plugin. Search, read, and update your ReadMe docs and API reference from your editor.", + "author": { "name": "ReadMe", "url": "https://readme.com" }, + "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server", + "repository": "https://github.com/readmeio/readme-plugins", + "license": "MIT", + "keywords": ["readme", "documentation", "mcp", "openapi"], + "extensions": { + "com.openai": { + "interface": { + "displayName": "ReadMe", + "shortDescription": "Search, read, and update your ReadMe docs and API reference.", + "longDescription": "Connects ChatGPT and Codex to the ReadMe MCP server so the model can list API specs, inspect endpoints, search documentation, and follow ReadMe's documentation workflows.", + "developerName": "ReadMe", + "category": "Productivity", + "capabilities": ["Read"], + "websiteURL": "https://readme.com", + "privacyPolicyURL": "https://readme.com/privacy", + "termsOfServiceURL": "https://readme.com/tos", + "defaultPrompt": [ + "Use ReadMe to list the endpoints in the ReadMe API.", + "Use ReadMe to explain how to create a docs branch." + ] + } + } + } +} diff --git a/codex/skills/onboarding/SKILL.md b/codex/skills/onboarding/SKILL.md new file mode 100644 index 0000000..89a6dda --- /dev/null +++ b/codex/skills/onboarding/SKILL.md @@ -0,0 +1,53 @@ +--- +name: onboarding +description: Get a new customer from zero to a live ReadMe developer hub. Use when someone is new to ReadMe, asks what ReadMe is, wants to sign up, create a project, publish their first API reference or guide, or needs an API key for this plugin. Explains the product and walks the web-UI setup flow. +--- + +# ReadMe onboarding + +> Onboarding endpoints are coming soon. Until then this skill only covers the web-UI flow and ReadMe basics. + +## What ReadMe is + +ReadMe hosts a developer hub for your API at `{subdomain}.readme.io` or a custom domain. One hub contains: + +| Section | Content | +| --- | --- | +| Guides | Markdown pages in categories, with a sidebar | +| API Reference | Interactive docs generated from an OpenAPI or Swagger definition, with a Try It console | +| Recipes | Step-by-step code walkthroughs | +| Changelog | Release notes, shared across versions | +| Custom Pages | Free-form Markdown or HTML pages | + +Guides, reference, recipes and custom pages live on a **branch** (a version such as `1.0` or `stable`). The changelog does not. Ask AI and the project's MCP server answer questions from the hub content. Metrics track page views, search, page quality, and, with SDK setup, API calls. + +Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and Developer Metrics API reads. + +## Quick Start + +1. Sign up at `https://dash.readme.com/signup`. +2. Click **Create New Project**. Set a name, upload a logo (ReadMe picks brand colors from it), and choose the subdomain. +3. Add the API definition under **API Reference**: upload an OpenAPI file, import a URL, build one from scratch, or run `npx rdme openapi upload ` from a terminal. ReadMe validates the file and renders every endpoint. +4. Write the first guide under **Guides**. Use the AI Agent for a draft or the editor for a blank page. A "Getting Started" page is the usual first one. +5. Generate an API key at **Configuration β†’ API Keys**, URL `https://dash.readme.com/project/{subdomain}/v{version}/api-key`. +6. Export it as `README_API_KEY` in the shell that starts the editor, then restart the editor so the plugin picks it up. +7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. A 500 titled `An unknown error has occurred.` means the key is missing or wrong; go back to step 5. + +After step 7, load the `readme-api` skill for anything else in the project. + +## Doing it with Claude in Chrome + +Steps 1 to 5 are all browser work. If the Claude in Chrome extension is connected (`mcp__claude-in-chrome__*` tools are available), offer to drive them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. + +## Reading the docs meanwhile + +Use `readme:search` for a question, then `readme:fetch` with the returned id. Useful pages: + +| Id | Page | +| --- | --- | +| `main/quickstart` | Three-step setup | +| `main/creating-a-project` | Project settings on creation | +| `main/openapi-upload-and-management` | Upload, sync, and re-sync an OpenAPI file | +| `main/branches` | How branches and versions work | +| `ref:main/intro-to-the-readme-api` | API v2 overview and auth | +| `main/sdks` | Metrics SDKs for API logs | From f65053a0f5ca8f6a3deb78a88abac1ab0c403824 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:35:05 +1000 Subject: [PATCH 11/22] codex: sync skills and add chatgpt sections --- codex/skills/onboarding/SKILL.md | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/codex/skills/onboarding/SKILL.md b/codex/skills/onboarding/SKILL.md index 89a6dda..613924c 100644 --- a/codex/skills/onboarding/SKILL.md +++ b/codex/skills/onboarding/SKILL.md @@ -30,14 +30,30 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D 3. Add the API definition under **API Reference**: upload an OpenAPI file, import a URL, build one from scratch, or run `npx rdme openapi upload ` from a terminal. ReadMe validates the file and renders every endpoint. 4. Write the first guide under **Guides**. Use the AI Agent for a draft or the editor for a blank page. A "Getting Started" page is the usual first one. 5. Generate an API key at **Configuration β†’ API Keys**, URL `https://dash.readme.com/project/{subdomain}/v{version}/api-key`. -6. Export it as `README_API_KEY` in the shell that starts the editor, then restart the editor so the plugin picks it up. +6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server with the same name, which replaces the plugin's one, then exports the key in the shell that starts Codex and starts a new session. In Codex: + + ``` + export README_API_KEY=rdme_… + codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY + ``` + + Codex reads the variable at startup, so the key never lands in a config file. The ChatGPT desktop app shares Codex's config, so this registration also covers Codex sessions there. In Claude Code the equivalent is `claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}'`. Not possible in ChatGPT web; see the section below. 7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. A 500 titled `An unknown error has occurred.` means the key is missing or wrong; go back to step 5. After step 7, load the `readme-api` skill for anything else in the project. -## Doing it with Claude in Chrome +## Doing it with the ChatGPT browser + +Steps 1 to 5 are all browser work. In the ChatGPT desktop app or ChatGPT web, offer to drive them with `@Browser` instead of only listing the steps: open the signup page, create the project, and open the API Keys page. The built-in browser has its own profile, so the user signs in to ReadMe there and types credentials and payment details themselves; ChatGPT asks before submitting forms. It cannot upload files, so for step 3 import the OpenAPI definition by URL or run `npx rdme openapi upload ` from Codex. Codex CLI and the IDE extension have no browser; list the steps there. Steps 6 and 7 stay in the terminal. + +## When you cannot install anything yourself + +In a ChatGPT chat, desktop or web, you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands in the chat. If the `readme:*` tools are missing, the user has to install the plugin by hand. Give them these steps exactly: + +- ChatGPT desktop app: open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/readme-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load. +- ChatGPT web: only the plugin directory is available. Until the ReadMe plugin is listed there, send the user to the desktop app or to Codex CLI. -Steps 1 to 5 are all browser work. If the Claude in Chrome extension is connected (`mcp__claude-in-chrome__*` tools are available), offer to drive them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. +Once installed, the ReadMe connector in a chat is read-only: `readme:search`, `readme:fetch` and the endpoint tools work on public projects, but ChatGPT cannot take an API key, so steps 6 and 7 of the Quick Start do not apply and write tools such as `readme:update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in Codex with the server registered as in step 6. ## Reading the docs meanwhile From f2483a5ee61d4902d536e8ac5c2c40e5635ff0ab Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:42:40 +1000 Subject: [PATCH 12/22] codex: chatgpt web developer mode path --- codex/skills/onboarding/SKILL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codex/skills/onboarding/SKILL.md b/codex/skills/onboarding/SKILL.md index 613924c..295f283 100644 --- a/codex/skills/onboarding/SKILL.md +++ b/codex/skills/onboarding/SKILL.md @@ -51,7 +51,7 @@ Steps 1 to 5 are all browser work. In the ChatGPT desktop app or ChatGPT web, of In a ChatGPT chat, desktop or web, you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands in the chat. If the `readme:*` tools are missing, the user has to install the plugin by hand. Give them these steps exactly: - ChatGPT desktop app: open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/readme-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load. -- ChatGPT web: only the plugin directory is available. Until the ReadMe plugin is listed there, send the user to the desktop app or to Codex CLI. +- ChatGPT web: there is no marketplace option, only the plugin directory. Until the ReadMe plugin is listed there, the user can still add the MCP server on its own: turn on **Developer mode** under **Settings β†’ Security and login**, open **Plugins**, click **+** next to the search box, and in the **New Plugin** form set the name to `readme`, the server URL to `https://docs.readme.com/mcp`, and authentication to **No Auth**. That gives the `readme:*` tools but not the skills, so keep this skill's content in the conversation yourself. Once installed, the ReadMe connector in a chat is read-only: `readme:search`, `readme:fetch` and the endpoint tools work on public projects, but ChatGPT cannot take an API key, so steps 6 and 7 of the Quick Start do not apply and write tools such as `readme:update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in Codex with the server registered as in step 6. From 38afb126714c1e7c49ce353baf7acdbc278311fe Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Tue, 15 Sep 2026 07:46:56 +1000 Subject: [PATCH 13/22] codex: point at agent-plugins and drop the duplicate license Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01KDoRbmzuRVJ6Ev9MPEmLm5 --- codex/LICENSE | 21 --------------------- codex/README.md | 2 +- codex/plugin.json | 2 +- codex/skills/onboarding/SKILL.md | 2 +- 4 files changed, 3 insertions(+), 24 deletions(-) delete mode 100644 codex/LICENSE diff --git a/codex/LICENSE b/codex/LICENSE deleted file mode 100644 index 5cb285b..0000000 --- a/codex/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2026 ReadMe - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/codex/README.md b/codex/README.md index 7725051..e9aa817 100644 --- a/codex/README.md +++ b/codex/README.md @@ -7,7 +7,7 @@ Connects ChatGPT and Codex to the [ReadMe MCP server](https://docs.readme.com/ma The repository root is a Codex plugin marketplace. Add it, then install the plugin: ``` -codex plugin marketplace add readmeio/readme-plugins +codex plugin marketplace add readmeio/agent-plugins codex plugin add readme@readme ``` diff --git a/codex/plugin.json b/codex/plugin.json index 08b9188..5e92cf0 100644 --- a/codex/plugin.json +++ b/codex/plugin.json @@ -5,7 +5,7 @@ "description": "ReadMe MCP server packaged as a plugin. Search, read, and update your ReadMe docs and API reference from your editor.", "author": { "name": "ReadMe", "url": "https://readme.com" }, "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server", - "repository": "https://github.com/readmeio/readme-plugins", + "repository": "https://github.com/readmeio/agent-plugins", "license": "MIT", "keywords": ["readme", "documentation", "mcp", "openapi"], "extensions": { diff --git a/codex/skills/onboarding/SKILL.md b/codex/skills/onboarding/SKILL.md index 295f283..3643e13 100644 --- a/codex/skills/onboarding/SKILL.md +++ b/codex/skills/onboarding/SKILL.md @@ -50,7 +50,7 @@ Steps 1 to 5 are all browser work. In the ChatGPT desktop app or ChatGPT web, of In a ChatGPT chat, desktop or web, you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands in the chat. If the `readme:*` tools are missing, the user has to install the plugin by hand. Give them these steps exactly: -- ChatGPT desktop app: open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/readme-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load. +- ChatGPT desktop app: open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/agent-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load. - ChatGPT web: there is no marketplace option, only the plugin directory. Until the ReadMe plugin is listed there, the user can still add the MCP server on its own: turn on **Developer mode** under **Settings β†’ Security and login**, open **Plugins**, click **+** next to the search box, and in the **New Plugin** form set the name to `readme`, the server URL to `https://docs.readme.com/mcp`, and authentication to **No Auth**. That gives the `readme:*` tools but not the skills, so keep this skill's content in the conversation yourself. Once installed, the ReadMe connector in a chat is read-only: `readme:search`, `readme:fetch` and the endpoint tools work on public projects, but ChatGPT cannot take an API key, so steps 6 and 7 of the Quick Start do not apply and write tools such as `readme:update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in Codex with the server registered as in step 6. From 40f94d9fb6c1fab4133ecd79835105032ee58e67 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Wed, 16 Sep 2026 14:40:38 +1000 Subject: [PATCH 14/22] fix(codex): release as 1.0.0 to match the other plugin manifests --- codex/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codex/plugin.json b/codex/plugin.json index 5e92cf0..2168dcd 100644 --- a/codex/plugin.json +++ b/codex/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "readme", - "version": "0.1.0", + "version": "1.0.0", "description": "ReadMe MCP server packaged as a plugin. Search, read, and update your ReadMe docs and API reference from your editor.", "author": { "name": "ReadMe", "url": "https://readme.com" }, "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server", From 75732ae1f0037c5aff2edc40f24fb49b62acf53d Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Tue, 15 Sep 2026 14:48:32 +1000 Subject: [PATCH 15/22] refactor(plugins): give each client its own plugin directory Root was a Cursor plugin, an Agent Plugins package, and a marketplace host for claude/ and codex/ at the same time. That left two MCP definitions that disagreed and a root manifest duplicating codex/. Root is now only a marketplace, with one directory per client. Co-Authored-By: Claude Opus 5 --- .cursor-plugin/marketplace.json | 20 +++ .cursor-plugin/plugin.json | 55 -------- README.md | 125 ++++++++---------- .../.cursor-plugin/plugin.json | 19 ++- cursor/CHANGELOG.md | 9 ++ cursor/LICENSE | 18 +++ cursor/README.md | 106 +++++++++++++++ {assets => cursor/assets}/logo.svg | 0 cursor/mcp.json | 8 ++ mcp.json | 12 -- 10 files changed, 229 insertions(+), 143 deletions(-) create mode 100644 .cursor-plugin/marketplace.json delete mode 100644 .cursor-plugin/plugin.json rename plugin.json => cursor/.cursor-plugin/plugin.json (62%) create mode 100644 cursor/CHANGELOG.md create mode 100644 cursor/LICENSE create mode 100644 cursor/README.md rename {assets => cursor/assets}/logo.svg (100%) create mode 100644 cursor/mcp.json delete mode 100644 mcp.json diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json new file mode 100644 index 0000000..6284c57 --- /dev/null +++ b/.cursor-plugin/marketplace.json @@ -0,0 +1,20 @@ +{ + "name": "readme", + "owner": { + "name": "ReadMe", + "email": "support@readme.io" + }, + "metadata": { + "description": "ReadMe plugins for AI coding agents" + }, + "plugins": [ + { + "name": "readme", + "source": "cursor", + "description": "Search, read, and update your ReadMe docs, API reference, and changelog.", + "minClientVersions": { + "cursor": "3.13.0" + } + } + ] +} diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json deleted file mode 100644 index 1c319c5..0000000 --- a/.cursor-plugin/plugin.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "name": "readme", - "displayName": "ReadMe", - "version": "1.0.0", - "minClientVersions": { - "cursor": "3.13.0" - }, - "description": "Search, read, and update your ReadMe docs, API reference, and changelog.", - "author": { - "name": "ReadMe", - "email": "support@readme.io" - }, - "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server", - "repository": "https://github.com/readmeio/agent-plugins", - "license": "MIT", - "logo": "assets/logo.svg", - "keywords": [ - "readme", - "documentation", - "docs", - "api-reference", - "openapi", - "changelog", - "mcp" - ], - "category": "integrations", - "tags": [ - "readme", - "documentation", - "api", - "mcp" - ], - "variables": { - "type": "object", - "properties": { - "README_API_KEY": { - "type": "string", - "title": "ReadMe API key", - "description": "API key from ReadMe Account Settings > API Keys (starts with rdme_). Grants read and write access to the projects the key belongs to." - } - }, - "required": [ - "README_API_KEY" - ] - }, - "mcpServers": { - "readme": { - "type": "http", - "url": "https://docs.readme.com/mcp", - "headers": { - "Authorization": "Bearer ${README_API_KEY}" - } - } - } -} diff --git a/README.md b/README.md index 9a5185b..2be6690 100644 --- a/README.md +++ b/README.md @@ -1,87 +1,68 @@ -# ReadMe +# ReadMe agent plugins -Search, read, and update your ReadMe documentation from your editor. +Official [ReadMe](https://readme.com) plugins that connect AI coding agents to ReadMe's +[MCP server](https://docs.readme.com/main/docs/readmes-mcp-server), so agents can search your +guides and API reference, inspect OpenAPI specs, draft changelog entries, and open documentation +updates for review. -## Overview +One plugin per client, because each client has its own manifest format and its own way of handling +credentials. -This plugin connects compatible AI assistants to [ReadMe](https://readme.com) through ReadMe's -[MCP](https://modelcontextprotocol.io/) server at `https://docs.readme.com/mcp`. +| Client | Plugin | Marketplace manifest | Install | +| ------------------- | --------------------- | ----------------------------------- | ------------------------------------------------------------------------- | +| Cursor | [`cursor/`](cursor/) | `.cursor-plugin/marketplace.json` | `/add-plugin readme`, or **Cursor Settings β†’ Plugins** | +| Claude | [`claude/`](claude/) | `.claude-plugin/marketplace.json` | `/plugin marketplace add readmeio/agent-plugins` | +| ChatGPT and Codex | [`codex/`](codex/) | `.agents/plugins/marketplace.json` | `codex plugin marketplace add readmeio/agent-plugins` | -Once connected, your assistant can search your guides and API reference, inspect your OpenAPI specs, -draft changelog entries, and open documentation updates for review β€” without leaving the editor. +Each plugin directory has its own README with install steps and auth setup. -## Installation +Claude and Codex take the repository itself as a marketplace from the command line, as above. Cursor +has no CLI equivalent: teams add this repository under **Dashboard β†’ Plugins β†’ Team Marketplaces β†’ +Add Marketplace β†’ Import from Repo**, and Cursor indexes it from the root manifest. -### Cursor +## Repository structure -1. Open **Customize** in Cursor's sidebar. -2. Find **ReadMe** in the marketplace. -3. Select **Install** and choose project or user scope. -4. Set your **ReadMe API key** when prompted (see below). +The repository root is a marketplace for all three clients β€” it is not itself a plugin. Each client +reads only its own marketplace manifest and ignores the others. -Or run `/add-plugin readme` in chat. - -### API key - -The server authenticates with a ReadMe API key. Open **Account Settings β†’ API Keys** in ReadMe and -create a key. Paste it into **Plugins β†’ Configure** as **ReadMe API key**. - -The key decides which projects the assistant can reach, and grants read and write access to them. -Rotate it from Account Settings if it is ever exposed. - -Once connected, ask Cursor to work with your docs, for example: "Find our authentication guide and -add a section on refresh tokens." - -## MCP - -```json -{ - "mcpServers": { - "readme": { - "type": "http", - "url": "https://docs.readme.com/mcp", - "headers": { - "Authorization": "Bearer ${README_API_KEY}" - } - } - } -} +``` +agent-plugins/ +β”œβ”€β”€ .cursor-plugin/marketplace.json # Cursor marketplace β†’ cursor +β”œβ”€β”€ .claude-plugin/marketplace.json # Claude marketplace β†’ ./claude +β”œβ”€β”€ .agents/plugins/marketplace.json # Codex marketplace β†’ ./codex +β”œβ”€β”€ cursor/ +β”‚ β”œβ”€β”€ .cursor-plugin/plugin.json +β”‚ β”œβ”€β”€ mcp.json +β”‚ β”œβ”€β”€ assets/logo.svg +β”‚ β”œβ”€β”€ README.md +β”‚ β”œβ”€β”€ CHANGELOG.md +β”‚ └── LICENSE +β”œβ”€β”€ claude/ +β”‚ β”œβ”€β”€ .claude-plugin/plugin.json +β”‚ β”œβ”€β”€ .mcp.json +β”‚ β”œβ”€β”€ skills/ +β”‚ └── README.md +β”œβ”€β”€ codex/ +β”‚ β”œβ”€β”€ plugin.json # Agent Plugins 1.0.0 manifest +β”‚ β”œβ”€β”€ mcp.json +β”‚ β”œβ”€β”€ skills/ +β”‚ └── README.md +β”œβ”€β”€ README.md +└── LICENSE ``` -## Tools - -| Tool | What it does | -| ------------------ | -------------------------------------------------------------------- | -| `search` | Search guide pages, reference pages, and docs content by keyword | -| `fetch` | Retrieve a specific guide or reference page by ID | -| `update-docs` | Open a documentation update on a new branch and return a review link | -| `list-specs` | List the OpenAPI specs available in the project | -| `search-endpoints` | Search paths, operations, and parameters | -| `list-endpoints` | List all API paths and HTTP methods with summaries | -| `get-endpoint` | Get detail on one endpoint, including security schemes and servers | -| `execute-request` | Execute an API request from a HAR request object | -| `draft-changelog` | Generate a changelog draft from merged GitHub PRs | - -`update-docs` writes to a new branch and returns a review link, so your published docs are never -edited in place. `execute-request` sends a real request to the API in the spec. - -## Which ReadMe MCP server is this? - -ReadMe has two kinds of MCP server, and this plugin is the first one. - -**ReadMe's MCP server** (`https://docs.readme.com/mcp`) is what this plugin installs. You use it to -manage the documentation in your own ReadMe project. - -**Your project's MCP server** (`https://your-project.readme.io/mcp`) is the one ReadMe generates -from your API spec for _your_ users. Every project has its own URL, so it cannot be installed from -the marketplace. To connect to one, use the instructions published on that project's hub. See -[your project's MCP server](https://docs.readme.com/main/docs/your-projects-mcp-server). +## Authentication -## Support +All three plugins talk to the same endpoint, `https://docs.readme.com/mcp`, and all three ship +anonymous. Without a key you get read-only access to public docs, which is enough for searching and +reading, and none of the plugins prompt for anything on install. -- **ReadMe’s MCP server:** https://docs.readme.com/main/docs/readmes-mcp-server -- **Report issues:** https://github.com/readmeio/agent-plugins/issues -- **Contact support:** support@readme.io +Write tools such as `update-docs` need a ReadMe API key. That step is the user's, not the package's, +because each client wires credentials differently and the Agent Plugins spec forbids putting them in +a plugin at all: it requires headers to be literal package data with no secrets in them, and Codex +strips `Authorization` from plugin MCP configs regardless. In every client the shape is the same, +register the server yourself with the key and your entry replaces the plugin's anonymous one. Each +plugin README has the exact snippet. ## License diff --git a/plugin.json b/cursor/.cursor-plugin/plugin.json similarity index 62% rename from plugin.json rename to cursor/.cursor-plugin/plugin.json index eae1454..3a2c7fd 100644 --- a/plugin.json +++ b/cursor/.cursor-plugin/plugin.json @@ -1,16 +1,19 @@ { - "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", "name": "readme", + "displayName": "ReadMe", "version": "1.0.0", + "minClientVersions": { + "cursor": "3.13.0" + }, "description": "Search, read, and update your ReadMe docs, API reference, and changelog.", "author": { "name": "ReadMe", - "email": "support@readme.io", - "url": "https://readme.com" + "email": "support@readme.io" }, "homepage": "https://docs.readme.com/main/docs/readmes-mcp-server", "repository": "https://github.com/readmeio/agent-plugins", "license": "MIT", + "logo": "assets/logo.svg", "keywords": [ "readme", "documentation", @@ -19,5 +22,13 @@ "openapi", "changelog", "mcp" - ] + ], + "category": "integrations", + "tags": [ + "readme", + "documentation", + "api", + "mcp" + ], + "mcpServers": "./mcp.json" } diff --git a/cursor/CHANGELOG.md b/cursor/CHANGELOG.md new file mode 100644 index 0000000..5756ea6 --- /dev/null +++ b/cursor/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +All notable changes to this plugin will be documented here. + +## 1.0.0 β€” initial release + +- Added the `readme` MCP server pointing at ReadMe's hosted Streamable HTTP endpoint (`https://docs.readme.com/mcp`). +- Ships anonymous. Public docs are readable without a key, and write access is opt-in: users register the server with their own API key when they want it. +- Logo: ReadMe's official owl mark. diff --git a/cursor/LICENSE b/cursor/LICENSE new file mode 100644 index 0000000..e69fef2 --- /dev/null +++ b/cursor/LICENSE @@ -0,0 +1,18 @@ +Copyright Β© 2026 ReadMe + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the β€œSoftware”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED β€œAS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/cursor/README.md b/cursor/README.md new file mode 100644 index 0000000..c91f60a --- /dev/null +++ b/cursor/README.md @@ -0,0 +1,106 @@ +# ReadMe + +Cursor plugin that connects agents to [ReadMe](https://readme.com) through ReadMe's remote +[Model Context Protocol](https://modelcontextprotocol.io/) server at `https://docs.readme.com/mcp`. + +Search your guides and API reference, inspect your OpenAPI specs, draft changelog entries, and open +documentation updates for review β€” without leaving the editor. + +## Install + +1. Open **Cursor Settings β†’ Plugins**. +2. Search for **ReadMe**. +3. Click **Install** and choose project or user scope. + +Or run `/add-plugin readme` in chat. Nothing to configure afterwards: the plugin reads public docs +straight away, and a key is only needed for writes (see below). + +### From this repository + +Teams that want the plugin from source, or ahead of the marketplace, can add the repository itself: + +1. Open **Dashboard β†’ Plugins**. +2. Under **Team Marketplaces**, click **Add Marketplace**, then **Import from Repo**. +3. Enter `readmeio/agent-plugins`. + +Cursor reads `.cursor-plugin/marketplace.json` from the repository root and indexes the plugin from +there. Teams and Enterprise plans only. + +## MCP + +```json +{ + "mcpServers": { + "readme": { + "type": "http", + "url": "https://docs.readme.com/mcp" + } + } +} +``` + +## Authentication + +Public read access works without any setup, so the plugin ships no credential and asks for nothing +on install. + +Write tools such as `update-docs` need your ReadMe API key. Register the server yourself once with +the key, and your `readme` entry replaces the plugin's anonymous one: + +```json +{ + "mcpServers": { + "readme": { + "type": "http", + "url": "https://docs.readme.com/mcp", + "headers": { + "Authorization": "Bearer ${env:README_API_KEY}" + } + } + } +} +``` + +Put that in `~/.cursor/mcp.json` for every project, or `.cursor/mcp.json` for one. Create the key +under **Account Settings β†’ API Keys** in ReadMe and export it as `README_API_KEY` rather than +committing it. The key decides which project the agent reaches, and grants read and write access to +it. Rotate it from Account Settings if it is ever exposed. + +## What agents can do + +| Tool | What it does | +| ------------------ | -------------------------------------------------------------------- | +| `search` | Search guide pages, reference pages, and docs content by keyword | +| `fetch` | Retrieve a specific guide or reference page by ID | +| `update-docs` | Open a documentation update on a new branch and return a review link | +| `list-specs` | List the OpenAPI specs available in the project | +| `search-endpoints` | Search paths, operations, and parameters | +| `list-endpoints` | List all API paths and HTTP methods with summaries | +| `get-endpoint` | Get detail on one endpoint, including security schemes and servers | +| `execute-request` | Execute an API request from a HAR request object | +| `draft-changelog` | Generate a changelog draft from merged GitHub PRs | + +`update-docs` writes to a new branch and returns a review link, so your published docs are never +edited in place. `execute-request` sends a real request to the API in the spec. + +## Which ReadMe MCP server is this? + +ReadMe has two kinds of MCP server, and this plugin is the first one. + +**ReadMe's MCP server** (`https://docs.readme.com/mcp`) is what this plugin installs. You use it to +manage the documentation in your own ReadMe project. + +**Your project's MCP server** (`https://your-project.readme.io/mcp`) is the one ReadMe generates +from your API spec for _your_ users. Every project has its own URL, so it cannot be installed from +the marketplace. To connect to one, use the instructions published on that project's hub. See +[your project's MCP server](https://docs.readme.com/main/docs/your-projects-mcp-server). + +## Support + +- **ReadMe's MCP server:** https://docs.readme.com/main/docs/readmes-mcp-server +- **Report issues:** https://github.com/readmeio/agent-plugins/issues +- **Contact support:** support@readme.io + +## License + +MIT diff --git a/assets/logo.svg b/cursor/assets/logo.svg similarity index 100% rename from assets/logo.svg rename to cursor/assets/logo.svg diff --git a/cursor/mcp.json b/cursor/mcp.json new file mode 100644 index 0000000..59156bc --- /dev/null +++ b/cursor/mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "readme": { + "type": "http", + "url": "https://docs.readme.com/mcp" + } + } +} diff --git a/mcp.json b/mcp.json deleted file mode 100644 index 07a58b9..0000000 --- a/mcp.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json", - "mcpServers": { - "readme": { - "type": "streamable-http", - "url": "https://docs.readme.com/mcp", - "headers": { - "Authorization": "Bearer ${README_API_KEY}" - } - } - } -} From a3440daadad5d5f5e0e7275f10766733eddaa7c9 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Wed, 16 Sep 2026 11:56:26 +1000 Subject: [PATCH 16/22] feat(cursor): add a skill for which project a call lands in The MCP server is bound to one project by its hostname, so search and fetch read ReadMe's own documentation while only execute-request, with the user's key, reaches theirs. Agents cannot tell these apart from the tool names, and the README was promising that search covered the user's own guides. Co-Authored-By: Claude Opus 5 --- cursor/.cursor-plugin/plugin.json | 1 + cursor/CHANGELOG.md | 1 + cursor/README.md | 62 ++++++++++++++++---------- cursor/skills/mcp-server/SKILL.md | 74 +++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 cursor/skills/mcp-server/SKILL.md diff --git a/cursor/.cursor-plugin/plugin.json b/cursor/.cursor-plugin/plugin.json index 3a2c7fd..32074cf 100644 --- a/cursor/.cursor-plugin/plugin.json +++ b/cursor/.cursor-plugin/plugin.json @@ -30,5 +30,6 @@ "api", "mcp" ], + "skills": "./skills/", "mcpServers": "./mcp.json" } diff --git a/cursor/CHANGELOG.md b/cursor/CHANGELOG.md index 5756ea6..a9ef7ac 100644 --- a/cursor/CHANGELOG.md +++ b/cursor/CHANGELOG.md @@ -6,4 +6,5 @@ All notable changes to this plugin will be documented here. - Added the `readme` MCP server pointing at ReadMe's hosted Streamable HTTP endpoint (`https://docs.readme.com/mcp`). - Ships anonymous. Public docs are readable without a key, and write access is opt-in: users register the server with their own API key when they want it. +- Added the `mcp-server` skill, so the agent knows this server reads ReadMe's own documentation and that only `execute-request` with the user's key reaches their project. - Logo: ReadMe's official owl mark. diff --git a/cursor/README.md b/cursor/README.md index c91f60a..edb73ef 100644 --- a/cursor/README.md +++ b/cursor/README.md @@ -3,8 +3,12 @@ Cursor plugin that connects agents to [ReadMe](https://readme.com) through ReadMe's remote [Model Context Protocol](https://modelcontextprotocol.io/) server at `https://docs.readme.com/mcp`. -Search your guides and API reference, inspect your OpenAPI specs, draft changelog entries, and open -documentation updates for review β€” without leaving the editor. +Ask how ReadMe works, look up the ReadMe API, and drive your own project through that API with your +key, without leaving the editor. + +The server is bound to one project by its hostname, and this one is ReadMe's own documentation. So +`search` and `fetch` answer questions *about ReadMe*, while your project is reached through +`execute-request` and your key. The `mcp-server` skill keeps the agent straight on that. ## Install @@ -44,8 +48,9 @@ there. Teams and Enterprise plans only. Public read access works without any setup, so the plugin ships no credential and asks for nothing on install. -Write tools such as `update-docs` need your ReadMe API key. Register the server yourself once with -the key, and your `readme` entry replaces the plugin's anonymous one: +Anything that changes your project goes through `execute-request` against `api.readme.com`, and that +needs your ReadMe API key. Register the server yourself once with the key, and your `readme` entry +replaces the plugin's anonymous one: ```json { @@ -68,33 +73,44 @@ it. Rotate it from Account Settings if it is ever exposed. ## What agents can do -| Tool | What it does | -| ------------------ | -------------------------------------------------------------------- | -| `search` | Search guide pages, reference pages, and docs content by keyword | -| `fetch` | Retrieve a specific guide or reference page by ID | -| `update-docs` | Open a documentation update on a new branch and return a review link | -| `list-specs` | List the OpenAPI specs available in the project | -| `search-endpoints` | Search paths, operations, and parameters | -| `list-endpoints` | List all API paths and HTTP methods with summaries | -| `get-endpoint` | Get detail on one endpoint, including security schemes and servers | -| `execute-request` | Execute an API request from a HAR request object | -| `draft-changelog` | Generate a changelog draft from merged GitHub PRs | - -`update-docs` writes to a new branch and returns a review link, so your published docs are never -edited in place. `execute-request` sends a real request to the API in the spec. +| Tool | What it does | Reads or acts on | +| ------------------ | ------------------------------------------------------------------ | ------------------ | +| `search` | Search guides, reference pages, and docs content by keyword | ReadMe's own docs | +| `fetch` | Retrieve a specific guide or reference page by ID | ReadMe's own docs | +| `list-specs` | List the OpenAPI specs available | ReadMe's own specs | +| `list-endpoints` | List all API paths and HTTP methods with summaries | ReadMe's own specs | +| `search-endpoints` | Search paths, operations, and parameters | ReadMe's own specs | +| `get-endpoint` | Detail on one endpoint, including security schemes and servers | ReadMe's own specs | +| `execute-request` | Execute a real API request | **Your project** | +| `update-docs` | Returns instructions for updating docs, for the agent to follow | Nothing by itself | +| `draft-changelog` | Returns instructions for drafting a changelog from merged PRs | Nothing by itself | + +`execute-request` is the only tool that changes anything, and the only one your API key applies to. +`update-docs` and `draft-changelog` are prompts rather than actions: they hand the agent a procedure, +and the agent carries it out through `execute-request`. + +## Skills + +| Skill | What it does | +| ----- | ------------ | +| `mcp-server` | Keeps the agent straight on which project a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | ## Which ReadMe MCP server is this? ReadMe has two kinds of MCP server, and this plugin is the first one. -**ReadMe's MCP server** (`https://docs.readme.com/mcp`) is what this plugin installs. You use it to -manage the documentation in your own ReadMe project. +**ReadMe's MCP server** (`https://docs.readme.com/mcp`) is what this plugin installs. It answers +questions about ReadMe from ReadMe's own documentation, and lets the agent drive the ReadMe API +against your project once you attach a key. -**Your project's MCP server** (`https://your-project.readme.io/mcp`) is the one ReadMe generates -from your API spec for _your_ users. Every project has its own URL, so it cannot be installed from -the marketplace. To connect to one, use the instructions published on that project's hub. See +**Your project's MCP server** (`https://your-project.readme.io/mcp`) is the one ReadMe generates for +_your_ users to ask questions of your published hub. You do not need it to work on your own docs +from here: with a key, `execute-request` reaches your content through `api.readme.com/v2`. Every +project has its own URL, so it cannot be installed from the marketplace. See [your project's MCP server](https://docs.readme.com/main/docs/your-projects-mcp-server). +Both are the same software; the hostname is what decides which project it serves. + ## Support - **ReadMe's MCP server:** https://docs.readme.com/main/docs/readmes-mcp-server diff --git a/cursor/skills/mcp-server/SKILL.md b/cursor/skills/mcp-server/SKILL.md new file mode 100644 index 0000000..f3d0575 --- /dev/null +++ b/cursor/skills/mcp-server/SKILL.md @@ -0,0 +1,74 @@ +--- +name: mcp-server +description: Work out which ReadMe project a tool call will hit before making it. Use whenever the user asks to search, read, or change "our docs", "my docs", or a named project through the ReadMe MCP server, and before any write. Explains that this server reads ReadMe's own documentation while writes land on the user's project. +--- + +# Which project am I touching? + +This plugin connects to ReadMe's own documentation project at `https://docs.readme.com/mcp`. A +ReadMe MCP server is bound to exactly one project by its hostname, decided when the server is built, +and no tool takes a project argument. You cannot point this server at the user's project. + +That matters because reads and writes land in different places. + +## The split + +| Tool | Reads or acts on | +| --- | --- | +| `search`, `fetch` | ReadMe's own product documentation. Never the user's content. | +| `list-specs`, `list-endpoints`, `get-endpoint`, `search-endpoints`, `get-server-variables` | ReadMe's own API definitions, as documents | +| `execute-request` | Makes a real HTTP call. With the user's key against `api.readme.com`, this acts on **their** project | +| `send-feedback` | Files feedback against ReadMe, not the user's project. Rarely exposed | +| `update-docs`, `draft-changelog` | Prompt text, not actions. They return instructions for you to follow, and change nothing by themselves | + +Two of these have side effects, and only one of them touches the user: `execute-request` is the only +tool their key applies to, and the only way to change anything in their project. `send-feedback` +writes too, but the record lands in ReadMe's queue. + +`execute-request` cannot call just any URL. It is restricted to the servers declared in this +project's own API definitions, which here means `api.readme.com` and `metrics.readme.io`. The user's +own hub is not reachable from this server, so there is no way to read or write their content except +through the ReadMe API. + +## Before any write + +Do not ask the user which project. They cannot change the answer, and the key already decides it. +Look it up and say it: + +1. `execute-request`, spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. +2. State the project name and subdomain from the response, then make the change. + +A 500 titled `An unknown error has occurred.` means no key is attached. The v2 API does not return +401 for a missing bearer. Stop and tell the user to register the server with their key, as described +in the plugin README. Never read `README_API_KEY` yourself or build the header by hand. + +## When the user asks about their own docs + +"Search our docs", "what does our guide say", "find the page about X in my project" cannot be +answered with `search` or `fetch` here. Those read ReadMe's documentation and will return confident, +wrong answers about someone else's content. + +Do not send the user off to configure anything. Their key already reaches their content through the +ReadMe API, so switch tools and carry on: + +| They want | Call, via `execute-request` with spec title `ReadMe API` | +| --- | --- | +| Search their content | `GET https://api.readme.com/v2/search?query=...`, optionally `section`, `version`, `projects` | +| Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | +| List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | + +`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill has the full +route map if the request goes beyond these. + +Only if the user explicitly wants an assistant over their published hub, for their own end users, +is the answer a different server: every project publishes one at `https://{subdomain}.readme.io/mcp` +or its custom domain. That is a product feature they set up deliberately, not a workaround for this +conversation. + +## Quick check + +Ask yourself which of these a request needs before choosing a tool: + +- **How does ReadMe work?** β†’ `search` and `fetch`. Correct server, no key needed. +- **What is in my hub?** β†’ not `search`. Use `execute-request` against `api.readme.com/v2`. +- **Change something in my project** β†’ `execute-request` with their key, after naming the project. From 5581517046ef9c9f1720395775f35c27ae0c5850 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Wed, 16 Sep 2026 12:14:03 +1000 Subject: [PATCH 17/22] feat(cursor): make the skill establish project and auth before acting The agent had no way to tell an anonymous server from a keyed one, so it asked for a key it sometimes already had, and answered from ReadMe's own docs when no project was named. Adds a probe against /projects/me that distinguishes the two, and names the Missing Security Schemes error that an unexpanded ${README_API_KEY} placeholder produces. Co-Authored-By: Claude Opus 5 --- cursor/skills/mcp-server/SKILL.md | 59 ++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/cursor/skills/mcp-server/SKILL.md b/cursor/skills/mcp-server/SKILL.md index f3d0575..cefcc0f 100644 --- a/cursor/skills/mcp-server/SKILL.md +++ b/cursor/skills/mcp-server/SKILL.md @@ -1,6 +1,6 @@ --- name: mcp-server -description: Work out which ReadMe project a tool call will hit before making it. Use whenever the user asks to search, read, or change "our docs", "my docs", or a named project through the ReadMe MCP server, and before any write. Explains that this server reads ReadMe's own documentation while writes land on the user's project. +description: Establish which ReadMe project is in play, and how it is authenticated, before acting on anything of the user's. Use whenever the user mentions "our docs", "my docs", their hub, or a named project, whenever a ReadMe call fails on authentication, and before any write. This server reads ReadMe's own documentation; the user's project is reached only through execute-request and their key. --- # Which project am I touching? @@ -30,17 +30,51 @@ project's own API definitions, which here means `api.readme.com` and `metrics.re own hub is not reachable from this server, so there is no way to read or write their content except through the ReadMe API. -## Before any write +## Start here, before touching anything of theirs -Do not ask the user which project. They cannot change the answer, and the key already decides it. -Look it up and say it: +Reading ReadMe's own documentation needs nothing. The moment a request concerns *their* project, +establish which project it is. Do not guess, and do not quietly answer from ReadMe's docs instead. -1. `execute-request`, spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. -2. State the project name and subdomain from the response, then make the change. +**Step 1. Find out whether a key is already attached.** Call `execute-request`, spec title +`ReadMe API`, `GET https://api.readme.com/v2/projects/me`, and send no `Authorization` header. -A 500 titled `An unknown error has occurred.` means no key is attached. The v2 API does not return -401 for a missing bearer. Stop and tell the user to register the server with their key, as described -in the plugin README. Never read `README_API_KEY` yourself or build the header by hand. +| Result | What it means | Do | +| --- | --- | --- | +| A project object | The server registration already carries a key | Name the project and subdomain, then carry on. Never ask for a key | +| `Missing Security Schemes` | No key anywhere | Go to step 2 | + +Do this before asking the user anything. The plugin ships anonymous, but a user who registered their +own `readme` server has a key on the connection, and asking them for one they already supplied is +noise. + +**Step 2. No key, and no project named.** Stop and ask. Do not pick a project, do not assume the +user means ReadMe's own docs, and do not start reading guides to infer one. Ask which ReadMe project +they mean and how they want to authenticate. + +While waiting, be clear about what does work unauthenticated: `search` and `fetch` over ReadMe's own +product documentation, and the reference tools over ReadMe's API definitions. None of their content. + +**Step 3. Project known, no key.** Ask for it, and offer the better option first: + +- **Preferred:** they register the server with the key themselves, so it never enters the chat. The + plugin README has the `~/.cursor/mcp.json` snippet. +- **Otherwise:** they paste the key and you pass it as an `Authorization: Bearer` header inside the + `execute-request` call. This works, but the key is then in the transcript. Say so when it happens, + and tell them to rotate it afterwards. + +**Step 4. Name the project before you change anything.** Never ask the user which project a write +lands in. The key already decides, and they cannot override it. State the name and subdomain from +step 1, then make the change. + +## When authentication looks configured but fails + +`Missing Security Schemes` while the user believes a key is set almost always means the registration +carries a placeholder rather than a value: `${env:README_API_KEY}` or `${README_API_KEY}` written +into `mcp.json` with the environment variable unset, which clients pass through as literal text. + +Say that plainly. Ask them to confirm the variable is exported in the environment the editor was +launched from, and to restart the editor, since the header is resolved once when the server +connects. Do not work around it by asking for the key in chat before checking. ## When the user asks about their own docs @@ -69,6 +103,7 @@ conversation. Ask yourself which of these a request needs before choosing a tool: -- **How does ReadMe work?** β†’ `search` and `fetch`. Correct server, no key needed. -- **What is in my hub?** β†’ not `search`. Use `execute-request` against `api.readme.com/v2`. -- **Change something in my project** β†’ `execute-request` with their key, after naming the project. +- **How does ReadMe work?** β†’ `search` and `fetch`. Correct server, no key needed, no project to establish. +- **What is in my hub?** β†’ not `search`. Run the step 1 probe, then `execute-request` against `api.readme.com/v2`. +- **Change something in my project** β†’ `execute-request`, after naming the project from step 1. +- **No project named and no key?** β†’ ask. Never default to ReadMe's own docs and present it as theirs. From 38f7274856ed5a00ef84295248e65868afc1bd42 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Wed, 16 Sep 2026 12:30:27 +1000 Subject: [PATCH 18/22] feat(cursor): show the calls the skill asks for, and probe once The skill described a protocol without demonstrating it, so the agent had to infer the shape of every call. It now carries the probe and the keyed variant as worked examples, including the required title argument that fails with an unhelpful validation error when omitted. Also resolves the project once per session rather than per turn, states that step 3 only applies to an anonymous server, and folds the routing list into the tool table so one decision is described once. Co-Authored-By: Claude Opus 5 --- cursor/skills/mcp-server/SKILL.md | 145 ++++++++++++++++-------------- 1 file changed, 80 insertions(+), 65 deletions(-) diff --git a/cursor/skills/mcp-server/SKILL.md b/cursor/skills/mcp-server/SKILL.md index cefcc0f..42d91a2 100644 --- a/cursor/skills/mcp-server/SKILL.md +++ b/cursor/skills/mcp-server/SKILL.md @@ -6,104 +6,119 @@ description: Establish which ReadMe project is in play, and how it is authentica # Which project am I touching? This plugin connects to ReadMe's own documentation project at `https://docs.readme.com/mcp`. A -ReadMe MCP server is bound to exactly one project by its hostname, decided when the server is built, -and no tool takes a project argument. You cannot point this server at the user's project. +ReadMe MCP server is bound to one project by its hostname, fixed when the server is built, and no +tool takes a project argument. This server always answers for ReadMe's own docs. -That matters because reads and writes land in different places. +Their project is reachable too, but only through the ReadMe API, and only with their key. So reads +and writes land in different places. ## The split -| Tool | Reads or acts on | -| --- | --- | -| `search`, `fetch` | ReadMe's own product documentation. Never the user's content. | -| `list-specs`, `list-endpoints`, `get-endpoint`, `search-endpoints`, `get-server-variables` | ReadMe's own API definitions, as documents | -| `execute-request` | Makes a real HTTP call. With the user's key against `api.readme.com`, this acts on **their** project | -| `send-feedback` | Files feedback against ReadMe, not the user's project. Rarely exposed | -| `update-docs`, `draft-changelog` | Prompt text, not actions. They return instructions for you to follow, and change nothing by themselves | - -Two of these have side effects, and only one of them touches the user: `execute-request` is the only -tool their key applies to, and the only way to change anything in their project. `send-feedback` -writes too, but the record lands in ReadMe's queue. +| Tool | Answers for | Use it when | +| --- | --- | --- | +| `search`, `fetch` | ReadMe's own product documentation | The question is about how ReadMe works | +| `list-specs`, `list-endpoints`, `get-endpoint`, `search-endpoints`, `get-server-variables` | ReadMe's own API definitions, as documents | Looking up a route before calling it | +| `execute-request` | **The user's project**, via `api.readme.com` with their key | Reading or changing anything of theirs | +| `send-feedback` | ReadMe's feedback queue, not theirs | They want to report something to ReadMe | +| `update-docs`, `draft-changelog` | Nothing. They return instructions for you to carry out | You want the recommended procedure | -`execute-request` cannot call just any URL. It is restricted to the servers declared in this -project's own API definitions, which here means `api.readme.com` and `metrics.readme.io`. The user's -own hub is not reachable from this server, so there is no way to read or write their content except -through the ReadMe API. +`execute-request` is the only tool the user's key applies to, and the only way to touch their +project. It calls only the servers declared in this project's API definitions, which means +`api.readme.com` and `metrics.readme.io`; their own hub is not reachable from here. ## Start here, before touching anything of theirs -Reading ReadMe's own documentation needs nothing. The moment a request concerns *their* project, -establish which project it is. Do not guess, and do not quietly answer from ReadMe's docs instead. +Questions about ReadMe itself need none of this: use `search` and `fetch` and answer. + +Anything concerning *their* project starts by establishing which project, and whether a key is +already attached. Resolve this once per session and reuse the answer; do not re-probe each turn. + +**Step 1. Probe.** Call `execute-request` with no `Authorization` header: + +```json +{ + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me" + } +} +``` -**Step 1. Find out whether a key is already attached.** Call `execute-request`, spec title -`ReadMe API`, `GET https://api.readme.com/v2/projects/me`, and send no `Authorization` header. +`title` is required and names the spec. Omitting it fails with +`Invalid arguments: title: expected string, received undefined`. -| Result | What it means | Do | +| Result | Meaning | Next | | --- | --- | --- | -| A project object | The server registration already carries a key | Name the project and subdomain, then carry on. Never ask for a key | -| `Missing Security Schemes` | No key anywhere | Go to step 2 | +| A project object | The server registration already carries a key | Name the project and subdomain, then carry on. Ask for nothing | +| `Missing Security Schemes` | No key anywhere | Step 2 | -Do this before asking the user anything. The plugin ships anonymous, but a user who registered their -own `readme` server has a key on the connection, and asking them for one they already supplied is -noise. +Probe before asking the user anything. The plugin ships anonymous, but a user who registered their +own `readme` server already has a key on the connection, and asking for one they supplied is noise. -**Step 2. No key, and no project named.** Stop and ask. Do not pick a project, do not assume the -user means ReadMe's own docs, and do not start reading guides to infer one. Ask which ReadMe project -they mean and how they want to authenticate. +**Step 2. No key, and no project named.** Ask, and wait. Pick no project, infer none from open +files or earlier turns, and read no guides to narrow it down: -While waiting, be clear about what does work unauthenticated: `search` and `fetch` over ReadMe's own -product documentation, and the reference tools over ReadMe's API definitions. None of their content. +> This plugin talks to ReadMe's own documentation, so I can answer questions about how ReadMe works +> right now. To work on your project I need to know which one, and an API key. Which project, and +> would you rather register the key with the server or paste it here? -**Step 3. Project known, no key.** Ask for it, and offer the better option first: +**Step 3. Project known, no key.** This step applies only when the server is anonymous. If step 1 +returned a project, the registration carries a key, it is applied automatically, and you send none +of your own. -- **Preferred:** they register the server with the key themselves, so it never enters the chat. The +Offer the better option first: + +- **Preferred:** they register the server with the key themselves, so it stays out of the chat. The plugin README has the `~/.cursor/mcp.json` snippet. -- **Otherwise:** they paste the key and you pass it as an `Authorization: Bearer` header inside the - `execute-request` call. This works, but the key is then in the transcript. Say so when it happens, - and tell them to rotate it afterwards. +- **Otherwise:** they paste it and you send it as a header in the call: + + ```json + { + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me", + "headers": [{ "name": "Authorization", "value": "Bearer rdme_..." }] + } + } + ``` + + This works, and it also puts the key in the transcript. Say so, and tell them to rotate it. -**Step 4. Name the project before you change anything.** Never ask the user which project a write -lands in. The key already decides, and they cannot override it. State the name and subdomain from -step 1, then make the change. +**Step 4. Name the project before you change anything.** The key decides which project a write +lands in, and the user cannot override it, so asking them is misleading. State the name and +subdomain from step 1, then make the change. ## When authentication looks configured but fails `Missing Security Schemes` while the user believes a key is set almost always means the registration -carries a placeholder rather than a value: `${env:README_API_KEY}` or `${README_API_KEY}` written -into `mcp.json` with the environment variable unset, which clients pass through as literal text. +holds a placeholder rather than a value: `${env:README_API_KEY}` or `${README_API_KEY}` left in +`mcp.json` with the environment variable unset, which clients pass through as literal text. -Say that plainly. Ask them to confirm the variable is exported in the environment the editor was -launched from, and to restart the editor, since the header is resolved once when the server -connects. Do not work around it by asking for the key in chat before checking. +Say that plainly, and check it before asking for the key in chat. Ask them to confirm the variable +is exported in the environment the editor launched from, then restart the editor, since the header +resolves once when the server connects. ## When the user asks about their own docs "Search our docs", "what does our guide say", "find the page about X in my project" cannot be -answered with `search` or `fetch` here. Those read ReadMe's documentation and will return confident, +answered by `search` or `fetch` here. Those read ReadMe's documentation and would return confident, wrong answers about someone else's content. -Do not send the user off to configure anything. Their key already reaches their content through the -ReadMe API, so switch tools and carry on: +Their key already reaches their content through the ReadMe API, so switch tools and carry on rather +than sending them away to configure anything: -| They want | Call, via `execute-request` with spec title `ReadMe API` | +| They want | Call, via `execute-request`, spec title `ReadMe API` | | --- | --- | | Search their content | `GET https://api.readme.com/v2/search?query=...`, optionally `section`, `version`, `projects` | | Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | | List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | -`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill has the full -route map if the request goes beyond these. - -Only if the user explicitly wants an assistant over their published hub, for their own end users, -is the answer a different server: every project publishes one at `https://{subdomain}.readme.io/mcp` -or its custom domain. That is a product feature they set up deliberately, not a workaround for this -conversation. - -## Quick check - -Ask yourself which of these a request needs before choosing a tool: +`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full +route map when a request goes beyond these. -- **How does ReadMe work?** β†’ `search` and `fetch`. Correct server, no key needed, no project to establish. -- **What is in my hub?** β†’ not `search`. Run the step 1 probe, then `execute-request` against `api.readme.com/v2`. -- **Change something in my project** β†’ `execute-request`, after naming the project from step 1. -- **No project named and no key?** β†’ ask. Never default to ReadMe's own docs and present it as theirs. +A different server is the answer only when the user explicitly wants an assistant over their +published hub for their own end users: every project publishes one at +`https://{subdomain}.readme.io/mcp` or its custom domain. That is a product feature they set up +deliberately, not a workaround for this conversation. From af28f294d78e78337c3030782cfd267e69c750bf Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Wed, 16 Sep 2026 13:34:56 +1000 Subject: [PATCH 19/22] proper prompt engineering --- claude/skills/onboarding/SKILL.md | 2 +- codex/skills/onboarding/SKILL.md | 2 +- cursor/README.md | 1 + cursor/skills/mcp-auth/SKILL.md | 92 +++++++++++++++++++++++ cursor/skills/mcp-server/SKILL.md | 121 +++++++++++------------------- 5 files changed, 138 insertions(+), 80 deletions(-) create mode 100644 cursor/skills/mcp-auth/SKILL.md diff --git a/claude/skills/onboarding/SKILL.md b/claude/skills/onboarding/SKILL.md index d5a0167..2866902 100644 --- a/claude/skills/onboarding/SKILL.md +++ b/claude/skills/onboarding/SKILL.md @@ -38,7 +38,7 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D ``` Keep the single quotes: Claude Code expands `${README_API_KEY}` when it starts, so the key never lands in a config file. In Codex: `codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY`. Not possible in Claude Desktop Chat, Cowork or claude.ai; see the section below. -7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. A 500 titled `An unknown error has occurred.` means the key is missing or wrong; go back to step 5. +7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. ## Doing it with Claude in Chrome diff --git a/codex/skills/onboarding/SKILL.md b/codex/skills/onboarding/SKILL.md index 3643e13..66b7318 100644 --- a/codex/skills/onboarding/SKILL.md +++ b/codex/skills/onboarding/SKILL.md @@ -38,7 +38,7 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D ``` Codex reads the variable at startup, so the key never lands in a config file. The ChatGPT desktop app shares Codex's config, so this registration also covers Codex sessions there. In Claude Code the equivalent is `claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}'`. Not possible in ChatGPT web; see the section below. -7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. A 500 titled `An unknown error has occurred.` means the key is missing or wrong; go back to step 5. +7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. After step 7, load the `readme-api` skill for anything else in the project. diff --git a/cursor/README.md b/cursor/README.md index edb73ef..aebf313 100644 --- a/cursor/README.md +++ b/cursor/README.md @@ -94,6 +94,7 @@ and the agent carries it out through `execute-request`. | Skill | What it does | | ----- | ------------ | | `mcp-server` | Keeps the agent straight on which project a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | +| `mcp-auth` | Establishes which key is in play and diagnoses the failures a missing or unresolved one produces | ## Which ReadMe MCP server is this? diff --git a/cursor/skills/mcp-auth/SKILL.md b/cursor/skills/mcp-auth/SKILL.md new file mode 100644 index 0000000..a39ea9e --- /dev/null +++ b/cursor/skills/mcp-auth/SKILL.md @@ -0,0 +1,92 @@ +--- +name: mcp-auth +description: Establish or repair the ReadMe API key behind execute-request. Use when a ReadMe call fails with "Missing Security Schemes", "The API key couldn't be located", or "An unknown error has occurred", when the user asks which project their key reaches, when they say they set a key but it is not working, and before the first write to their project. +--- + +# The key behind execute-request + +The plugin ships anonymous. Public reads of ReadMe's documentation need no key; anything touching +the user's own project does, and it travels on the MCP server registration rather than in the tool +call. See the `mcp-server` skill for which calls land where. + +## Assume anonymous + +Most users have not registered a key, so do not spend a call proving it. Go straight to the work: + +- ReadMe documentation questions β€” `search` and `fetch`, no key involved. +- The user's project, and they have not mentioned a key β€” go to **No key yet** below. +- The user says they registered one, or an `execute-request` call fails β€” verify with the probe. + +## Verify + +`execute-request`, spec title `ReadMe API`, with no `Authorization` header of your own: + +```json +{ + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me" + } +} +``` + +| Response | Means | Next | +| --- | --- | --- | +| A project object | The registration carries a working key | Name the project and subdomain, carry on. Ask for nothing | +| `Missing Security Schemes` | No `Authorization` header at all β€” the server is anonymous | **No key yet** | +| `"title": "The API key couldn't be located."`, status 401 | A key is being sent, but it is not a real key | **A key is set but wrong** | +| `"title": "An unknown error has occurred."`, status 500 | The bearer is empty β€” the variable resolved to nothing | **A key is set but wrong** | + +Resolve this once per session. Having seen a project object, send no `Authorization` header of your +own for the rest of the session. + +## No key yet + +If the user has not named a project, ask, and wait. Pick no project, infer none from open files or +earlier turns, and read no guides to narrow it down. Ask which project, and whether they would rather +register the key with the server or paste it in chat. + +Offer the better option first: + +- **Preferred:** they register the server with the key themselves, so it stays out of the chat. The + plugin README has the `~/.cursor/mcp.json` snippet. They create the key under **Configuration β†’ + API Keys** in ReadMe. This takes an editor restart, since the header resolves when the server + connects. +- **Otherwise:** they paste it and you send it as a header on each call: + + ```json + { + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me", + "headers": [{ "name": "Authorization", "value": "Bearer rdme_..." }] + } + } + ``` + + This works, and it also puts the key in the transcript. Say so, and tell them to rotate it. + +Send a header of your own **only** when the probe returned `Missing Security Schemes`. A header on the +server registration overrides anything you set in `harRequest`, so against a registered server a +pasted key is silently ignored and the call lands in whichever project the registration owns β€” no +error, just the wrong project. + +## A key is set but wrong + +Both failures mean an `Authorization` header is reaching the API and the API is rejecting it. The +usual cause is a placeholder in `mcp.json` β€” `${env:README_API_KEY}` β€” that the client resolved to +nothing, or passed through as literal text, because the variable is unset: + +- **Status 500, `An unknown error has occurred.`** β€” the header arrived empty. +- **Status 401, `The API key couldn't be located.`** β€” a value arrived, but no such key exists. + Also what a revoked or mistyped key returns. + +Say that plainly before asking them to paste anything. Ask them to confirm the variable is exported +in the environment the editor launched from, then restart the editor. If the key is genuinely gone, +they create a new one under **Configuration β†’ API Keys**. + +Do not work around either failure by probing with `curl` or by retrying against the `Legacy API` +spec. One key maps to one project; if the call reaches the wrong project, the registration is the +thing to change. diff --git a/cursor/skills/mcp-server/SKILL.md b/cursor/skills/mcp-server/SKILL.md index 42d91a2..1150430 100644 --- a/cursor/skills/mcp-server/SKILL.md +++ b/cursor/skills/mcp-server/SKILL.md @@ -1,39 +1,45 @@ --- name: mcp-server -description: Establish which ReadMe project is in play, and how it is authenticated, before acting on anything of the user's. Use whenever the user mentions "our docs", "my docs", their hub, or a named project, whenever a ReadMe call fails on authentication, and before any write. This server reads ReadMe's own documentation; the user's project is reached only through execute-request and their key. +description: Route ReadMe MCP calls to the right project. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides" - and before calling execute-request for the first time in a session. --- -# Which project am I touching? +# Which project does this call land in? -This plugin connects to ReadMe's own documentation project at `https://docs.readme.com/mcp`. A -ReadMe MCP server is bound to one project by its hostname, fixed when the server is built, and no -tool takes a project argument. This server always answers for ReadMe's own docs. +This plugin connects to `https://docs.readme.com/mcp`, which serves **ReadMe's own documentation**. +`search` and `fetch` answer questions about how ReadMe works. The user's project is reached only +through `execute-request` with their API key. Reads and writes land in different places. -Their project is reachable too, but only through the ReadMe API, and only with their key. So reads -and writes land in different places. +Questions about ReadMe itself need nothing else: use `search` and `fetch` and answer. -## The split +## Tools on this server | Tool | Answers for | Use it when | | --- | --- | --- | | `search`, `fetch` | ReadMe's own product documentation | The question is about how ReadMe works | -| `list-specs`, `list-endpoints`, `get-endpoint`, `search-endpoints`, `get-server-variables` | ReadMe's own API definitions, as documents | Looking up a route before calling it | -| `execute-request` | **The user's project**, via `api.readme.com` with their key | Reading or changing anything of theirs | -| `send-feedback` | ReadMe's feedback queue, not theirs | They want to report something to ReadMe | +| `list-specs`, `list-endpoints`, `get-endpoint`, `search-endpoints` | ReadMe's API definitions, as documents | Looking up a route before calling it | +| `execute-request` | **The user's project**, with their key | Reading or changing anything of theirs | | `update-docs`, `draft-changelog` | Nothing. They return instructions for you to carry out | You want the recommended procedure | -`execute-request` is the only tool the user's key applies to, and the only way to touch their -project. It calls only the servers declared in this project's API definitions, which means -`api.readme.com` and `metrics.readme.io`; their own hub is not reachable from here. +Tool availability is per-project configuration, not a fixed list. Call `tools/list` rather than +assuming a tool named here is present, and never assume one that is not. -## Start here, before touching anything of theirs +## The three specs -Questions about ReadMe itself need none of this: use `search` and `fetch` and answer. +`execute-request` reaches only servers declared in these definitions. There are three, and +`search-endpoints` searches all of them at once: -Anything concerning *their* project starts by establishing which project, and whether a key is -already attached. Resolve this once per session and reuse the answer; do not re-probe each turn. +| Spec title | Server | Auth | +| --- | --- | --- | +| `ReadMe API` | `https://api.readme.com/v2` | Bearer `rdme_...` | +| `Developer Metrics API` | `https://metrics.readme.io` | Bearer `rdme_...` | +| `Legacy API` | `https://dash.readme.com/api/v1` | HTTP basic | + +**Use `ReadMe API` for all work on the user's content.** `Legacy API` is v1: it takes basic auth +rather than a bearer token, and it is unavailable to projects on ReadMe Refactored. `search-endpoints` +will surface its routes alongside the others β€” ignore them. Never fall back to v1 when a v2 call +fails. -**Step 1. Probe.** Call `execute-request` with no `Authorization` header: +## Calling execute-request ```json { @@ -45,60 +51,14 @@ already attached. Resolve this once per session and reuse the answer; do not re- } ``` -`title` is required and names the spec. Omitting it fails with -`Invalid arguments: title: expected string, received undefined`. - -| Result | Meaning | Next | -| --- | --- | --- | -| A project object | The server registration already carries a key | Name the project and subdomain, then carry on. Ask for nothing | -| `Missing Security Schemes` | No key anywhere | Step 2 | - -Probe before asking the user anything. The plugin ships anonymous, but a user who registered their -own `readme` server already has a key on the connection, and asking for one they supplied is noise. - -**Step 2. No key, and no project named.** Ask, and wait. Pick no project, infer none from open -files or earlier turns, and read no guides to narrow it down: - -> This plugin talks to ReadMe's own documentation, so I can answer questions about how ReadMe works -> right now. To work on your project I need to know which one, and an API key. Which project, and -> would you rather register the key with the server or paste it here? - -**Step 3. Project known, no key.** This step applies only when the server is anonymous. If step 1 -returned a project, the registration carries a key, it is applied automatically, and you send none -of your own. - -Offer the better option first: +- `title` names the spec and is required whenever the server carries more than one, as this one does. + Omitting it fails validation before the request is made. +- `url` must be absolute. `get-endpoint` and `search-endpoints` report paths relative to the server + (`/projects/me`), so prepend `https://api.readme.com/v2` rather than pasting the path through. +- The key decides which project the call lands in, and the user cannot override it per-request. + Name the project before you change anything; asking them which one to write to is misleading. -- **Preferred:** they register the server with the key themselves, so it stays out of the chat. The - plugin README has the `~/.cursor/mcp.json` snippet. -- **Otherwise:** they paste it and you send it as a header in the call: - - ```json - { - "title": "ReadMe API", - "harRequest": { - "method": "get", - "url": "https://api.readme.com/v2/projects/me", - "headers": [{ "name": "Authorization", "value": "Bearer rdme_..." }] - } - } - ``` - - This works, and it also puts the key in the transcript. Say so, and tell them to rotate it. - -**Step 4. Name the project before you change anything.** The key decides which project a write -lands in, and the user cannot override it, so asking them is misleading. State the name and -subdomain from step 1, then make the change. - -## When authentication looks configured but fails - -`Missing Security Schemes` while the user believes a key is set almost always means the registration -holds a placeholder rather than a value: `${env:README_API_KEY}` or `${README_API_KEY}` left in -`mcp.json` with the environment variable unset, which clients pass through as literal text. - -Say that plainly, and check it before asking for the key in chat. Ask them to confirm the variable -is exported in the environment the editor launched from, then restart the editor, since the header -resolves once when the server connects. +Setting up, verifying, or repairing that key is the `mcp-auth` skill. ## When the user asks about their own docs @@ -115,10 +75,15 @@ than sending them away to configure anything: | Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | | List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | -`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full -route map when a request goes beyond these. +`{branch}` is a version number, `stable`, or a branch name. Use `search-endpoints` with spec title +`ReadMe API` when a request goes beyond these. + +## A different server, when they actually want one + +Every ReadMe project publishes its own MCP server at `https://{subdomain}.readme.io/mcp`, or its +custom domain. That is for *their* end users to ask questions of *their* published hub. It is a +product feature they set up deliberately, not a workaround for this conversation, and it is not +needed to work on their own docs from here. -A different server is the answer only when the user explicitly wants an assistant over their -published hub for their own end users: every project publishes one at -`https://{subdomain}.readme.io/mcp` or its custom domain. That is a product feature they set up -deliberately, not a workaround for this conversation. +A server's hostname decides which project it serves. Enterprise hostnames serve a whole group, so +`search` and `fetch` there can span several child projects. From 614cba077858edf0e8a860ea52cdf48594b9a462 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Wed, 16 Sep 2026 14:25:51 +1000 Subject: [PATCH 20/22] refactor(skills): make skills agent-agnostic and generate per-client copies Five canonical skills live in skills/ and are the only ones to edit. Each client directory gets a byte-identical generated copy, since every marketplace submission reads only its own directory. Host-specific instructions moved inside the shared files as per-client tables: registering the key, driving a browser, and installing the plugin by hand. Tool names are bare, with no namespace prefix. scripts/sync-skills.mjs regenerates the copies and --check fails on drift. scripts/validate-skills.mjs checks frontmatter and the 20,000-char limit. CI runs both plus claude plugin validate. --- .github/workflows/validate.yml | 29 ++++++++ README.md | 22 +++++- claude/README.md | 14 +++- claude/skills/mcp-auth/SKILL.md | 111 ++++++++++++++++++++++++++++++ claude/skills/mcp-server/SKILL.md | 89 ++++++++++++++++++++++++ claude/skills/onboarding/SKILL.md | 42 ++++++----- codex/README.md | 10 +++ codex/skills/mcp-auth/SKILL.md | 111 ++++++++++++++++++++++++++++++ codex/skills/mcp-server/SKILL.md | 89 ++++++++++++++++++++++++ codex/skills/onboarding/SKILL.md | 41 +++++++---- cursor/README.md | 3 + cursor/skills/mcp-auth/SKILL.md | 35 +++++++--- cursor/skills/mcp-server/SKILL.md | 4 +- cursor/skills/onboarding/SKILL.md | 80 +++++++++++++++++++++ scripts/sync-skills.mjs | 87 +++++++++++++++++++++++ scripts/validate-skills.mjs | 68 ++++++++++++++++++ skills/mcp-auth/SKILL.md | 111 ++++++++++++++++++++++++++++++ skills/mcp-server/SKILL.md | 89 ++++++++++++++++++++++++ skills/onboarding/SKILL.md | 80 +++++++++++++++++++++ 19 files changed, 1070 insertions(+), 45 deletions(-) create mode 100644 .github/workflows/validate.yml create mode 100644 claude/skills/mcp-auth/SKILL.md create mode 100644 claude/skills/mcp-server/SKILL.md create mode 100644 codex/skills/mcp-auth/SKILL.md create mode 100644 codex/skills/mcp-server/SKILL.md create mode 100644 cursor/skills/onboarding/SKILL.md create mode 100755 scripts/sync-skills.mjs create mode 100755 scripts/validate-skills.mjs create mode 100644 skills/mcp-auth/SKILL.md create mode 100644 skills/mcp-server/SKILL.md create mode 100644 skills/onboarding/SKILL.md diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..1c0fe4e --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,29 @@ +name: Validate + +on: + push: + pull_request: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Skills are identical across clients + run: node scripts/sync-skills.mjs --check + + - name: Skill frontmatter and size + run: node scripts/validate-skills.mjs + + - name: Claude plugin manifest + run: | + if command -v claude >/dev/null 2>&1; then + claude plugin validate ./claude + else + echo "::warning::claude CLI not available, skipping plugin validation" + fi diff --git a/README.md b/README.md index 2be6690..5cf550c 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,11 @@ agent-plugins/ β”œβ”€β”€ .cursor-plugin/marketplace.json # Cursor marketplace β†’ cursor β”œβ”€β”€ .claude-plugin/marketplace.json # Claude marketplace β†’ ./claude β”œβ”€β”€ .agents/plugins/marketplace.json # Codex marketplace β†’ ./codex +β”œβ”€β”€ skills/ # Canonical skills β€” edit these β”œβ”€β”€ cursor/ β”‚ β”œβ”€β”€ .cursor-plugin/plugin.json β”‚ β”œβ”€β”€ mcp.json +β”‚ β”œβ”€β”€ skills/ # Generated from ../skills β”‚ β”œβ”€β”€ assets/logo.svg β”‚ β”œβ”€β”€ README.md β”‚ β”œβ”€β”€ CHANGELOG.md @@ -40,17 +42,33 @@ agent-plugins/ β”œβ”€β”€ claude/ β”‚ β”œβ”€β”€ .claude-plugin/plugin.json β”‚ β”œβ”€β”€ .mcp.json -β”‚ β”œβ”€β”€ skills/ +β”‚ β”œβ”€β”€ skills/ # Generated from ../skills β”‚ └── README.md β”œβ”€β”€ codex/ β”‚ β”œβ”€β”€ plugin.json # Agent Plugins 1.0.0 manifest β”‚ β”œβ”€β”€ mcp.json -β”‚ β”œβ”€β”€ skills/ +β”‚ β”œβ”€β”€ skills/ # Generated from ../skills β”‚ └── README.md +β”œβ”€β”€ scripts/ β”œβ”€β”€ README.md └── LICENSE ``` +## Skills + +The five skills are agent-agnostic: anything a client does differently β€” registering an API key, +driving a browser, installing the plugin by hand β€” is a per-client table inside the shared file, so +there is one copy of every fact. + +Edit `skills/` and nothing else, then regenerate the three published copies: + +``` +node scripts/sync-skills.mjs +``` + +CI runs `node scripts/sync-skills.mjs --check` and fails if a client copy has drifted. Each client +ships its own directory because each marketplace submission reads only that directory. + ## Authentication All three plugins talk to the same endpoint, `https://docs.readme.com/mcp`, and all three ship diff --git a/claude/README.md b/claude/README.md index 8ae4d7e..b7f0ba0 100644 --- a/claude/README.md +++ b/claude/README.md @@ -59,4 +59,16 @@ Keep the single quotes so Claude Code expands the variable at startup instead of One key maps to one project. To switch projects, change the exported key and restart. -Claude Desktop Chat, Cowork and claude.ai cannot take an API key, so the plugin stays read-only there. \ No newline at end of file +Claude Desktop Chat, Cowork and claude.ai cannot take an API key, so the plugin stays read-only there. + +--- + +## Skills + +| Skill | What it does | +| ----- | ------------ | +| `mcp-server` | Keeps the agent straight on which project a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | +| `mcp-auth` | Establishes which key is in play and diagnoses the failures a missing or unresolved one produces | +| `readme-api` | The full ReadMe API v2 route map, so the agent can go straight to the right call | +| `developer-metrics-api` | Page views, search terms and page quality reads, plus sending your API's request logs to ReadMe | +| `onboarding` | Walks a new customer from signup to a published hub and a working API key | diff --git a/claude/skills/mcp-auth/SKILL.md b/claude/skills/mcp-auth/SKILL.md new file mode 100644 index 0000000..f26cc61 --- /dev/null +++ b/claude/skills/mcp-auth/SKILL.md @@ -0,0 +1,111 @@ +--- +name: mcp-auth +description: Establish or repair the ReadMe API key behind execute-request. Use when a ReadMe call fails with "Missing Security Schemes", "The API key couldn't be located", or "An unknown error has occurred", when the user asks which project their key reaches, when they say they set a key but it is not working, and before the first write to their project. +--- + +# The key behind execute-request + +The plugin ships anonymous. Public reads of ReadMe's documentation need no key; anything touching +the user's own project does, and it travels on the MCP server registration rather than in the tool +call. See the `mcp-server` skill for which calls land where. + +## Tools + +- `execute-request` + +## Assume anonymous + +Most users have not registered a key, so do not spend a call proving it. Go straight to the work: + +- ReadMe documentation questions β€” `search` and `fetch`, no key involved. +- The user's project, and they have not mentioned a key β€” go to **No key yet** below. +- The user says they registered one, or an `execute-request` call fails β€” verify with the probe. + +## Verify + +`execute-request`, spec title `ReadMe API`, with no `Authorization` header of your own: + +```json +{ + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me" + } +} +``` + +| Response | Means | Next | +| --- | --- | --- | +| A project object | The registration carries a working key | Name the project and subdomain, carry on. Ask for nothing | +| `Missing Security Schemes` | No `Authorization` header at all β€” the server is anonymous | **No key yet** | +| `"title": "The API key couldn't be located."`, status 401 | A key is being sent, but it is not a real key | **A key is set but wrong** | +| `"title": "An unknown error has occurred."`, status 500 | The bearer is empty β€” the variable resolved to nothing | **A key is set but wrong** | + +Resolve this once per session. Having seen a project object, send no `Authorization` header of your +own for the rest of the session. + +## No key yet + +If the user has not named a project, ask, and wait. Pick no project, infer none from open files or +earlier turns, and read no guides to narrow it down. Ask which project, and whether they would rather +register the key with the server or paste it in chat. + +Offer the better option first: + +- **Preferred:** they register the server with the key themselves, so it stays out of the chat. They + create the key under **Configuration β†’ API Keys** in ReadMe, then follow **Registering the key** + below. +- **Otherwise:** they paste it and you send it as a header on each call: + + ```json + { + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me", + "headers": [{ "name": "Authorization", "value": "Bearer rdme_..." }] + } + } + ``` + + This works, and it also puts the key in the transcript. Say so, and tell them to rotate it. + +Send a header of your own **only** when the probe returned `Missing Security Schemes`. A header on the +server registration overrides anything you set in `harRequest`, so against a registered server a +pasted key is silently ignored and the call lands in whichever project the registration owns β€” no +error, just the wrong project. + +## A key is set but wrong + +Both failures mean an `Authorization` header is reaching the API and the API is rejecting it. The +usual cause is the registration referring to an environment variable the client resolved to nothing, +or passed through as literal text, because the variable is unset where the client launched from: + +- **Status 500, `An unknown error has occurred.`** β€” the header arrived empty. +- **Status 401, `The API key couldn't be located.`** β€” a value arrived, but no such key exists. + Also what a revoked or mistyped key returns. + +Say that plainly before asking them to paste anything. Ask them to confirm the variable is exported +in the environment the client launched from, then reconnect as the **Registering the key** row for +their client describes. If the key is genuinely gone, they create a new one under **Configuration β†’ +API Keys**. + +Do not work around either failure by probing with `curl` or by retrying against the `Legacy API` +spec. One key maps to one project; if the call reaches the wrong project, the registration is the +thing to change. + +## Registering the key + +Registering a `readme` server of their own replaces the plugin's anonymous one. The server name stays +the same, so the skills and tools keep working. + +Find the row for the client you are running in. If you cannot tell which one that is, ask the user β€” +the wrong row sends them to a config file their client never reads. + +| Client | How | +| --- | --- | +| Claude Code | `export README_API_KEY=rdme_…`, then `claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}'`. Keep the single quotes: the variable is expanded when Claude Code starts, so the key never lands in a config file. Restart afterwards | +| Codex, and the ChatGPT desktop app that shares its config | `export README_API_KEY=rdme_…`, then `codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY`. Codex reads the variable at startup, so the key never lands in a config file. Start a new session afterwards | +| Cursor | Add a `readme` entry to `~/.cursor/mcp.json` for every project, or `.cursor/mcp.json` for one: `"type": "http"`, `"url": "https://docs.readme.com/mcp"`, and a `headers` block setting `Authorization` to `Bearer ${env:README_API_KEY}`. Export the variable in the shell the editor launches from, then restart the editor, since the header resolves when the server connects | +| Claude Desktop, Cowork, claude.ai, ChatGPT web | Not possible. The connector is read-only on these surfaces and cannot take a key. Say so, and offer to carry on in a CLI or editor | diff --git a/claude/skills/mcp-server/SKILL.md b/claude/skills/mcp-server/SKILL.md new file mode 100644 index 0000000..f39ced1 --- /dev/null +++ b/claude/skills/mcp-server/SKILL.md @@ -0,0 +1,89 @@ +--- +name: mcp-server +description: Route ReadMe MCP calls to the right project. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides" - and before calling execute-request for the first time in a session. +--- + +# Which project does this call land in? + +This plugin connects to `https://docs.readme.com/mcp`, which serves **ReadMe's own documentation**. +`search` and `fetch` answer questions about how ReadMe works. The user's project is reached only +through `execute-request` with their API key. Reads and writes land in different places. + +Questions about ReadMe itself need nothing else: use `search` and `fetch` and answer. + +## Tools on this server + +| Tool | Answers for | Use it when | +| --- | --- | --- | +| `search`, `fetch` | ReadMe's own product documentation | The question is about how ReadMe works | +| `list-specs`, `list-endpoints`, `get-endpoint`, `search-endpoints` | ReadMe's API definitions, as documents | Looking up a route before calling it | +| `execute-request` | **The user's project**, with their key | Reading or changing anything of theirs | +| `update-docs`, `draft-changelog` | Nothing. They return instructions for you to carry out | You want the recommended procedure | + +Tool availability is per-project configuration, not a fixed list. Call `tools/list` rather than +assuming a tool named here is present, and never assume one that is not. + +## The three specs + +`execute-request` reaches only servers declared in these definitions. There are three, and +`search-endpoints` searches all of them at once: + +| Spec title | Server | Auth | +| --- | --- | --- | +| `ReadMe API` | `https://api.readme.com/v2` | Bearer `rdme_...` | +| `Developer Metrics API` | `https://metrics.readme.io` | Bearer `rdme_...` | +| `Legacy API` | `https://dash.readme.com/api/v1` | HTTP basic | + +**Use `ReadMe API` for all work on the user's content.** `Legacy API` is v1: it takes basic auth +rather than a bearer token, and it is unavailable to projects on ReadMe Refactored. `search-endpoints` +will surface its routes alongside the others β€” ignore them. Never fall back to v1 when a v2 call +fails. + +## Calling execute-request + +```json +{ + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me" + } +} +``` + +- `title` names the spec and is required whenever the server carries more than one, as this one does. + Omitting it fails validation before the request is made. +- `url` must be absolute. `get-endpoint` and `search-endpoints` report paths relative to the server + (`/projects/me`), so prepend `https://api.readme.com/v2` rather than pasting the path through. +- The key decides which project the call lands in, and the user cannot override it per-request. + Name the project before you change anything; asking them which one to write to is misleading. + +Setting up, verifying, or repairing that key is the `mcp-auth` skill. + +## When the user asks about their own docs + +"Search our docs", "what does our guide say", "find the page about X in my project" cannot be +answered by `search` or `fetch` here. Those read ReadMe's documentation and would return confident, +wrong answers about someone else's content. + +Their key already reaches their content through the ReadMe API, so switch tools and carry on rather +than sending them away to configure anything: + +| They want | Call, via `execute-request`, spec title `ReadMe API` | +| --- | --- | +| Search their content | `GET https://api.readme.com/v2/search?query=...`, optionally `section`, `version`, `projects` | +| Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | +| List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | + +`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full +route map, so load that before reaching for `search-endpoints`. + +## A different server, when they actually want one + +Every ReadMe project publishes its own MCP server at `https://{subdomain}.readme.io/mcp`, or its +custom domain. That is for *their* end users to ask questions of *their* published hub. It is a +product feature they set up deliberately, not a workaround for this conversation, and it is not +needed to work on their own docs from here. + +A server's hostname decides which project it serves. Enterprise hostnames serve a whole group, so +`search` and `fetch` there can span several child projects. diff --git a/claude/skills/onboarding/SKILL.md b/claude/skills/onboarding/SKILL.md index 2866902..bb972ff 100644 --- a/claude/skills/onboarding/SKILL.md +++ b/claude/skills/onboarding/SKILL.md @@ -7,6 +7,12 @@ description: Get a new customer from zero to a live ReadMe developer hub. Use wh > Onboarding endpoints are coming soon. Until then this skill only covers the web-UI flow and ReadMe basics. +## Tools + +- `search` +- `fetch` +- `execute-request` + ## What ReadMe is ReadMe hosts a developer hub for your API at `{subdomain}.readme.io` or a custom domain. One hub contains: @@ -30,35 +36,37 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D 3. Add the API definition under **API Reference**: upload an OpenAPI file, import a URL, build one from scratch, or run `npx rdme openapi upload ` from a terminal. ReadMe validates the file and renders every endpoint. 4. Write the first guide under **Guides**. Use the AI Agent for a draft or the editor for a blank page. A "Getting Started" page is the usual first one. 5. Generate an API key at **Configuration β†’ API Keys**, URL `https://dash.readme.com/project/{subdomain}/v{version}/api-key`. -6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server with the same name at user scope, which replaces the plugin's one, then exports the key in the shell that starts the editor and restarts it. In Claude Code: +6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server under the same name, which replaces the plugin's one. The command differs per client: use the registration table in the `mcp-auth` skill, which also covers repairing a key that is already set. +7. Verify: `execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. - ``` - export README_API_KEY=rdme_… - claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}' - ``` +## Driving the browser yourself - Keep the single quotes: Claude Code expands `${README_API_KEY}` when it starts, so the key never lands in a config file. In Codex: `codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY`. Not possible in Claude Desktop Chat, Cowork or claude.ai; see the section below. -7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. +Steps 1 to 5 are all browser work. If you can drive a browser, offer to do them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. -## Doing it with Claude in Chrome +Find the row for the client you are running in. If you cannot tell which one that is, ask rather than guess. -Steps 1 to 5 are all browser work. If the Claude in Chrome extension is connected (`mcp__claude-in-chrome__*` tools are available), offer to drive them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. +| Client | Drive the browser with | +| --- | --- | +| Claude Code | `mcp__claude-in-chrome__*`, when the Claude in Chrome extension is connected | +| ChatGPT desktop app or ChatGPT web | `@Browser`. It has its own profile, so the user signs in to ReadMe there, and it asks before submitting forms. It cannot upload files, so for step 3 import the API definition by URL or run `npx rdme openapi upload ` from a terminal | +| Codex CLI, Codex IDE extension, Cursor | No browser of their own. List the steps for the user | ## When you cannot install anything yourself -In Claude Desktop Chat, Cowork and claude.ai you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands. If the `readme:*` tools are missing, the user has to install the plugin by hand. Give them these steps exactly: +On a chat surface you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands there. If the ReadMe tools are missing, the user has to install the plugin by hand. Find their client below and give them those steps exactly. -1. Click **Customize** in the left sidebar, then **Plugins**. In Cowork, open the **Cowork** tab first. -2. Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/agent-plugins`. -3. Find **readme** in the list and click **Install**, then start a new chat so the tools load. - -Plugins need a paid Claude plan. On Team and Enterprise an owner may have disabled personal marketplaces, in which case they add it under **Organization settings β†’ Plugins**. +| Client | Steps | +| --- | --- | +| Claude Desktop, Cowork, claude.ai | Click **Customize** in the left sidebar, then **Plugins** β€” in Cowork, open the **Cowork** tab first. Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/agent-plugins`. Find **readme** in the list, click **Install**, then start a new chat so the tools load. Plugins need a paid Claude plan; on Team and Enterprise an owner may have disabled personal marketplaces, in which case they add it under **Organization settings β†’ Plugins** | +| ChatGPT desktop app | Open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/agent-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load | +| ChatGPT web | There is no marketplace option, only the plugin directory. Until the ReadMe plugin is listed there, the user can still add the MCP server on its own: turn on **Developer mode** under **Settings β†’ Security and login**, open **Plugins**, click **+** next to the search box, and in the **New Plugin** form set the name to `readme`, the server URL to `https://docs.readme.com/mcp`, and authentication to **No Auth**. That gives the tools but not the skills, so keep this skill's content in the conversation yourself | +| Cursor | Open **Cursor Settings β†’ Plugins**, search for **ReadMe**, click **Install** and choose project or user scope. Or run `/add-plugin readme` in chat | -Once installed, the ReadMe connector on these surfaces is read-only: `readme:search`, `readme:fetch` and the endpoint tools work on public projects, but there is no way to supply `README_API_KEY`, so steps 6 and 7 of the Quick Start do not apply and write tools such as `readme:update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in Claude Code, Codex or Cursor with the server registered as in step 6. +On the chat surfaces above the ReadMe connector stays read-only once installed: `search`, `fetch` and the endpoint tools work on public projects, but there is no way to supply an API key, so steps 6 and 7 of the Quick Start do not apply and write tools such as `update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in a CLI or editor with the server registered as in step 6. ## Reading the docs meanwhile -Use `readme:search` for a question, then `readme:fetch` with the returned id. Useful pages: +Use `search` for a question, then `fetch` with the returned id. Useful pages: | Id | Page | | --- | --- | diff --git a/codex/README.md b/codex/README.md index e9aa817..c559896 100644 --- a/codex/README.md +++ b/codex/README.md @@ -25,3 +25,13 @@ codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var RE ``` Your `readme` entry replaces the plugin's anonymous one. The skills keep working because the server name is unchanged. Find your key under **Configuration β†’ API Keys** in your ReadMe project dashboard. + +## Skills + +| Skill | What it does | +| ----- | ------------ | +| `mcp-server` | Keeps the agent straight on which project a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | +| `mcp-auth` | Establishes which key is in play and diagnoses the failures a missing or unresolved one produces | +| `readme-api` | The full ReadMe API v2 route map, so the agent can go straight to the right call | +| `developer-metrics-api` | Page views, search terms and page quality reads, plus sending your API's request logs to ReadMe | +| `onboarding` | Walks a new customer from signup to a published hub and a working API key | diff --git a/codex/skills/mcp-auth/SKILL.md b/codex/skills/mcp-auth/SKILL.md new file mode 100644 index 0000000..f26cc61 --- /dev/null +++ b/codex/skills/mcp-auth/SKILL.md @@ -0,0 +1,111 @@ +--- +name: mcp-auth +description: Establish or repair the ReadMe API key behind execute-request. Use when a ReadMe call fails with "Missing Security Schemes", "The API key couldn't be located", or "An unknown error has occurred", when the user asks which project their key reaches, when they say they set a key but it is not working, and before the first write to their project. +--- + +# The key behind execute-request + +The plugin ships anonymous. Public reads of ReadMe's documentation need no key; anything touching +the user's own project does, and it travels on the MCP server registration rather than in the tool +call. See the `mcp-server` skill for which calls land where. + +## Tools + +- `execute-request` + +## Assume anonymous + +Most users have not registered a key, so do not spend a call proving it. Go straight to the work: + +- ReadMe documentation questions β€” `search` and `fetch`, no key involved. +- The user's project, and they have not mentioned a key β€” go to **No key yet** below. +- The user says they registered one, or an `execute-request` call fails β€” verify with the probe. + +## Verify + +`execute-request`, spec title `ReadMe API`, with no `Authorization` header of your own: + +```json +{ + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me" + } +} +``` + +| Response | Means | Next | +| --- | --- | --- | +| A project object | The registration carries a working key | Name the project and subdomain, carry on. Ask for nothing | +| `Missing Security Schemes` | No `Authorization` header at all β€” the server is anonymous | **No key yet** | +| `"title": "The API key couldn't be located."`, status 401 | A key is being sent, but it is not a real key | **A key is set but wrong** | +| `"title": "An unknown error has occurred."`, status 500 | The bearer is empty β€” the variable resolved to nothing | **A key is set but wrong** | + +Resolve this once per session. Having seen a project object, send no `Authorization` header of your +own for the rest of the session. + +## No key yet + +If the user has not named a project, ask, and wait. Pick no project, infer none from open files or +earlier turns, and read no guides to narrow it down. Ask which project, and whether they would rather +register the key with the server or paste it in chat. + +Offer the better option first: + +- **Preferred:** they register the server with the key themselves, so it stays out of the chat. They + create the key under **Configuration β†’ API Keys** in ReadMe, then follow **Registering the key** + below. +- **Otherwise:** they paste it and you send it as a header on each call: + + ```json + { + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me", + "headers": [{ "name": "Authorization", "value": "Bearer rdme_..." }] + } + } + ``` + + This works, and it also puts the key in the transcript. Say so, and tell them to rotate it. + +Send a header of your own **only** when the probe returned `Missing Security Schemes`. A header on the +server registration overrides anything you set in `harRequest`, so against a registered server a +pasted key is silently ignored and the call lands in whichever project the registration owns β€” no +error, just the wrong project. + +## A key is set but wrong + +Both failures mean an `Authorization` header is reaching the API and the API is rejecting it. The +usual cause is the registration referring to an environment variable the client resolved to nothing, +or passed through as literal text, because the variable is unset where the client launched from: + +- **Status 500, `An unknown error has occurred.`** β€” the header arrived empty. +- **Status 401, `The API key couldn't be located.`** β€” a value arrived, but no such key exists. + Also what a revoked or mistyped key returns. + +Say that plainly before asking them to paste anything. Ask them to confirm the variable is exported +in the environment the client launched from, then reconnect as the **Registering the key** row for +their client describes. If the key is genuinely gone, they create a new one under **Configuration β†’ +API Keys**. + +Do not work around either failure by probing with `curl` or by retrying against the `Legacy API` +spec. One key maps to one project; if the call reaches the wrong project, the registration is the +thing to change. + +## Registering the key + +Registering a `readme` server of their own replaces the plugin's anonymous one. The server name stays +the same, so the skills and tools keep working. + +Find the row for the client you are running in. If you cannot tell which one that is, ask the user β€” +the wrong row sends them to a config file their client never reads. + +| Client | How | +| --- | --- | +| Claude Code | `export README_API_KEY=rdme_…`, then `claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}'`. Keep the single quotes: the variable is expanded when Claude Code starts, so the key never lands in a config file. Restart afterwards | +| Codex, and the ChatGPT desktop app that shares its config | `export README_API_KEY=rdme_…`, then `codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY`. Codex reads the variable at startup, so the key never lands in a config file. Start a new session afterwards | +| Cursor | Add a `readme` entry to `~/.cursor/mcp.json` for every project, or `.cursor/mcp.json` for one: `"type": "http"`, `"url": "https://docs.readme.com/mcp"`, and a `headers` block setting `Authorization` to `Bearer ${env:README_API_KEY}`. Export the variable in the shell the editor launches from, then restart the editor, since the header resolves when the server connects | +| Claude Desktop, Cowork, claude.ai, ChatGPT web | Not possible. The connector is read-only on these surfaces and cannot take a key. Say so, and offer to carry on in a CLI or editor | diff --git a/codex/skills/mcp-server/SKILL.md b/codex/skills/mcp-server/SKILL.md new file mode 100644 index 0000000..f39ced1 --- /dev/null +++ b/codex/skills/mcp-server/SKILL.md @@ -0,0 +1,89 @@ +--- +name: mcp-server +description: Route ReadMe MCP calls to the right project. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides" - and before calling execute-request for the first time in a session. +--- + +# Which project does this call land in? + +This plugin connects to `https://docs.readme.com/mcp`, which serves **ReadMe's own documentation**. +`search` and `fetch` answer questions about how ReadMe works. The user's project is reached only +through `execute-request` with their API key. Reads and writes land in different places. + +Questions about ReadMe itself need nothing else: use `search` and `fetch` and answer. + +## Tools on this server + +| Tool | Answers for | Use it when | +| --- | --- | --- | +| `search`, `fetch` | ReadMe's own product documentation | The question is about how ReadMe works | +| `list-specs`, `list-endpoints`, `get-endpoint`, `search-endpoints` | ReadMe's API definitions, as documents | Looking up a route before calling it | +| `execute-request` | **The user's project**, with their key | Reading or changing anything of theirs | +| `update-docs`, `draft-changelog` | Nothing. They return instructions for you to carry out | You want the recommended procedure | + +Tool availability is per-project configuration, not a fixed list. Call `tools/list` rather than +assuming a tool named here is present, and never assume one that is not. + +## The three specs + +`execute-request` reaches only servers declared in these definitions. There are three, and +`search-endpoints` searches all of them at once: + +| Spec title | Server | Auth | +| --- | --- | --- | +| `ReadMe API` | `https://api.readme.com/v2` | Bearer `rdme_...` | +| `Developer Metrics API` | `https://metrics.readme.io` | Bearer `rdme_...` | +| `Legacy API` | `https://dash.readme.com/api/v1` | HTTP basic | + +**Use `ReadMe API` for all work on the user's content.** `Legacy API` is v1: it takes basic auth +rather than a bearer token, and it is unavailable to projects on ReadMe Refactored. `search-endpoints` +will surface its routes alongside the others β€” ignore them. Never fall back to v1 when a v2 call +fails. + +## Calling execute-request + +```json +{ + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me" + } +} +``` + +- `title` names the spec and is required whenever the server carries more than one, as this one does. + Omitting it fails validation before the request is made. +- `url` must be absolute. `get-endpoint` and `search-endpoints` report paths relative to the server + (`/projects/me`), so prepend `https://api.readme.com/v2` rather than pasting the path through. +- The key decides which project the call lands in, and the user cannot override it per-request. + Name the project before you change anything; asking them which one to write to is misleading. + +Setting up, verifying, or repairing that key is the `mcp-auth` skill. + +## When the user asks about their own docs + +"Search our docs", "what does our guide say", "find the page about X in my project" cannot be +answered by `search` or `fetch` here. Those read ReadMe's documentation and would return confident, +wrong answers about someone else's content. + +Their key already reaches their content through the ReadMe API, so switch tools and carry on rather +than sending them away to configure anything: + +| They want | Call, via `execute-request`, spec title `ReadMe API` | +| --- | --- | +| Search their content | `GET https://api.readme.com/v2/search?query=...`, optionally `section`, `version`, `projects` | +| Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | +| List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | + +`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full +route map, so load that before reaching for `search-endpoints`. + +## A different server, when they actually want one + +Every ReadMe project publishes its own MCP server at `https://{subdomain}.readme.io/mcp`, or its +custom domain. That is for *their* end users to ask questions of *their* published hub. It is a +product feature they set up deliberately, not a workaround for this conversation, and it is not +needed to work on their own docs from here. + +A server's hostname decides which project it serves. Enterprise hostnames serve a whole group, so +`search` and `fetch` there can span several child projects. diff --git a/codex/skills/onboarding/SKILL.md b/codex/skills/onboarding/SKILL.md index 66b7318..b2d274c 100644 --- a/codex/skills/onboarding/SKILL.md +++ b/codex/skills/onboarding/SKILL.md @@ -7,6 +7,12 @@ description: Get a new customer from zero to a live ReadMe developer hub. Use wh > Onboarding endpoints are coming soon. Until then this skill only covers the web-UI flow and ReadMe basics. +## Tools + +- `search` +- `fetch` +- `execute-request` + ## What ReadMe is ReadMe hosts a developer hub for your API at `{subdomain}.readme.io` or a custom domain. One hub contains: @@ -30,34 +36,39 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D 3. Add the API definition under **API Reference**: upload an OpenAPI file, import a URL, build one from scratch, or run `npx rdme openapi upload ` from a terminal. ReadMe validates the file and renders every endpoint. 4. Write the first guide under **Guides**. Use the AI Agent for a draft or the editor for a blank page. A "Getting Started" page is the usual first one. 5. Generate an API key at **Configuration β†’ API Keys**, URL `https://dash.readme.com/project/{subdomain}/v{version}/api-key`. -6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server with the same name, which replaces the plugin's one, then exports the key in the shell that starts Codex and starts a new session. In Codex: +6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server under the same name, which replaces the plugin's one. The command differs per client: use the registration table in the `mcp-auth` skill, which also covers repairing a key that is already set. +7. Verify: `execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. - ``` - export README_API_KEY=rdme_… - codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY - ``` +After step 7, load the `readme-api` skill for anything else in the project. - Codex reads the variable at startup, so the key never lands in a config file. The ChatGPT desktop app shares Codex's config, so this registration also covers Codex sessions there. In Claude Code the equivalent is `claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}'`. Not possible in ChatGPT web; see the section below. -7. Verify: `readme:execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. +## Driving the browser yourself -After step 7, load the `readme-api` skill for anything else in the project. +Steps 1 to 5 are all browser work. If you can drive a browser, offer to do them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. -## Doing it with the ChatGPT browser +Find the row for the client you are running in. If you cannot tell which one that is, ask rather than guess. -Steps 1 to 5 are all browser work. In the ChatGPT desktop app or ChatGPT web, offer to drive them with `@Browser` instead of only listing the steps: open the signup page, create the project, and open the API Keys page. The built-in browser has its own profile, so the user signs in to ReadMe there and types credentials and payment details themselves; ChatGPT asks before submitting forms. It cannot upload files, so for step 3 import the OpenAPI definition by URL or run `npx rdme openapi upload ` from Codex. Codex CLI and the IDE extension have no browser; list the steps there. Steps 6 and 7 stay in the terminal. +| Client | Drive the browser with | +| --- | --- | +| Claude Code | `mcp__claude-in-chrome__*`, when the Claude in Chrome extension is connected | +| ChatGPT desktop app or ChatGPT web | `@Browser`. It has its own profile, so the user signs in to ReadMe there, and it asks before submitting forms. It cannot upload files, so for step 3 import the API definition by URL or run `npx rdme openapi upload ` from a terminal | +| Codex CLI, Codex IDE extension, Cursor | No browser of their own. List the steps for the user | ## When you cannot install anything yourself -In a ChatGPT chat, desktop or web, you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands in the chat. If the `readme:*` tools are missing, the user has to install the plugin by hand. Give them these steps exactly: +On a chat surface you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands there. If the ReadMe tools are missing, the user has to install the plugin by hand. Find their client below and give them those steps exactly. -- ChatGPT desktop app: open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/agent-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load. -- ChatGPT web: there is no marketplace option, only the plugin directory. Until the ReadMe plugin is listed there, the user can still add the MCP server on its own: turn on **Developer mode** under **Settings β†’ Security and login**, open **Plugins**, click **+** next to the search box, and in the **New Plugin** form set the name to `readme`, the server URL to `https://docs.readme.com/mcp`, and authentication to **No Auth**. That gives the `readme:*` tools but not the skills, so keep this skill's content in the conversation yourself. +| Client | Steps | +| --- | --- | +| Claude Desktop, Cowork, claude.ai | Click **Customize** in the left sidebar, then **Plugins** β€” in Cowork, open the **Cowork** tab first. Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/agent-plugins`. Find **readme** in the list, click **Install**, then start a new chat so the tools load. Plugins need a paid Claude plan; on Team and Enterprise an owner may have disabled personal marketplaces, in which case they add it under **Organization settings β†’ Plugins** | +| ChatGPT desktop app | Open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/agent-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load | +| ChatGPT web | There is no marketplace option, only the plugin directory. Until the ReadMe plugin is listed there, the user can still add the MCP server on its own: turn on **Developer mode** under **Settings β†’ Security and login**, open **Plugins**, click **+** next to the search box, and in the **New Plugin** form set the name to `readme`, the server URL to `https://docs.readme.com/mcp`, and authentication to **No Auth**. That gives the tools but not the skills, so keep this skill's content in the conversation yourself | +| Cursor | Open **Cursor Settings β†’ Plugins**, search for **ReadMe**, click **Install** and choose project or user scope. Or run `/add-plugin readme` in chat | -Once installed, the ReadMe connector in a chat is read-only: `readme:search`, `readme:fetch` and the endpoint tools work on public projects, but ChatGPT cannot take an API key, so steps 6 and 7 of the Quick Start do not apply and write tools such as `readme:update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in Codex with the server registered as in step 6. +On the chat surfaces above the ReadMe connector stays read-only once installed: `search`, `fetch` and the endpoint tools work on public projects, but there is no way to supply an API key, so steps 6 and 7 of the Quick Start do not apply and write tools such as `update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in a CLI or editor with the server registered as in step 6. ## Reading the docs meanwhile -Use `readme:search` for a question, then `readme:fetch` with the returned id. Useful pages: +Use `search` for a question, then `fetch` with the returned id. Useful pages: | Id | Page | | --- | --- | diff --git a/cursor/README.md b/cursor/README.md index aebf313..7c76b60 100644 --- a/cursor/README.md +++ b/cursor/README.md @@ -95,6 +95,9 @@ and the agent carries it out through `execute-request`. | ----- | ------------ | | `mcp-server` | Keeps the agent straight on which project a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | | `mcp-auth` | Establishes which key is in play and diagnoses the failures a missing or unresolved one produces | +| `readme-api` | The full ReadMe API v2 route map, so the agent can go straight to the right call | +| `developer-metrics-api` | Page views, search terms and page quality reads, plus sending your API's request logs to ReadMe | +| `onboarding` | Walks a new customer from signup to a published hub and a working API key | ## Which ReadMe MCP server is this? diff --git a/cursor/skills/mcp-auth/SKILL.md b/cursor/skills/mcp-auth/SKILL.md index a39ea9e..f26cc61 100644 --- a/cursor/skills/mcp-auth/SKILL.md +++ b/cursor/skills/mcp-auth/SKILL.md @@ -9,6 +9,10 @@ The plugin ships anonymous. Public reads of ReadMe's documentation need no key; the user's own project does, and it travels on the MCP server registration rather than in the tool call. See the `mcp-server` skill for which calls land where. +## Tools + +- `execute-request` + ## Assume anonymous Most users have not registered a key, so do not spend a call proving it. Go straight to the work: @@ -49,10 +53,9 @@ register the key with the server or paste it in chat. Offer the better option first: -- **Preferred:** they register the server with the key themselves, so it stays out of the chat. The - plugin README has the `~/.cursor/mcp.json` snippet. They create the key under **Configuration β†’ - API Keys** in ReadMe. This takes an editor restart, since the header resolves when the server - connects. +- **Preferred:** they register the server with the key themselves, so it stays out of the chat. They + create the key under **Configuration β†’ API Keys** in ReadMe, then follow **Registering the key** + below. - **Otherwise:** they paste it and you send it as a header on each call: ```json @@ -76,17 +79,33 @@ error, just the wrong project. ## A key is set but wrong Both failures mean an `Authorization` header is reaching the API and the API is rejecting it. The -usual cause is a placeholder in `mcp.json` β€” `${env:README_API_KEY}` β€” that the client resolved to -nothing, or passed through as literal text, because the variable is unset: +usual cause is the registration referring to an environment variable the client resolved to nothing, +or passed through as literal text, because the variable is unset where the client launched from: - **Status 500, `An unknown error has occurred.`** β€” the header arrived empty. - **Status 401, `The API key couldn't be located.`** β€” a value arrived, but no such key exists. Also what a revoked or mistyped key returns. Say that plainly before asking them to paste anything. Ask them to confirm the variable is exported -in the environment the editor launched from, then restart the editor. If the key is genuinely gone, -they create a new one under **Configuration β†’ API Keys**. +in the environment the client launched from, then reconnect as the **Registering the key** row for +their client describes. If the key is genuinely gone, they create a new one under **Configuration β†’ +API Keys**. Do not work around either failure by probing with `curl` or by retrying against the `Legacy API` spec. One key maps to one project; if the call reaches the wrong project, the registration is the thing to change. + +## Registering the key + +Registering a `readme` server of their own replaces the plugin's anonymous one. The server name stays +the same, so the skills and tools keep working. + +Find the row for the client you are running in. If you cannot tell which one that is, ask the user β€” +the wrong row sends them to a config file their client never reads. + +| Client | How | +| --- | --- | +| Claude Code | `export README_API_KEY=rdme_…`, then `claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}'`. Keep the single quotes: the variable is expanded when Claude Code starts, so the key never lands in a config file. Restart afterwards | +| Codex, and the ChatGPT desktop app that shares its config | `export README_API_KEY=rdme_…`, then `codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY`. Codex reads the variable at startup, so the key never lands in a config file. Start a new session afterwards | +| Cursor | Add a `readme` entry to `~/.cursor/mcp.json` for every project, or `.cursor/mcp.json` for one: `"type": "http"`, `"url": "https://docs.readme.com/mcp"`, and a `headers` block setting `Authorization` to `Bearer ${env:README_API_KEY}`. Export the variable in the shell the editor launches from, then restart the editor, since the header resolves when the server connects | +| Claude Desktop, Cowork, claude.ai, ChatGPT web | Not possible. The connector is read-only on these surfaces and cannot take a key. Say so, and offer to carry on in a CLI or editor | diff --git a/cursor/skills/mcp-server/SKILL.md b/cursor/skills/mcp-server/SKILL.md index 1150430..f39ced1 100644 --- a/cursor/skills/mcp-server/SKILL.md +++ b/cursor/skills/mcp-server/SKILL.md @@ -75,8 +75,8 @@ than sending them away to configure anything: | Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | | List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | -`{branch}` is a version number, `stable`, or a branch name. Use `search-endpoints` with spec title -`ReadMe API` when a request goes beyond these. +`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full +route map, so load that before reaching for `search-endpoints`. ## A different server, when they actually want one diff --git a/cursor/skills/onboarding/SKILL.md b/cursor/skills/onboarding/SKILL.md new file mode 100644 index 0000000..b2d274c --- /dev/null +++ b/cursor/skills/onboarding/SKILL.md @@ -0,0 +1,80 @@ +--- +name: onboarding +description: Get a new customer from zero to a live ReadMe developer hub. Use when someone is new to ReadMe, asks what ReadMe is, wants to sign up, create a project, publish their first API reference or guide, or needs an API key for this plugin. Explains the product and walks the web-UI setup flow. +--- + +# ReadMe onboarding + +> Onboarding endpoints are coming soon. Until then this skill only covers the web-UI flow and ReadMe basics. + +## Tools + +- `search` +- `fetch` +- `execute-request` + +## What ReadMe is + +ReadMe hosts a developer hub for your API at `{subdomain}.readme.io` or a custom domain. One hub contains: + +| Section | Content | +| --- | --- | +| Guides | Markdown pages in categories, with a sidebar | +| API Reference | Interactive docs generated from an OpenAPI or Swagger definition, with a Try It console | +| Recipes | Step-by-step code walkthroughs | +| Changelog | Release notes, shared across versions | +| Custom Pages | Free-form Markdown or HTML pages | + +Guides, reference, recipes and custom pages live on a **branch** (a version such as `1.0` or `stable`). The changelog does not. Ask AI and the project's MCP server answer questions from the hub content. Metrics track page views, search, page quality, and, with SDK setup, API calls. + +Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and Developer Metrics API reads. + +## Quick Start + +1. Sign up at `https://dash.readme.com/signup`. +2. Click **Create New Project**. Set a name, upload a logo (ReadMe picks brand colors from it), and choose the subdomain. +3. Add the API definition under **API Reference**: upload an OpenAPI file, import a URL, build one from scratch, or run `npx rdme openapi upload ` from a terminal. ReadMe validates the file and renders every endpoint. +4. Write the first guide under **Guides**. Use the AI Agent for a draft or the editor for a blank page. A "Getting Started" page is the usual first one. +5. Generate an API key at **Configuration β†’ API Keys**, URL `https://dash.readme.com/project/{subdomain}/v{version}/api-key`. +6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server under the same name, which replaces the plugin's one. The command differs per client: use the registration table in the `mcp-auth` skill, which also covers repairing a key that is already set. +7. Verify: `execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. + +After step 7, load the `readme-api` skill for anything else in the project. + +## Driving the browser yourself + +Steps 1 to 5 are all browser work. If you can drive a browser, offer to do them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. + +Find the row for the client you are running in. If you cannot tell which one that is, ask rather than guess. + +| Client | Drive the browser with | +| --- | --- | +| Claude Code | `mcp__claude-in-chrome__*`, when the Claude in Chrome extension is connected | +| ChatGPT desktop app or ChatGPT web | `@Browser`. It has its own profile, so the user signs in to ReadMe there, and it asks before submitting forms. It cannot upload files, so for step 3 import the API definition by URL or run `npx rdme openapi upload ` from a terminal | +| Codex CLI, Codex IDE extension, Cursor | No browser of their own. List the steps for the user | + +## When you cannot install anything yourself + +On a chat surface you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands there. If the ReadMe tools are missing, the user has to install the plugin by hand. Find their client below and give them those steps exactly. + +| Client | Steps | +| --- | --- | +| Claude Desktop, Cowork, claude.ai | Click **Customize** in the left sidebar, then **Plugins** β€” in Cowork, open the **Cowork** tab first. Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/agent-plugins`. Find **readme** in the list, click **Install**, then start a new chat so the tools load. Plugins need a paid Claude plan; on Team and Enterprise an owner may have disabled personal marketplaces, in which case they add it under **Organization settings β†’ Plugins** | +| ChatGPT desktop app | Open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/agent-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load | +| ChatGPT web | There is no marketplace option, only the plugin directory. Until the ReadMe plugin is listed there, the user can still add the MCP server on its own: turn on **Developer mode** under **Settings β†’ Security and login**, open **Plugins**, click **+** next to the search box, and in the **New Plugin** form set the name to `readme`, the server URL to `https://docs.readme.com/mcp`, and authentication to **No Auth**. That gives the tools but not the skills, so keep this skill's content in the conversation yourself | +| Cursor | Open **Cursor Settings β†’ Plugins**, search for **ReadMe**, click **Install** and choose project or user scope. Or run `/add-plugin readme` in chat | + +On the chat surfaces above the ReadMe connector stays read-only once installed: `search`, `fetch` and the endpoint tools work on public projects, but there is no way to supply an API key, so steps 6 and 7 of the Quick Start do not apply and write tools such as `update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in a CLI or editor with the server registered as in step 6. + +## Reading the docs meanwhile + +Use `search` for a question, then `fetch` with the returned id. Useful pages: + +| Id | Page | +| --- | --- | +| `main/quickstart` | Three-step setup | +| `main/creating-a-project` | Project settings on creation | +| `main/openapi-upload-and-management` | Upload, sync, and re-sync an OpenAPI file | +| `main/branches` | How branches and versions work | +| `ref:main/intro-to-the-readme-api` | API v2 overview and auth | +| `main/sdks` | Metrics SDKs for API logs | diff --git a/scripts/sync-skills.mjs b/scripts/sync-skills.mjs new file mode 100755 index 0000000..5ae219a --- /dev/null +++ b/scripts/sync-skills.mjs @@ -0,0 +1,87 @@ +#!/usr/bin/env node +import { readdir, readFile, mkdir, copyFile, rm } from 'node:fs/promises'; +import { dirname, join, relative, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const source = join(repoRoot, 'skills'); +const hosts = ['claude', 'codex', 'cursor']; + +async function listFiles(root) { + const found = []; + async function walk(dir) { + let entries; + try { + entries = await readdir(dir, { withFileTypes: true }); + } catch (error) { + if (error.code === 'ENOENT') return; + throw error; + } + for (const entry of entries) { + const full = join(dir, entry.name); + if (entry.isDirectory()) await walk(full); + else found.push(relative(root, full)); + } + } + await walk(root); + return found.sort(); +} + +async function sameContent(a, b) { + const [left, right] = await Promise.all([readFile(a), readFile(b)]); + return left.equals(right); +} + +const sourceFiles = await listFiles(source); +if (sourceFiles.length === 0) { + console.error(`No skills found in ${relative(repoRoot, source)}`); + process.exit(1); +} + +const check = process.argv.includes('--check'); +const problems = []; + +for (const host of hosts) { + const target = join(repoRoot, host, 'skills'); + const targetFiles = await listFiles(target); + const extras = targetFiles.filter((file) => !sourceFiles.includes(file)); + + for (const file of sourceFiles) { + const from = join(source, file); + const to = join(target, file); + if (check) { + if (!targetFiles.includes(file)) problems.push(`missing: ${host}/skills/${file}`); + else if (!(await sameContent(from, to))) problems.push(`differs: ${host}/skills/${file}`); + continue; + } + await mkdir(dirname(to), { recursive: true }); + await copyFile(from, to); + } + + for (const file of extras) { + if (check) problems.push(`extra: ${host}/skills/${file}`); + else await rm(join(target, file)); + } +} + +if (!check) { + for (const host of hosts) { + const target = join(repoRoot, host, 'skills'); + for (const entry of await readdir(target, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + const contents = await listFiles(join(target, entry.name)); + if (contents.length === 0) await rm(join(target, entry.name), { recursive: true }); + } + } + console.log(`Synced ${sourceFiles.length} file(s) to ${hosts.join(', ')}`); + process.exit(0); +} + +if (problems.length > 0) { + console.error('Generated skills are out of sync with skills/:'); + for (const problem of problems) console.error(` ${problem}`); + console.error('\nRun `node scripts/sync-skills.mjs` and commit the result.'); + process.exit(1); +} + +console.log(`Skills are in sync across ${hosts.join(', ')}`); diff --git a/scripts/validate-skills.mjs b/scripts/validate-skills.mjs new file mode 100755 index 0000000..4bbb2c5 --- /dev/null +++ b/scripts/validate-skills.mjs @@ -0,0 +1,68 @@ +#!/usr/bin/env node +import { readdir, readFile } from 'node:fs/promises'; +import { basename, dirname, join, relative, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const SKILL_CHAR_LIMIT = 20000; + +const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const roots = ['skills', 'claude/skills', 'codex/skills', 'cursor/skills']; +const problems = []; + +function parseFrontmatter(text) { + const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/); + if (!match) return null; + const fields = {}; + for (const line of match[1].split(/\r?\n/)) { + const field = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/); + if (field) fields[field[1]] = field[2].trim(); + } + return fields; +} + +for (const root of roots) { + const dir = join(repoRoot, root); + let entries; + try { + entries = await readdir(dir, { withFileTypes: true }); + } catch { + problems.push(`${root}: directory is missing`); + continue; + } + + for (const entry of entries) { + if (!entry.isDirectory()) continue; + const path = join(dir, entry.name, 'SKILL.md'); + const label = relative(repoRoot, path); + let text; + try { + text = await readFile(path, 'utf8'); + } catch { + problems.push(`${label}: skill directory has no SKILL.md`); + continue; + } + + if (text.length > SKILL_CHAR_LIMIT) { + problems.push(`${label}: ${text.length} chars exceeds the ${SKILL_CHAR_LIMIT} limit`); + } + + const frontmatter = parseFrontmatter(text); + if (!frontmatter) { + problems.push(`${label}: no YAML frontmatter`); + continue; + } + if (!frontmatter.name) problems.push(`${label}: frontmatter has no name`); + else if (frontmatter.name !== basename(dirname(path))) { + problems.push(`${label}: name "${frontmatter.name}" does not match its directory`); + } + if (!frontmatter.description) problems.push(`${label}: frontmatter has no description`); + } +} + +if (problems.length > 0) { + console.error('Skill validation failed:'); + for (const problem of problems) console.error(` ${problem}`); + process.exit(1); +} + +console.log(`Validated frontmatter and size for skills in ${roots.join(', ')}`); diff --git a/skills/mcp-auth/SKILL.md b/skills/mcp-auth/SKILL.md new file mode 100644 index 0000000..f26cc61 --- /dev/null +++ b/skills/mcp-auth/SKILL.md @@ -0,0 +1,111 @@ +--- +name: mcp-auth +description: Establish or repair the ReadMe API key behind execute-request. Use when a ReadMe call fails with "Missing Security Schemes", "The API key couldn't be located", or "An unknown error has occurred", when the user asks which project their key reaches, when they say they set a key but it is not working, and before the first write to their project. +--- + +# The key behind execute-request + +The plugin ships anonymous. Public reads of ReadMe's documentation need no key; anything touching +the user's own project does, and it travels on the MCP server registration rather than in the tool +call. See the `mcp-server` skill for which calls land where. + +## Tools + +- `execute-request` + +## Assume anonymous + +Most users have not registered a key, so do not spend a call proving it. Go straight to the work: + +- ReadMe documentation questions β€” `search` and `fetch`, no key involved. +- The user's project, and they have not mentioned a key β€” go to **No key yet** below. +- The user says they registered one, or an `execute-request` call fails β€” verify with the probe. + +## Verify + +`execute-request`, spec title `ReadMe API`, with no `Authorization` header of your own: + +```json +{ + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me" + } +} +``` + +| Response | Means | Next | +| --- | --- | --- | +| A project object | The registration carries a working key | Name the project and subdomain, carry on. Ask for nothing | +| `Missing Security Schemes` | No `Authorization` header at all β€” the server is anonymous | **No key yet** | +| `"title": "The API key couldn't be located."`, status 401 | A key is being sent, but it is not a real key | **A key is set but wrong** | +| `"title": "An unknown error has occurred."`, status 500 | The bearer is empty β€” the variable resolved to nothing | **A key is set but wrong** | + +Resolve this once per session. Having seen a project object, send no `Authorization` header of your +own for the rest of the session. + +## No key yet + +If the user has not named a project, ask, and wait. Pick no project, infer none from open files or +earlier turns, and read no guides to narrow it down. Ask which project, and whether they would rather +register the key with the server or paste it in chat. + +Offer the better option first: + +- **Preferred:** they register the server with the key themselves, so it stays out of the chat. They + create the key under **Configuration β†’ API Keys** in ReadMe, then follow **Registering the key** + below. +- **Otherwise:** they paste it and you send it as a header on each call: + + ```json + { + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me", + "headers": [{ "name": "Authorization", "value": "Bearer rdme_..." }] + } + } + ``` + + This works, and it also puts the key in the transcript. Say so, and tell them to rotate it. + +Send a header of your own **only** when the probe returned `Missing Security Schemes`. A header on the +server registration overrides anything you set in `harRequest`, so against a registered server a +pasted key is silently ignored and the call lands in whichever project the registration owns β€” no +error, just the wrong project. + +## A key is set but wrong + +Both failures mean an `Authorization` header is reaching the API and the API is rejecting it. The +usual cause is the registration referring to an environment variable the client resolved to nothing, +or passed through as literal text, because the variable is unset where the client launched from: + +- **Status 500, `An unknown error has occurred.`** β€” the header arrived empty. +- **Status 401, `The API key couldn't be located.`** β€” a value arrived, but no such key exists. + Also what a revoked or mistyped key returns. + +Say that plainly before asking them to paste anything. Ask them to confirm the variable is exported +in the environment the client launched from, then reconnect as the **Registering the key** row for +their client describes. If the key is genuinely gone, they create a new one under **Configuration β†’ +API Keys**. + +Do not work around either failure by probing with `curl` or by retrying against the `Legacy API` +spec. One key maps to one project; if the call reaches the wrong project, the registration is the +thing to change. + +## Registering the key + +Registering a `readme` server of their own replaces the plugin's anonymous one. The server name stays +the same, so the skills and tools keep working. + +Find the row for the client you are running in. If you cannot tell which one that is, ask the user β€” +the wrong row sends them to a config file their client never reads. + +| Client | How | +| --- | --- | +| Claude Code | `export README_API_KEY=rdme_…`, then `claude mcp add --scope user --transport http readme https://docs.readme.com/mcp --header 'Authorization: Bearer ${README_API_KEY}'`. Keep the single quotes: the variable is expanded when Claude Code starts, so the key never lands in a config file. Restart afterwards | +| Codex, and the ChatGPT desktop app that shares its config | `export README_API_KEY=rdme_…`, then `codex mcp add readme --url https://docs.readme.com/mcp --bearer-token-env-var README_API_KEY`. Codex reads the variable at startup, so the key never lands in a config file. Start a new session afterwards | +| Cursor | Add a `readme` entry to `~/.cursor/mcp.json` for every project, or `.cursor/mcp.json` for one: `"type": "http"`, `"url": "https://docs.readme.com/mcp"`, and a `headers` block setting `Authorization` to `Bearer ${env:README_API_KEY}`. Export the variable in the shell the editor launches from, then restart the editor, since the header resolves when the server connects | +| Claude Desktop, Cowork, claude.ai, ChatGPT web | Not possible. The connector is read-only on these surfaces and cannot take a key. Say so, and offer to carry on in a CLI or editor | diff --git a/skills/mcp-server/SKILL.md b/skills/mcp-server/SKILL.md new file mode 100644 index 0000000..f39ced1 --- /dev/null +++ b/skills/mcp-server/SKILL.md @@ -0,0 +1,89 @@ +--- +name: mcp-server +description: Route ReadMe MCP calls to the right project. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides" - and before calling execute-request for the first time in a session. +--- + +# Which project does this call land in? + +This plugin connects to `https://docs.readme.com/mcp`, which serves **ReadMe's own documentation**. +`search` and `fetch` answer questions about how ReadMe works. The user's project is reached only +through `execute-request` with their API key. Reads and writes land in different places. + +Questions about ReadMe itself need nothing else: use `search` and `fetch` and answer. + +## Tools on this server + +| Tool | Answers for | Use it when | +| --- | --- | --- | +| `search`, `fetch` | ReadMe's own product documentation | The question is about how ReadMe works | +| `list-specs`, `list-endpoints`, `get-endpoint`, `search-endpoints` | ReadMe's API definitions, as documents | Looking up a route before calling it | +| `execute-request` | **The user's project**, with their key | Reading or changing anything of theirs | +| `update-docs`, `draft-changelog` | Nothing. They return instructions for you to carry out | You want the recommended procedure | + +Tool availability is per-project configuration, not a fixed list. Call `tools/list` rather than +assuming a tool named here is present, and never assume one that is not. + +## The three specs + +`execute-request` reaches only servers declared in these definitions. There are three, and +`search-endpoints` searches all of them at once: + +| Spec title | Server | Auth | +| --- | --- | --- | +| `ReadMe API` | `https://api.readme.com/v2` | Bearer `rdme_...` | +| `Developer Metrics API` | `https://metrics.readme.io` | Bearer `rdme_...` | +| `Legacy API` | `https://dash.readme.com/api/v1` | HTTP basic | + +**Use `ReadMe API` for all work on the user's content.** `Legacy API` is v1: it takes basic auth +rather than a bearer token, and it is unavailable to projects on ReadMe Refactored. `search-endpoints` +will surface its routes alongside the others β€” ignore them. Never fall back to v1 when a v2 call +fails. + +## Calling execute-request + +```json +{ + "title": "ReadMe API", + "harRequest": { + "method": "get", + "url": "https://api.readme.com/v2/projects/me" + } +} +``` + +- `title` names the spec and is required whenever the server carries more than one, as this one does. + Omitting it fails validation before the request is made. +- `url` must be absolute. `get-endpoint` and `search-endpoints` report paths relative to the server + (`/projects/me`), so prepend `https://api.readme.com/v2` rather than pasting the path through. +- The key decides which project the call lands in, and the user cannot override it per-request. + Name the project before you change anything; asking them which one to write to is misleading. + +Setting up, verifying, or repairing that key is the `mcp-auth` skill. + +## When the user asks about their own docs + +"Search our docs", "what does our guide say", "find the page about X in my project" cannot be +answered by `search` or `fetch` here. Those read ReadMe's documentation and would return confident, +wrong answers about someone else's content. + +Their key already reaches their content through the ReadMe API, so switch tools and carry on rather +than sending them away to configure anything: + +| They want | Call, via `execute-request`, spec title `ReadMe API` | +| --- | --- | +| Search their content | `GET https://api.readme.com/v2/search?query=...`, optionally `section`, `version`, `projects` | +| Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | +| List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | + +`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full +route map, so load that before reaching for `search-endpoints`. + +## A different server, when they actually want one + +Every ReadMe project publishes its own MCP server at `https://{subdomain}.readme.io/mcp`, or its +custom domain. That is for *their* end users to ask questions of *their* published hub. It is a +product feature they set up deliberately, not a workaround for this conversation, and it is not +needed to work on their own docs from here. + +A server's hostname decides which project it serves. Enterprise hostnames serve a whole group, so +`search` and `fetch` there can span several child projects. diff --git a/skills/onboarding/SKILL.md b/skills/onboarding/SKILL.md new file mode 100644 index 0000000..b2d274c --- /dev/null +++ b/skills/onboarding/SKILL.md @@ -0,0 +1,80 @@ +--- +name: onboarding +description: Get a new customer from zero to a live ReadMe developer hub. Use when someone is new to ReadMe, asks what ReadMe is, wants to sign up, create a project, publish their first API reference or guide, or needs an API key for this plugin. Explains the product and walks the web-UI setup flow. +--- + +# ReadMe onboarding + +> Onboarding endpoints are coming soon. Until then this skill only covers the web-UI flow and ReadMe basics. + +## Tools + +- `search` +- `fetch` +- `execute-request` + +## What ReadMe is + +ReadMe hosts a developer hub for your API at `{subdomain}.readme.io` or a custom domain. One hub contains: + +| Section | Content | +| --- | --- | +| Guides | Markdown pages in categories, with a sidebar | +| API Reference | Interactive docs generated from an OpenAPI or Swagger definition, with a Try It console | +| Recipes | Step-by-step code walkthroughs | +| Changelog | Release notes, shared across versions | +| Custom Pages | Free-form Markdown or HTML pages | + +Guides, reference, recipes and custom pages live on a **branch** (a version such as `1.0` or `stable`). The changelog does not. Ask AI and the project's MCP server answer questions from the hub content. Metrics track page views, search, page quality, and, with SDK setup, API calls. + +Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and Developer Metrics API reads. + +## Quick Start + +1. Sign up at `https://dash.readme.com/signup`. +2. Click **Create New Project**. Set a name, upload a logo (ReadMe picks brand colors from it), and choose the subdomain. +3. Add the API definition under **API Reference**: upload an OpenAPI file, import a URL, build one from scratch, or run `npx rdme openapi upload ` from a terminal. ReadMe validates the file and renders every endpoint. +4. Write the first guide under **Guides**. Use the AI Agent for a draft or the editor for a blank page. A "Getting Started" page is the usual first one. +5. Generate an API key at **Configuration β†’ API Keys**, URL `https://dash.readme.com/project/{subdomain}/v{version}/api-key`. +6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server under the same name, which replaces the plugin's one. The command differs per client: use the registration table in the `mcp-auth` skill, which also covers repairing a key that is already set. +7. Verify: `execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. + +After step 7, load the `readme-api` skill for anything else in the project. + +## Driving the browser yourself + +Steps 1 to 5 are all browser work. If you can drive a browser, offer to do them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. + +Find the row for the client you are running in. If you cannot tell which one that is, ask rather than guess. + +| Client | Drive the browser with | +| --- | --- | +| Claude Code | `mcp__claude-in-chrome__*`, when the Claude in Chrome extension is connected | +| ChatGPT desktop app or ChatGPT web | `@Browser`. It has its own profile, so the user signs in to ReadMe there, and it asks before submitting forms. It cannot upload files, so for step 3 import the API definition by URL or run `npx rdme openapi upload ` from a terminal | +| Codex CLI, Codex IDE extension, Cursor | No browser of their own. List the steps for the user | + +## When you cannot install anything yourself + +On a chat surface you have no shell and cannot add a marketplace, install a plugin or edit MCP config. Do not attempt it and do not ask the user to run commands there. If the ReadMe tools are missing, the user has to install the plugin by hand. Find their client below and give them those steps exactly. + +| Client | Steps | +| --- | --- | +| Claude Desktop, Cowork, claude.ai | Click **Customize** in the left sidebar, then **Plugins** β€” in Cowork, open the **Cowork** tab first. Under **Personal plugins**, click **+** β†’ **Add marketplace** and enter `readmeio/agent-plugins`. Find **readme** in the list, click **Install**, then start a new chat so the tools load. Plugins need a paid Claude plan; on Team and Enterprise an owner may have disabled personal marketplaces, in which case they add it under **Organization settings β†’ Plugins** | +| ChatGPT desktop app | Open the **Plugins** tab and click **Add marketplace**. Enter `readmeio/agent-plugins` as the source, leave the Git ref as `main` and the sparse paths empty, then click **Add marketplace**. Install **readme** from the new marketplace and start a new chat so the tools load | +| ChatGPT web | There is no marketplace option, only the plugin directory. Until the ReadMe plugin is listed there, the user can still add the MCP server on its own: turn on **Developer mode** under **Settings β†’ Security and login**, open **Plugins**, click **+** next to the search box, and in the **New Plugin** form set the name to `readme`, the server URL to `https://docs.readme.com/mcp`, and authentication to **No Auth**. That gives the tools but not the skills, so keep this skill's content in the conversation yourself | +| Cursor | Open **Cursor Settings β†’ Plugins**, search for **ReadMe**, click **Install** and choose project or user scope. Or run `/add-plugin readme` in chat | + +On the chat surfaces above the ReadMe connector stays read-only once installed: `search`, `fetch` and the endpoint tools work on public projects, but there is no way to supply an API key, so steps 6 and 7 of the Quick Start do not apply and write tools such as `update-docs` fail. Say so before the user tries. For creating or updating pages, offer to continue in a CLI or editor with the server registered as in step 6. + +## Reading the docs meanwhile + +Use `search` for a question, then `fetch` with the returned id. Useful pages: + +| Id | Page | +| --- | --- | +| `main/quickstart` | Three-step setup | +| `main/creating-a-project` | Project settings on creation | +| `main/openapi-upload-and-management` | Upload, sync, and re-sync an OpenAPI file | +| `main/branches` | How branches and versions work | +| `ref:main/intro-to-the-readme-api` | API v2 overview and auth | +| `main/sdks` | Metrics SDKs for API logs | From db8fd22ce05f77d2dff5152a6d22e140445ac679 Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Wed, 16 Sep 2026 14:30:23 +1000 Subject: [PATCH 21/22] refactor(skills): drop the route-map skills, keep what the server cannot say readme-api and developer-metrics-api were hand-copied route tables. The server returns the same map from list-endpoints for 2.6KB against the 8.8KB skill, and get-endpoint already carries the Refactored-only notices, the category.uri pattern and prefer: handling=strict. Duplicating a spec that moves is how the skills go stale. The facts no endpoint listing can produce move into mcp-server: the paging response shape, child projects needing their own key, Enterprise gating on metrics reads, basic auth on the metrics spec, the SDK packages, and which dashboard metrics have no route at all. Fixes the metrics auth in the spec table, which said bearer where the definition says basic. --- README.md | 5 ++-- claude/README.md | 4 +-- claude/skills/mcp-server/SKILL.md | 43 ++++++++++++++++++++++++++++--- claude/skills/onboarding/SKILL.md | 2 ++ codex/README.md | 4 +-- codex/skills/mcp-server/SKILL.md | 43 ++++++++++++++++++++++++++++--- codex/skills/onboarding/SKILL.md | 2 +- cursor/README.md | 4 +-- cursor/skills/mcp-server/SKILL.md | 43 ++++++++++++++++++++++++++++--- cursor/skills/onboarding/SKILL.md | 2 +- skills/mcp-server/SKILL.md | 43 ++++++++++++++++++++++++++++--- skills/onboarding/SKILL.md | 2 +- 12 files changed, 167 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 5cf550c..4c17b3e 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,10 @@ agent-plugins/ ## Skills -The five skills are agent-agnostic: anything a client does differently β€” registering an API key, +The three skills are agent-agnostic: anything a client does differently β€” registering an API key, driving a browser, installing the plugin by hand β€” is a per-client table inside the shared file, so -there is one copy of every fact. +there is one copy of every fact. They carry only what the MCP server cannot tell an agent at +runtime; route maps come from `list-endpoints` and `get-endpoint`, not from a skill. Edit `skills/` and nothing else, then regenerate the three published copies: diff --git a/claude/README.md b/claude/README.md index b7f0ba0..3e04c18 100644 --- a/claude/README.md +++ b/claude/README.md @@ -67,8 +67,6 @@ Claude Desktop Chat, Cowork and claude.ai cannot take an API key, so the plugin | Skill | What it does | | ----- | ------------ | -| `mcp-server` | Keeps the agent straight on which project a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | +| `mcp-server` | Keeps the agent straight on which project and which spec a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | | `mcp-auth` | Establishes which key is in play and diagnoses the failures a missing or unresolved one produces | -| `readme-api` | The full ReadMe API v2 route map, so the agent can go straight to the right call | -| `developer-metrics-api` | Page views, search terms and page quality reads, plus sending your API's request logs to ReadMe | | `onboarding` | Walks a new customer from signup to a published hub and a working API key | diff --git a/claude/skills/mcp-server/SKILL.md b/claude/skills/mcp-server/SKILL.md index f39ced1..fcbaf37 100644 --- a/claude/skills/mcp-server/SKILL.md +++ b/claude/skills/mcp-server/SKILL.md @@ -1,6 +1,6 @@ --- name: mcp-server -description: Route ReadMe MCP calls to the right project. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides" - and before calling execute-request for the first time in a session. +description: Route ReadMe MCP calls to the right project and the right spec. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides", "how many page views", "top search terms", "send our API logs to ReadMe" - and before calling execute-request for the first time in a session. --- # Which project does this call land in? @@ -31,7 +31,7 @@ assuming a tool named here is present, and never assume one that is not. | Spec title | Server | Auth | | --- | --- | --- | | `ReadMe API` | `https://api.readme.com/v2` | Bearer `rdme_...` | -| `Developer Metrics API` | `https://metrics.readme.io` | Bearer `rdme_...` | +| `Developer Metrics API` | `https://metrics.readme.io` | HTTP basic, the key as username and an empty password | | `Legacy API` | `https://dash.readme.com/api/v1` | HTTP basic | **Use `ReadMe API` for all work on the user's content.** `Legacy API` is v1: it takes basic auth @@ -39,6 +39,19 @@ rather than a bearer token, and it is unavailable to projects on ReadMe Refactor will surface its routes alongside the others β€” ignore them. Never fall back to v1 when a v2 call fails. +## Finding a route + +Do not guess paths or work from memory. `list-endpoints` returns every path and summary in a spec in +one cheap call; `get-endpoint` adds the full request and response schema for one of them, including +which routes exist only on ReadMe Refactored. Read them rather than reproducing them here. + +Two things the definitions do not tell you: + +- Paginated responses carry `paging.next`, `paging.previous`, `paging.first` and `paging.last`. + Query with `page` and `per_page`, max 100 and max 50 on search. +- Enterprise child projects need the child's own key. Only the API-key routes take a `{subdomain}`, + and `me` works there. + ## Calling execute-request ```json @@ -75,8 +88,30 @@ than sending them away to configure anything: | Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | | List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | -`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full -route map, so load that before reaching for `search-endpoints`. +`{branch}` is a version number, `stable`, or a branch name. Everything is branch-scoped except +changelogs, images, fonts, API keys, search and the project itself. + +## Metrics + +Page views, search terms and page quality live in the `Developer Metrics API` spec, and reading them +needs the Enterprise plan β€” without it the API answers with an auth or plan error rather than saying +so. The registration sends a bearer token; if a call returns `Unauthorized` with a key set, send +`Authorization: Basic :">` on the HAR request instead. + +Most of what the dashboard shows has no route at all, so check here before going looking: + +| Metric | Readable via API | +| --- | --- | +| Page views, page quality, search terms | Yes | +| API calls | No β€” ingest only, `POST https://metrics.readme.io/request` | +| MCP tool calls, API errors, top endpoints, new users | No, dashboard only | + +For anything in the No rows, send the user to +`https://dash.readme.com/project/{subdomain}/v{version}/metrics`. + +Ingesting the user's own API logs is a server-side integration, not something to hand-build here. +Point them at the SDK for their stack β€” `readmeio` (Node), `readme-metrics` (Python, Ruby), +`readme/metrics` (PHP), `ReadMe.Metrics` (.NET) β€” and at `fetch` with id `main/sdks`. ## A different server, when they actually want one diff --git a/claude/skills/onboarding/SKILL.md b/claude/skills/onboarding/SKILL.md index bb972ff..3b500eb 100644 --- a/claude/skills/onboarding/SKILL.md +++ b/claude/skills/onboarding/SKILL.md @@ -39,6 +39,8 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D 6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server under the same name, which replaces the plugin's one. The command differs per client: use the registration table in the `mcp-auth` skill, which also covers repairing a key that is already set. 7. Verify: `execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. +After step 7, the `mcp-server` skill covers which spec and which project everything else lands in. + ## Driving the browser yourself Steps 1 to 5 are all browser work. If you can drive a browser, offer to do them in the user's own browser instead of only listing the steps: open the signup page, create the project, upload the API definition, and open the API Keys page. Let the user type credentials and payment details themselves. Steps 6 and 7 stay in the terminal. diff --git a/codex/README.md b/codex/README.md index c559896..7746a25 100644 --- a/codex/README.md +++ b/codex/README.md @@ -30,8 +30,6 @@ Your `readme` entry replaces the plugin's anonymous one. The skills keep working | Skill | What it does | | ----- | ------------ | -| `mcp-server` | Keeps the agent straight on which project a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | +| `mcp-server` | Keeps the agent straight on which project and which spec a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | | `mcp-auth` | Establishes which key is in play and diagnoses the failures a missing or unresolved one produces | -| `readme-api` | The full ReadMe API v2 route map, so the agent can go straight to the right call | -| `developer-metrics-api` | Page views, search terms and page quality reads, plus sending your API's request logs to ReadMe | | `onboarding` | Walks a new customer from signup to a published hub and a working API key | diff --git a/codex/skills/mcp-server/SKILL.md b/codex/skills/mcp-server/SKILL.md index f39ced1..fcbaf37 100644 --- a/codex/skills/mcp-server/SKILL.md +++ b/codex/skills/mcp-server/SKILL.md @@ -1,6 +1,6 @@ --- name: mcp-server -description: Route ReadMe MCP calls to the right project. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides" - and before calling execute-request for the first time in a session. +description: Route ReadMe MCP calls to the right project and the right spec. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides", "how many page views", "top search terms", "send our API logs to ReadMe" - and before calling execute-request for the first time in a session. --- # Which project does this call land in? @@ -31,7 +31,7 @@ assuming a tool named here is present, and never assume one that is not. | Spec title | Server | Auth | | --- | --- | --- | | `ReadMe API` | `https://api.readme.com/v2` | Bearer `rdme_...` | -| `Developer Metrics API` | `https://metrics.readme.io` | Bearer `rdme_...` | +| `Developer Metrics API` | `https://metrics.readme.io` | HTTP basic, the key as username and an empty password | | `Legacy API` | `https://dash.readme.com/api/v1` | HTTP basic | **Use `ReadMe API` for all work on the user's content.** `Legacy API` is v1: it takes basic auth @@ -39,6 +39,19 @@ rather than a bearer token, and it is unavailable to projects on ReadMe Refactor will surface its routes alongside the others β€” ignore them. Never fall back to v1 when a v2 call fails. +## Finding a route + +Do not guess paths or work from memory. `list-endpoints` returns every path and summary in a spec in +one cheap call; `get-endpoint` adds the full request and response schema for one of them, including +which routes exist only on ReadMe Refactored. Read them rather than reproducing them here. + +Two things the definitions do not tell you: + +- Paginated responses carry `paging.next`, `paging.previous`, `paging.first` and `paging.last`. + Query with `page` and `per_page`, max 100 and max 50 on search. +- Enterprise child projects need the child's own key. Only the API-key routes take a `{subdomain}`, + and `me` works there. + ## Calling execute-request ```json @@ -75,8 +88,30 @@ than sending them away to configure anything: | Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | | List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | -`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full -route map, so load that before reaching for `search-endpoints`. +`{branch}` is a version number, `stable`, or a branch name. Everything is branch-scoped except +changelogs, images, fonts, API keys, search and the project itself. + +## Metrics + +Page views, search terms and page quality live in the `Developer Metrics API` spec, and reading them +needs the Enterprise plan β€” without it the API answers with an auth or plan error rather than saying +so. The registration sends a bearer token; if a call returns `Unauthorized` with a key set, send +`Authorization: Basic :">` on the HAR request instead. + +Most of what the dashboard shows has no route at all, so check here before going looking: + +| Metric | Readable via API | +| --- | --- | +| Page views, page quality, search terms | Yes | +| API calls | No β€” ingest only, `POST https://metrics.readme.io/request` | +| MCP tool calls, API errors, top endpoints, new users | No, dashboard only | + +For anything in the No rows, send the user to +`https://dash.readme.com/project/{subdomain}/v{version}/metrics`. + +Ingesting the user's own API logs is a server-side integration, not something to hand-build here. +Point them at the SDK for their stack β€” `readmeio` (Node), `readme-metrics` (Python, Ruby), +`readme/metrics` (PHP), `ReadMe.Metrics` (.NET) β€” and at `fetch` with id `main/sdks`. ## A different server, when they actually want one diff --git a/codex/skills/onboarding/SKILL.md b/codex/skills/onboarding/SKILL.md index b2d274c..3b500eb 100644 --- a/codex/skills/onboarding/SKILL.md +++ b/codex/skills/onboarding/SKILL.md @@ -39,7 +39,7 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D 6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server under the same name, which replaces the plugin's one. The command differs per client: use the registration table in the `mcp-auth` skill, which also covers repairing a key that is already set. 7. Verify: `execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. -After step 7, load the `readme-api` skill for anything else in the project. +After step 7, the `mcp-server` skill covers which spec and which project everything else lands in. ## Driving the browser yourself diff --git a/cursor/README.md b/cursor/README.md index 7c76b60..ff04304 100644 --- a/cursor/README.md +++ b/cursor/README.md @@ -93,10 +93,8 @@ and the agent carries it out through `execute-request`. | Skill | What it does | | ----- | ------------ | -| `mcp-server` | Keeps the agent straight on which project a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | +| `mcp-server` | Keeps the agent straight on which project and which spec a call lands in: this server reads ReadMe's own docs, while `execute-request` plus your key acts on yours | | `mcp-auth` | Establishes which key is in play and diagnoses the failures a missing or unresolved one produces | -| `readme-api` | The full ReadMe API v2 route map, so the agent can go straight to the right call | -| `developer-metrics-api` | Page views, search terms and page quality reads, plus sending your API's request logs to ReadMe | | `onboarding` | Walks a new customer from signup to a published hub and a working API key | ## Which ReadMe MCP server is this? diff --git a/cursor/skills/mcp-server/SKILL.md b/cursor/skills/mcp-server/SKILL.md index f39ced1..fcbaf37 100644 --- a/cursor/skills/mcp-server/SKILL.md +++ b/cursor/skills/mcp-server/SKILL.md @@ -1,6 +1,6 @@ --- name: mcp-server -description: Route ReadMe MCP calls to the right project. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides" - and before calling execute-request for the first time in a session. +description: Route ReadMe MCP calls to the right project and the right spec. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides", "how many page views", "top search terms", "send our API logs to ReadMe" - and before calling execute-request for the first time in a session. --- # Which project does this call land in? @@ -31,7 +31,7 @@ assuming a tool named here is present, and never assume one that is not. | Spec title | Server | Auth | | --- | --- | --- | | `ReadMe API` | `https://api.readme.com/v2` | Bearer `rdme_...` | -| `Developer Metrics API` | `https://metrics.readme.io` | Bearer `rdme_...` | +| `Developer Metrics API` | `https://metrics.readme.io` | HTTP basic, the key as username and an empty password | | `Legacy API` | `https://dash.readme.com/api/v1` | HTTP basic | **Use `ReadMe API` for all work on the user's content.** `Legacy API` is v1: it takes basic auth @@ -39,6 +39,19 @@ rather than a bearer token, and it is unavailable to projects on ReadMe Refactor will surface its routes alongside the others β€” ignore them. Never fall back to v1 when a v2 call fails. +## Finding a route + +Do not guess paths or work from memory. `list-endpoints` returns every path and summary in a spec in +one cheap call; `get-endpoint` adds the full request and response schema for one of them, including +which routes exist only on ReadMe Refactored. Read them rather than reproducing them here. + +Two things the definitions do not tell you: + +- Paginated responses carry `paging.next`, `paging.previous`, `paging.first` and `paging.last`. + Query with `page` and `per_page`, max 100 and max 50 on search. +- Enterprise child projects need the child's own key. Only the API-key routes take a `{subdomain}`, + and `me` works there. + ## Calling execute-request ```json @@ -75,8 +88,30 @@ than sending them away to configure anything: | Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | | List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | -`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full -route map, so load that before reaching for `search-endpoints`. +`{branch}` is a version number, `stable`, or a branch name. Everything is branch-scoped except +changelogs, images, fonts, API keys, search and the project itself. + +## Metrics + +Page views, search terms and page quality live in the `Developer Metrics API` spec, and reading them +needs the Enterprise plan β€” without it the API answers with an auth or plan error rather than saying +so. The registration sends a bearer token; if a call returns `Unauthorized` with a key set, send +`Authorization: Basic :">` on the HAR request instead. + +Most of what the dashboard shows has no route at all, so check here before going looking: + +| Metric | Readable via API | +| --- | --- | +| Page views, page quality, search terms | Yes | +| API calls | No β€” ingest only, `POST https://metrics.readme.io/request` | +| MCP tool calls, API errors, top endpoints, new users | No, dashboard only | + +For anything in the No rows, send the user to +`https://dash.readme.com/project/{subdomain}/v{version}/metrics`. + +Ingesting the user's own API logs is a server-side integration, not something to hand-build here. +Point them at the SDK for their stack β€” `readmeio` (Node), `readme-metrics` (Python, Ruby), +`readme/metrics` (PHP), `ReadMe.Metrics` (.NET) β€” and at `fetch` with id `main/sdks`. ## A different server, when they actually want one diff --git a/cursor/skills/onboarding/SKILL.md b/cursor/skills/onboarding/SKILL.md index b2d274c..3b500eb 100644 --- a/cursor/skills/onboarding/SKILL.md +++ b/cursor/skills/onboarding/SKILL.md @@ -39,7 +39,7 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D 6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server under the same name, which replaces the plugin's one. The command differs per client: use the registration table in the `mcp-auth` skill, which also covers repairing a key that is already set. 7. Verify: `execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. -After step 7, load the `readme-api` skill for anything else in the project. +After step 7, the `mcp-server` skill covers which spec and which project everything else lands in. ## Driving the browser yourself diff --git a/skills/mcp-server/SKILL.md b/skills/mcp-server/SKILL.md index f39ced1..fcbaf37 100644 --- a/skills/mcp-server/SKILL.md +++ b/skills/mcp-server/SKILL.md @@ -1,6 +1,6 @@ --- name: mcp-server -description: Route ReadMe MCP calls to the right project. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides" - and before calling execute-request for the first time in a session. +description: Route ReadMe MCP calls to the right project and the right spec. Use before any request touching the user's own content - "our docs", "my hub", "create a page", "update the changelog", "what endpoints do we have", "search our guides", "how many page views", "top search terms", "send our API logs to ReadMe" - and before calling execute-request for the first time in a session. --- # Which project does this call land in? @@ -31,7 +31,7 @@ assuming a tool named here is present, and never assume one that is not. | Spec title | Server | Auth | | --- | --- | --- | | `ReadMe API` | `https://api.readme.com/v2` | Bearer `rdme_...` | -| `Developer Metrics API` | `https://metrics.readme.io` | Bearer `rdme_...` | +| `Developer Metrics API` | `https://metrics.readme.io` | HTTP basic, the key as username and an empty password | | `Legacy API` | `https://dash.readme.com/api/v1` | HTTP basic | **Use `ReadMe API` for all work on the user's content.** `Legacy API` is v1: it takes basic auth @@ -39,6 +39,19 @@ rather than a bearer token, and it is unavailable to projects on ReadMe Refactor will surface its routes alongside the others β€” ignore them. Never fall back to v1 when a v2 call fails. +## Finding a route + +Do not guess paths or work from memory. `list-endpoints` returns every path and summary in a spec in +one cheap call; `get-endpoint` adds the full request and response schema for one of them, including +which routes exist only on ReadMe Refactored. Read them rather than reproducing them here. + +Two things the definitions do not tell you: + +- Paginated responses carry `paging.next`, `paging.previous`, `paging.first` and `paging.last`. + Query with `page` and `per_page`, max 100 and max 50 on search. +- Enterprise child projects need the child's own key. Only the API-key routes take a `{subdomain}`, + and `me` works there. + ## Calling execute-request ```json @@ -75,8 +88,30 @@ than sending them away to configure anything: | Read one guide | `GET https://api.readme.com/v2/branches/{branch}/guides/{slug}` | | List what is in a category | `GET https://api.readme.com/v2/branches/{branch}/categories/{section}/{title}/pages` | -`{branch}` is a version number, `stable`, or a branch name. The `readme-api` skill carries the full -route map, so load that before reaching for `search-endpoints`. +`{branch}` is a version number, `stable`, or a branch name. Everything is branch-scoped except +changelogs, images, fonts, API keys, search and the project itself. + +## Metrics + +Page views, search terms and page quality live in the `Developer Metrics API` spec, and reading them +needs the Enterprise plan β€” without it the API answers with an auth or plan error rather than saying +so. The registration sends a bearer token; if a call returns `Unauthorized` with a key set, send +`Authorization: Basic :">` on the HAR request instead. + +Most of what the dashboard shows has no route at all, so check here before going looking: + +| Metric | Readable via API | +| --- | --- | +| Page views, page quality, search terms | Yes | +| API calls | No β€” ingest only, `POST https://metrics.readme.io/request` | +| MCP tool calls, API errors, top endpoints, new users | No, dashboard only | + +For anything in the No rows, send the user to +`https://dash.readme.com/project/{subdomain}/v{version}/metrics`. + +Ingesting the user's own API logs is a server-side integration, not something to hand-build here. +Point them at the SDK for their stack β€” `readmeio` (Node), `readme-metrics` (Python, Ruby), +`readme/metrics` (PHP), `ReadMe.Metrics` (.NET) β€” and at `fetch` with id `main/sdks`. ## A different server, when they actually want one diff --git a/skills/onboarding/SKILL.md b/skills/onboarding/SKILL.md index b2d274c..3b500eb 100644 --- a/skills/onboarding/SKILL.md +++ b/skills/onboarding/SKILL.md @@ -39,7 +39,7 @@ Plans: Starter (free), Pro, Enterprise. Enterprise supports child projects and D 6. Attach the key. The plugin's own `readme` server is anonymous and cannot read the key. The user registers a server under the same name, which replaces the plugin's one. The command differs per client: use the registration table in the `mcp-auth` skill, which also covers repairing a key that is already set. 7. Verify: `execute-request` with spec title `ReadMe API`, `GET https://api.readme.com/v2/projects/me`. A 200 with the project name means the plugin is wired to the right project. `Missing Security Schemes` means the registration is sending no key; a 401 titled `The API key couldn't be located.` means the key is wrong; a 500 titled `An unknown error has occurred.` means it resolved to an empty string. In every case, go back to step 5. -After step 7, load the `readme-api` skill for anything else in the project. +After step 7, the `mcp-server` skill covers which spec and which project everything else lands in. ## Driving the browser yourself From 0e1d9cc780eab3ffa065ee0c9c32b111cd4fbf3d Mon Sep 17 00:00:00 2001 From: minhthanhdang <150941282+minhthanhdang@users.noreply.github.com> Date: Thu, 17 Sep 2026 13:27:46 +1000 Subject: [PATCH 22/22] ci: only run the push job on main A PR push was triggering the suite twice, once for push and once for pull_request. --- .github/workflows/validate.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 16edf4f..88ad04c 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -2,6 +2,7 @@ name: Validate on: push: + branches: [main] pull_request: permissions: