Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes are listed here. The format follows [Keep a Changelog](https

## [Unreleased]

### Changed
- MCP distribution facts (2026-11-02): Official MCP Registry `_meta` 4 KB limit and npm version timing, Glama listing claim, awesome-mcp-servers requirements, Claude plugin directory rules.
- MCP distribution facts (2026-11-03): Glama build config and stale listings, awesome-mcp-servers bot and entry rules, Claude plugin preparation.
- Retired platforms (2026-11-05): one table in `references/mcp-registry-checklist.md`; guidance for retired platforms removed.
- Claude plugin directory (2026-11-05): a "Decide first" check for plugins that return third-party personal data, keep plugin files when not submitting, and two more documented holds (brand name, `docker run`).

### Added
- `scripts/check_repo_seo.py` flags files and README lines that name a retired platform.
- `scripts/check_listings.py`: read-only check of the Official MCP Registry entry, its npm or Docker Hub package, Glama and awesome-mcp-servers.

## [0.2.0] - 2026-11-02

### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
GitHub SEO Skill is an Agent Skill for Claude Code that gets open-source GitHub repos found on
Google and GitHub search. It audits a repo's name, description, topics and README, writes a
search-ready README, runs a pre-publish secret and client-data check, and walks MCP servers
through registry submissions such as the Official MCP Registry, Smithery, Glama and mcp.so.
through registry submissions such as the Official MCP Registry, Glama and mcp.so.

It works with any tool that supports the [Agent Skills](https://agentskills.io) format.

Expand Down
16 changes: 9 additions & 7 deletions skills/github-seo/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: github-seo
description: Makes an open-source GitHub repo discoverable and safe to publish. Audits the repo name, description, topics and README for search, writes a search-ready README, runs a pre-publish secret and client-data check, and guides the launch sequence. Covers MCP server registry submissions (Official MCP Registry, Smithery, Glama, mcp.so). Use when the user wants more stars, traffic or search visibility for a repo, is about to open-source a project, asks for GitHub SEO or repo SEO, or wants to publish an MCP server. Not for general website SEO.
description: Makes an open-source GitHub repo discoverable and safe to publish. Audits the repo name, description, topics and README for search, writes a search-ready README, runs a pre-publish secret and client-data check, and guides the launch sequence. Covers MCP server registry submissions (Official MCP Registry, Glama, mcp.so) and the Claude plugin directory. Use when the user wants more stars, traffic or search visibility for a repo, is about to open-source a project, asks for GitHub SEO or repo SEO, or wants to publish an MCP server. Not for general website SEO.
license: MIT
---

Expand Down Expand Up @@ -51,7 +51,7 @@ python3 scripts/check_repo_seo.py owner/repo
```

It reports pass, warn or fail for the description, topics, homepage, license, README shape,
and community files, and prints the one lever it cannot check (the social preview image).
community files and retired-platform leftovers, and prints the one lever it cannot check (the social preview image).
Fix failures first, then warnings.

## Step A: plain repo checklist
Expand All @@ -78,19 +78,21 @@ Fix failures first, then warnings.
produces the artifact the next needs.
9. **Upstream galleries and awesome-lists** only once the repo is complete and has real stars.
Maintainers reject cold, thin submissions.
10. **Claude plugin directory.** If the repo ships a Claude plugin, follow
`references/claude-plugin-directory.md` for the submission portal, Validate findings and
the other plugin distribution routes.
10. **Claude plugin directory.** If the repo ships or could ship a Claude plugin, start with
"Decide first" in `references/claude-plugin-directory.md`. It says whether to submit, then
covers the submission portal, Validate findings and the other plugin distribution routes.

## Step B: MCP server checklist (after Step A)

Start with `references/mcp-install-and-metadata.md`: choose the package type (npm, PyPI, OCI and
others each have their own ownership check), complete `server.json` including `websiteUrl`, and
lay out the README install routes per client. Then use `references/mcp-registry-checklist.md`. It covers the Official MCP Registry (`server.json`
plus the `mcp-publisher` CLI), Smithery, Glama, mcp.so, mcpservers.org, Cursor Directory, which
plus the `mcp-publisher` CLI), Glama, mcp.so, mcpservers.org, Cursor Directory, which
registries auto-ingest from the Official one, and common gotchas (stale listings under a personal
account, publish order, domain presence). Pitfalls from real runs (org namespace 403, OCI
account, the Glama build config, publish order, domain presence). Pitfalls from real runs (org namespace 403, OCI
build and label, leaked-history scrub) are in the install reference.
Submit only to the registries in that checklist, never to one in its "Retired platforms" table.
After you submit, confirm each listing with `python3 scripts/check_listings.py owner/repo`.

## What not to do

Expand Down
2 changes: 1 addition & 1 deletion skills/github-seo/evals/evals.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{ "type": "should_trigger", "prompt": "what topics and description should I put on this repo so people find it" },
{ "type": "should_trigger", "prompt": "plan the launch for our new open source tool, reddit, hn, the lot" },
{ "type": "should_trigger", "prompt": "is it safe to make this private repo public" },
{ "type": "should_trigger", "prompt": "submit my mcp server to smithery and glama" },
{ "type": "should_trigger", "prompt": "submit my mcp server to glama and mcp.so" },
{ "type": "should_trigger", "prompt": "audit the discoverability of github.com/acme/widget-cli" },
{ "type": "should_not_trigger", "prompt": "improve the SEO of my marketing website" },
{ "type": "should_not_trigger", "prompt": "write a blog post about our product" },
Expand Down
81 changes: 77 additions & 4 deletions skills/github-seo/references/claude-plugin-directory.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,50 @@ Generalised from one real submission at `claude.ai/directory/manage` on 2026-11-
[observed, 2026-11-02]. The portal and its checks change, so re-check each step before
repeating this. Anything not seen during the run is marked [unverified].

## Decide first

Answer two questions before any plugin work [verified, 2026-11-05, Anthropic Software Directory
Policy 1D and 3A]:

1. Does the plugin collect user data or connect to a remote service? Then it needs "a clear,
accessible privacy policy link". Without one, do not submit yet.
2. Does it collect or return personal data about people other than the user, such as emails or
profiles? Then tell the owner it may be refused even with a privacy policy, because software
must protect "the privacy interests of third parties".

Submit or skip is the owner's call.

If the answer is skip, change no files: the directory reads only what you submit. The plugin files
(`.claude-plugin/`, `.mcp.json`, plugin skills) still serve everyone who installs from the repo,
through its own `marketplace.json` or `/plugin marketplace add owner/repo`. Keep them unless the
owner wants the plugin gone everywhere. To find other marketplaces that list the repo:

```bash
gh search code "owner/repo" --filename marketplace.json
```

The search finds only marketplaces in repos you can read, so zero results do not prove that
nothing depends on the files.

## Prerequisites

- A paid claude.ai plan [observed, 2026-11-02].
- A public GitHub repo with `.claude-plugin/plugin.json` [observed, 2026-11-02].
- A GitHub account with push access to the repo, used by the submitter [observed, 2026-11-02].
- A paid claude.ai plan [observed, 2026-11-02]. On Team and Enterprise, the submitter needs the
Owner role or, on Enterprise, a custom role with the Directory permission [verified, 2026-11-02,
claude.com/docs/directory/publish.md].
- A GitHub repo with `.claude-plugin/plugin.json` [observed, 2026-11-02]. The repo can stay
private while you validate and submit, but must be public before the listing goes live
[verified, 2026-11-02, claude.com/docs/plugins/submit.md].
- A GitHub account with push access to the repo, used by the submitter [observed, 2026-11-02],
and connected on claude.ai in the submitting organisation [verified, 2026-11-02, same page].
- The listing belongs to the organisation you submit from. Submit from the organisation that
should own it long term [verified, 2026-11-02, claude.com/docs/directory/publish.md].
- Limits: at most 10 submissions per organisation per 24 hours (drafts and withdrawn
submissions count), and one submission per repo and folder [observed, 2026-11-02].

## The five steps

1. **Source.** Point the portal at the repo and folder.
1. **Source.** In the portal, select Submit new, then Plugin bundle [verified, 2026-11-02,
claude.com/docs/plugins/submit.md]. Point the portal at the repo and folder.
2. **Listing details.** Name, description, icon and related listing fields.
3. **Data handling.** Questions on personal data, whether the plugin sends data to other
services (declare this in the README), retention, and users under 18 [observed, 2026-11-02].
Expand All @@ -24,6 +57,24 @@ repeating this. Anything not seen during the run is marked [unverified].
5. **Review and submit.** An automated scan runs first. Held items go to a human reviewer.
Approval is not guaranteed, and no review-time estimate was shown [observed, 2026-11-02].

## Prepare the plugin

- The plugin folder is the folder that holds `.claude-plugin/plugin.json`, and installers get that
whole folder [verified, 2026-11-03, claude.com/docs/plugins/pre-submission-checklist.md]. If it
is the root of a repo that also holds the server's `package.json` and `yarn.lock`, every install
shows a note that the listed packages were not installed, because plugin installs do not support
yarn or pnpm lockfiles [observed, 2026-11-03, `claude plugin list`]. A server that runs from
npm through `npx` never uses those packages, so the note does not affect it [general].
- Set `displayName`, and set `icon` to a path inside the plugin, such as `./assets/icon.png`. The
directory reads `icon`, `documentationUrl`, `supportUrl`, `privacyPolicyUrl` and
`termsOfServiceUrl` from `plugin.json` only [verified, 2026-11-03,
code.claude.com/docs/en/plugins-reference].
- Add a README "Network access and data" section: what the plugin downloads, which hosts it calls,
what each request carries and what it stores. The checklist asks the README to describe
everything the plugin runs, sends or fetches [verified, 2026-11-03, pre-submission checklist].
- Run `claude plugin validate .` in the plugin folder before you push. It checks syntax and schema
only, so the portal's Validate still runs [verified, 2026-11-03, pre-submission checklist].

## Validate

Validate runs 7 checks and reports three kinds of result: Blocking findings, policy holds and
Expand All @@ -39,6 +90,23 @@ touches a fix [observed, 2026-11-02].

All rows [observed, 2026-11-02].

### Documented rules for packages and files

From claude.com/docs/plugins/pre-submission-checklist.md [verified, 2026-11-02; the brand and
`docker run` rows 2026-11-05]. The launcher rule lists `npx`, `bunx`, `pnpm dlx`, `yarn dlx`,
`uvx`, `pipx run` and `uv run` only.

| Rule | Result if broken |
|---|---|
| Pin every package a launcher runs to an exact version, such as `npx <pkg>@1.2.3` | Blocks, "Unpinned npx launcher" |
| A launcher with an exact pin | Still held for a reviewer, "Runs a pinned npx or uvx package" |
| `.npmrc` or another file that sets a registry or package source, in a plugin with a launcher | Blocks |
| `package.json` beside `package-lock.json`, `npm-shrinkwrap.json`, `bun.lock` or `bun.lockb` in the plugin folder root | Held for a reviewer, "Dependencies install from a lockfile". `yarn.lock` is not on the list |
| `name`, `displayName` or `author.name` could be mistaken for a well-known brand that is not yours | Held for a reviewer, "Name matches a known brand" |
| A local MCP server starts with something other than a file in the plugin, such as `docker run` | Held for a reviewer, "MCP server command wasn't read" |
| Keep every file that is not an image or font under 256 KiB | Held for a reviewer |
| Keep the plugin to 512 files or fewer | Held for a reviewer |

### Scanner false positives (second submission, 2026-11-02)

Two more plugins went through Validate on 2026-11-02. The scanner reads text in skills and
Expand Down Expand Up @@ -73,3 +141,8 @@ The review step offers an auto-publish toggle. Two update modes were shown [obse
- `anthropics/claude-plugins-official` is by partner contact only [observed, 2026-11-02].
- Your own `marketplace.json` lets users run `/plugin marketplace add <owner>/<repo>` [general].
- A skills.sh listing is automatic, built from `npx skills add` telemetry [observed, 2026-11-02].
- `/plugin install <name> --marketplace <owner>/<repo>` adds the marketplace and installs in one
step. It needs Claude Code v2.1.275 or later [verified, 2026-11-02,
code.claude.com/docs/en/plugins/publish.md].
- The directory no longer accepts desktop extension (MCPB) listings. Ship a local MCP server
inside a plugin bundle instead [verified, 2026-11-02, claude.com/docs/directory/publish.md].
24 changes: 17 additions & 7 deletions skills/github-seo/references/mcp-install-and-metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ mismatch is the most common publish failure.
| Docker/OCI | `oci` | Image label `io.modelcontextprotocol.server.name` equals the `server.json` `name` |
| MCPB bundle | `mcpb` | URL contains "mcp", and `fileSha256` is set (clients check the hash) |

npm timing: the registry checks that the exact version exists on npm. Right after `npm publish`
it can reject the version with "NPM package '...' exists, but version 'X' was not found (status:
404). A newly published release can take a moment to appear..." [verified, 2026-11-02, registry
`internal/validators/registries/npm.go`]. Publish to the registry only after
`npm view <pkg>@<version>` returns the version. The version became visible about one minute
after publish [observed on a Devkind npm MCP server, 2026-11-02].

OCI details [verified]: supported hosts are Docker Hub, `ghcr.io`, Google Artifact Registry,
`*.azurecr.io` and `mcr.microsoft.com`. The `identifier` is `registry/namespace/repository:tag`
(a digest also works). Pin a version tag, not `latest`. Put the `LABEL` in the Dockerfile and
Expand Down Expand Up @@ -71,11 +78,18 @@ Schema `2025-12-11` [verified]:
| `repository` | `url` and `source` | Source link for inspection. |
| `icons` | Optional | PNG or JPEG for UI display. |
| `packages` | Array | One entry per install route (see section 1). |
| `_meta` | Vendor extension | Free-form. Put author, tool list and website here as a bonus, not instead of `websiteUrl`. |
| `_meta` | Vendor extension | Only `io.modelcontextprotocol.registry/publisher-provided` is kept, max 4096 bytes of JSON. Put author and website here as a bonus, not instead of `websiteUrl`. |

Observed gap: a live entry that put the website only under `_meta` and left `websiteUrl` empty
[observed, 2026-10-31]. Whether downstream directories display `_meta` is unknown, so fill both.

`_meta` limit [verified, 2026-11-02, registry `internal/validators/validators.go`
`validatePublisherExtensions` and `docs/reference/server-json/official-registry-requirements.md`]:
the registry drops every other `_meta` key, and fails the publish when the publisher-provided
object exceeds 4 KB, with "publisher-provided extension exceeds 4KB limit (N bytes)". A full
tool-name list can pass that limit. A 125-tool server failed at 4474 bytes [observed on a Devkind
npm MCP server, 2026-11-02]. Keep the tool list out of `_meta` for a large server.

Environment variables go in `packages[].environmentVariables` with `name`, `description`,
`isRequired` and `isSecret`. Names only, never values.

Expand Down Expand Up @@ -125,20 +139,16 @@ server needs them.
| File | Feeds | Notes |
|---|---|---|
| `server.json` | Official MCP Registry | Section 3. Commit it to the repo root. |
| `smithery.yaml` | Smithery | `name`, `description`, `vendor`, `homepage`, `license`, `startCommand` with a config schema [observed]. |
| `manifest.json` | MCPB bundle, desktop installs | Carries `author` with name and URL, `repository`, and `user_config` prompts for credentials [observed]. |
| README badges | Humans | "Built by <org>" badge linking to the homepage. |

`smithery.yaml` with a docker `commandFunction` was copied from another published server README and is
[unverified] against Smithery's current docs. Check them before reusing it.

Keep one source of truth for the description, tool list and homepage, and copy it into each file.
A version drift between `package.json`, `server.json` and `manifest.json` is easy to introduce
[observed: one repo had `1.1.0` in two files and `1.0.9` in the third].

## 6. Make the org visible in every listing

- Same organisation name and the same homepage URL in `server.json` (`websiteUrl`), `smithery.yaml`,
- Same organisation name and the same homepage URL in `server.json` (`websiteUrl`),
`manifest.json`, the README byline and the repo About box.
- Link to a page on a domain you own that is specific to the server or its category, not only the
home page.
Expand Down Expand Up @@ -190,4 +200,4 @@ directory that renders the README. Keep it specific to the server's audience, no
- One link to a specific page on a domain you own (a services, consulting or product page, not
only the home page) plus a contact address.
- Request each linked URL first and confirm it returns 200.
- Use the same organisation name and homepage as in `server.json`, `smithery.yaml` and the About box.
- Use the same organisation name and homepage as in `server.json` and the About box.
Loading
Loading