From 3acf3a226368934894283e990eeab54abc684447 Mon Sep 17 00:00:00 2001 From: Mohammod Al Amin Ashik Date: Thu, 23 Apr 2026 08:13:18 +0800 Subject: [PATCH] docs: expand contributor docs and restructure issue templates - Add AGENTS.md following the agents.md spec for coding-agent guidance - Expand CONTRIBUTING.md from a brief overview into a detailed reference: full field tables (required/recommended/optional), transport + input + auth guidance, review criteria, trademark policy, security expectations, and troubleshooting for common validation errors - Rewrite PULL_REQUEST_TEMPLATE.md as a structured Add-Server template covering CI-enforced checks, reviewer quality bar, platform-managed fields, and trademark acknowledgements - Add request-server.yml so the community can ask for servers they don't have a definition for (label: server-request, title: "[Request] ") - Add bug-report.yml for flagging broken or incorrect existing definitions (label: bug, title: "[Bug] ") - Add config.yml to disable blank issues and lead the "New issue" chooser with the CONTRIBUTING (PR) path - Remove submit-server.yml; issue forms cannot open PRs, which made the template a slower and confusing path. Adding a server is now PR-only via the CONTRIBUTING quickstart. request-server.yml and bug-report.yml are deep-linked from the McpMux desktop app, so their filenames must stay stable. Signed-off-by: Mohammod Al Amin Ashik --- .github/ISSUE_TEMPLATE/bug-report.yml | 56 ++ .github/ISSUE_TEMPLATE/config.yml | 11 + .github/ISSUE_TEMPLATE/request-server.yml | 75 +++ .github/ISSUE_TEMPLATE/submit-server.yml | 60 -- .github/PULL_REQUEST_TEMPLATE.md | 103 +++- AGENTS.md | 128 ++++ CONTRIBUTING.md | 692 +++++++++++++++++++--- 7 files changed, 974 insertions(+), 151 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/request-server.yml delete mode 100644 .github/ISSUE_TEMPLATE/submit-server.yml create mode 100644 AGENTS.md diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..928c979 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,56 @@ +name: Bug in a Server Definition +description: Report a problem with an existing server definition in the registry +title: "[Bug] " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Use this to report a broken or incorrect server definition already in the registry. + + Bugs in the McpMux desktop app itself belong in the [mcp-mux repo](https://github.com/mcpmux/mcp-mux/issues/new/choose). + + - type: input + id: server_id + attributes: + label: Server ID + description: The `id` field from the JSON definition (e.g., `community.brave-search`). + placeholder: community.example-server + validations: + required: true + + - type: textarea + id: description + attributes: + label: What's wrong? + description: Broken command, missing field, wrong URL, bad `obtain` instructions, etc. + validations: + required: true + + - type: textarea + id: reproduce + attributes: + label: Steps to reproduce + description: How can a maintainer confirm the problem? + placeholder: | + 1. Install server `community.example-server` in McpMux + 2. Attempt to call tool `...` + 3. Observe error `...` + validations: + required: false + + - type: input + id: mcpmux_version + attributes: + label: McpMux Version (if applicable) + placeholder: e.g., 0.3.0 + validations: + required: false + + - type: textarea + id: logs + attributes: + label: Logs / Screenshots + description: Paste any relevant log output, error messages, or screenshots. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..b917210 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Contributing Guide (Pull Request path) + url: https://github.com/mcpmux/mcp-servers/blob/main/CONTRIBUTING.md + about: The fastest way to add a server — five-command quickstart for opening a PR + - name: Questions & Help + url: https://github.com/mcpmux/mcp-mux/discussions/categories/q-a + about: Ask questions about the registry or McpMux in GitHub Discussions + - name: Browse Existing Servers + url: https://mcpmux.com + about: Search the registry at mcpmux.com before opening a request diff --git a/.github/ISSUE_TEMPLATE/request-server.yml b/.github/ISSUE_TEMPLATE/request-server.yml new file mode 100644 index 0000000..79ddd0d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/request-server.yml @@ -0,0 +1,75 @@ +name: Request a Server +description: Suggest an MCP server we should add to the registry +title: "[Request] " +labels: ["server-request"] +body: + - type: markdown + attributes: + value: | + Know of an MCP server that should be in the McpMux registry? Tell us about it here. + + If you already have a working definition, use the **Submit a Server** template (or open a PR) instead — that's the fastest path. + + - type: input + id: name + attributes: + label: Server Name + description: What is this server called? + placeholder: e.g., Linear, Stripe, Obsidian + validations: + required: true + + - type: input + id: repository + attributes: + label: Upstream Repository or Homepage + description: Link to the MCP server's source code or docs (leave blank if you don't know of one yet) + placeholder: https://github.com/... or https://example.com/mcp + validations: + required: false + + - type: textarea + id: use_case + attributes: + label: What would you use it for? + description: A concrete example helps us prioritise. + placeholder: e.g., "Let Claude read my Linear issues so I can triage from chat." + validations: + required: true + + - type: dropdown + id: transport + attributes: + label: Transport (if known) + options: + - Not sure + - stdio (local command) + - http (remote URL) + validations: + required: false + + - type: checkboxes + id: categories + attributes: + label: Categories (pick any that fit) + options: + - label: Developer Tools + - label: Version Control + - label: Cloud Services + - label: Productivity + - label: Database + - label: Search & Web + - label: Communication + - label: File System + - label: Documentation + - label: AI & Machine Learning + - label: Monitoring & Observability + - label: Security + + - type: textarea + id: context + attributes: + label: Additional Context + description: Anything else we should know? Pricing, auth requirements, whether one already exists but needs polish, related issues, etc. + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/submit-server.yml b/.github/ISSUE_TEMPLATE/submit-server.yml deleted file mode 100644 index f99aac3..0000000 --- a/.github/ISSUE_TEMPLATE/submit-server.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Submit a Server -description: Submit an MCP server to the registry -title: "[Server] " -labels: ["new-server"] -body: - - type: input - id: name - attributes: - label: Server Name - placeholder: e.g., GitHub MCP Server - validations: - required: true - - type: input - id: repository - attributes: - label: Repository URL - placeholder: https://github.com/... - validations: - required: true - - type: dropdown - id: transport - attributes: - label: Transport Type - options: - - stdio (local command) - - http (remote URL) - validations: - required: true - - type: textarea - id: description - attributes: - label: Description - placeholder: What does this server do? - validations: - required: true - - type: input - id: install_command - attributes: - label: Install Command (for stdio) - placeholder: e.g., npx -y @example/mcp-server - - type: input - id: url - attributes: - label: Server URL (for http) - placeholder: https://api.example.com/mcp - - type: checkboxes - id: categories - attributes: - label: Categories - options: - - label: Developer Tools - - label: Version Control - - label: Cloud Services - - label: Productivity - - label: Database - - label: Search & Web - - label: Communication - - label: File System - - label: Documentation - - label: AI & Machine Learning diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 8ee38a3..b6fa77e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,18 +1,85 @@ -## New Server Definition - -**Server Name:** -**Server ID:** -**Transport:** stdio / http -**Repository:** - -### Checklist - -- [ ] JSON file placed in `servers/` directory -- [ ] File name matches server ID (e.g., `com.example.server.json`) -- [ ] Schema validates (`npm run validate servers/your-file.json`) -- [ ] No ID/alias conflicts (`npm run check-conflicts`) -- [ ] Required fields: `id`, `name`, `transport` -- [ ] Description provided -- [ ] At least one category assigned -- [ ] Publisher information included -- [ ] Repository link provided + + +## Change Type + + + +- [ ] Add a new server definition +- [ ] Update an existing server definition +- [ ] Fix a bug in an existing definition +- [ ] Other (describe in Summary) + +## Summary + + + +## Server Details + + + +- **Server Name:** +- **Server ID:** `community.example` or `com.publisher-name` +- **Transport:** `stdio` / `http` +- **Authentication:** `none` / `api_key` / `optional_api_key` / `oauth` / `basic` +- **Categories:** +- **Upstream Repository:** https://github.com/... + +## Checklist + +### CI-enforced — your PR will fail without these + +- [ ] JSON file lives at `servers/.json` +- [ ] Filename matches the `id` field exactly +- [ ] Required fields present: `id`, `name`, `transport` +- [ ] `pnpm validate servers/.json` passes +- [ ] `pnpm check-conflicts` passes (no duplicate IDs or aliases) +- [ ] `pnpm test` passes +- [ ] Every commit is signed off — `git commit -s` (DCO) + +### Reviewer quality bar + +- [ ] `description` is one clear sentence — no marketing fluff +- [ ] At least one category from [`categories.json`](../categories.json) is assigned +- [ ] Every `${input:ID}` placeholder has a matching `metadata.inputs[].id` +- [ ] Every secret / credential input is marked `"secret": true` +- [ ] Each credential input has an `obtain` block with step-by-step instructions (numbered, `\n` between steps) +- [ ] `auth.type` is consistent with how credentials are actually wired into the transport +- [ ] `links.repository` resolves (when the upstream is public) +- [ ] `capabilities` (`tools` / `resources` / `prompts` / `read_only_mode`) reflect what the server actually implements +- [ ] `platforms` is accurate — don't claim `["all"]` without verifying Windows/macOS/Linux + +### Platform-managed fields — leave unset + + + +- [ ] I did **not** set `badges`, `stats`, `sponsored`, `featured` +- [ ] I did **not** set `publisher.official`, `publisher.verified`, `publisher.domain_verified` +- [ ] I did **not** add any `_platform*`-prefixed keys + +### Trademark & branding + + + +- [ ] No "official" / "certified" / "endorsed" wording unless I represent the trademark owner +- [ ] I have the right to reference the `icon` URL (emoji or an asset I'm allowed to hot-link) + +### Tested locally (recommended for new servers) + +- [ ] Installed the server in McpMux and it started successfully +- [ ] Called at least one tool / fetched at least one resource / rendered at least one prompt + +## Notes for Reviewers + + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e26c374 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,128 @@ +# AGENTS.md + +Guidance for coding agents working inside the `mcp-servers` registry repo. Complements [`README.md`](README.md) and [`CONTRIBUTING.md`](CONTRIBUTING.md); when anything here conflicts with an explicit user instruction in the current session, the user wins. + +## Project Overview + +`mcp-servers` is the community-maintained registry of MCP server definitions for [McpMux](https://mcpmux.com). Each server is a single JSON file in `servers/`, validated against a JSON Schema on every PR. Merges to `main` are bundled and published to the McpMux discovery API, so definitions land in user installs automatically. + +This is **not** a code repo — there is no runtime to ship, no UI to build. The artefact is the set of JSON files and the bundle generated from them. Agent changes here are almost always JSON edits plus CI green. + +## Repository Layout + +``` +mcp-servers/ +├── servers/ # One JSON file per MCP server — the registry +├── schemas/ +│ └── server-definition.schema.json # JSON Schema 2020-12 — the contract +├── categories.json # Allowed categories +├── examples/ # Starter templates for contributors +│ ├── complete-example.json +│ ├── remote-hosted-example.json +│ ├── read-only-example.json +│ └── sponsored-example.json +├── scripts/ +│ ├── validate.js # AJV validation + conflict detection +│ └── build-bundle.js # Aggregates servers into bundle/bundle.json +├── tests/ # Vitest — schema, consistency, categories, bundle +├── bundle/ # Generated — do not edit by hand +├── CONTRIBUTING.md +└── LICENSE # Elastic License 2.0 (ELv2) +``` + +## Setup + +```bash +pnpm install +``` + +Node.js 20+ and pnpm 9+. No Rust, no native deps. + +## Commands + +| Command | What it does | +|---------|--------------| +| `pnpm validate servers/.json` | Validate specific definition(s) against the schema. | +| `pnpm validate:all` | Validate every file in `servers/`. | +| `pnpm check-conflicts` | Detect ID/alias collisions across definitions. | +| `pnpm test` | Full test suite (schema, consistency, categories, bundle). | +| `pnpm test:watch` | Watch mode for local iteration. | +| `pnpm build` | Generate `bundle/bundle.json`. | + +**Always run `pnpm validate:all && pnpm check-conflicts && pnpm test` before claiming a change is done.** CI runs the same checks on every PR. + +## Server Definition Rules + +Every definition must include **`id`**, **`name`**, and **`transport`**. Recommended additions: `description`, `alias`, `categories`, `capabilities`, `links.repository`, `contributor`, `platforms`, `auth`. + +### ID convention + +- Format `{tld}.{publisher}-{name}`, lowercase, regex `^[a-z0-9]+\.[a-z0-9][a-z0-9-]*$`. +- `com.*` — official publishers / well-known orgs (`com.github-mcp`, `com.notion-mcp`). +- `community.*` — community contributions (`community.sqlite`, `community.brave-search`). +- The filename must match the ID: `servers/community.brave-search.json`. + +### Transport + +- `stdio` — local command, runs on the user's machine. Provide `command`, `args`, optional `env`. +- `http` — remote Streamable-HTTP endpoint. Provide `url`. + +### Input placeholders + +User-supplied values flow through `${input:VAR}` substitution in `env` and `args`. Every placeholder must have a matching entry in `transport.metadata.inputs`. For secrets, set `secret: true` and `type: "password"` so McpMux encrypts them in the OS keychain. Include an `obtain` block with step-by-step instructions whenever the user has to visit a dashboard. + +See `examples/complete-example.json` for the full shape. + +### Categories + +Must come from `categories.json`. Need a new one? Open a registry issue — don't invent an ID inline. + +## Platform-Managed Fields (do not set) + +Contributor PRs that touch these are rejected: + +- `badges`, `stats`, `sponsored`, `featured` +- `publisher.official`, `publisher.verified`, `publisher.domain_verified` +- Any `_platform*` prefix + +These are computed or granted by McpMux maintainers after verification. + +## Trademark & Branding + +- Reference third-party products with "works with", "for", or "connects to" — never "official", "certified", "endorsed" unless you represent the trademark owner and are verified. +- Icons are referenced by URL (emoji or external) — McpMux does not host icon files. Only link to assets you have the right to reference. +- See `TRADEMARK-TAKEDOWN.md` for the full IP policy. + +## Commit & PR Guidelines + +- Commits must be **signed off** (DCO): `git commit -s -m "..."`. CI rejects unsigned commits. +- One server per PR keeps review fast. Multi-server PRs are fine for coordinated maintenance sweeps. +- PRs follow [`.github/PULL_REQUEST_TEMPLATE.md`](.github/PULL_REQUEST_TEMPLATE.md). The checklist exists to catch the common failure modes — please actually tick it. +- Don't bypass hooks (`--no-verify`) or DCO signing unless explicitly told to. + +## Issue Templates + +Two templates live in `.github/ISSUE_TEMPLATE/`: + +- `request-server.yml` — ask the community to add a server you don't have a definition for. **Deep-linked from the McpMux desktop app** — keep the filename stable. +- `bug-report.yml` — flag a broken or incorrect existing definition. **Deep-linked from the McpMux desktop app** — keep the filename stable. + +Contributors who want to add a server open a PR against `servers/` — there is no issue-based submission path. See `CONTRIBUTING.md` for the flow. + +Renaming or removing either template breaks deep links shipped in every installed McpMux — don't do it without coordinating with the app. + +## Adding a Server — Quick Recipe + +1. Copy the closest template from `examples/` to `servers/.json`. +2. Set `id`, `name`, `description`, `transport`, `categories`, `links.repository` at minimum. +3. For every user-provided value, add an entry to `transport.metadata.inputs` with `obtain` instructions. +4. `pnpm validate servers/.json && pnpm check-conflicts && pnpm test`. +5. `git commit -s -m "Add "` and open a PR. + +## Things Not To Do + +- **Don't edit `bundle/`** — it's generated by `scripts/build-bundle.js`. CI will overwrite anything you put there. +- **Don't edit `schemas/server-definition.schema.json`** as part of a server submission. Schema changes are their own PR, discussed separately. +- **Don't claim official status** (`publisher.official: true`, "official" badge, etc.) unless you're a verified publisher. +- **Don't remove or rename issue-template files** without coordinating with the McpMux app — the desktop app links to specific template filenames. +- **Don't add servers that require the user to run arbitrary shell scripts during install.** Stick to `npx`, `uvx`, `docker`, `python`, `node`, or HTTPS endpoints. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index defb96b..2f8095a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,124 +1,670 @@ -# Contributing MCP Servers +# Contributing to the McpMux Server Registry -Thank you for contributing to the MCPMux server registry! +Thank you for contributing! Every definition in `servers/` becomes a one-click install for every McpMux user once it's merged. This guide walks you through the full lifecycle of a contribution: license, setup, definition anatomy, validation, PR workflow, review criteria, and the trademark rules that keep the registry honest. -## License +If you're in a hurry, jump to: + +- [Quick Start](#quick-start) — five commands to a green PR +- [Anatomy of a Definition](#anatomy-of-a-definition) — every field, whether it's required, and what it does +- [PR Checklist](#pr-checklist) — what CI and reviewers verify +- [Troubleshooting](#troubleshooting) — fixes for the validation errors you'll actually hit + +> Looking to **request** a server rather than add one yourself? Open a [Request a Server](https://github.com/mcpmux/mcp-servers/issues/new?template=request-server.yml) issue. Looking to **report a broken definition**? Use the [Bug in a Server Definition](https://github.com/mcpmux/mcp-servers/issues/new?template=bug-report.yml) template. + +--- + +## Table of Contents + +- [License & DCO](#license--dco) +- [Prerequisites](#prerequisites) +- [Quick Start](#quick-start) +- [Repository Layout](#repository-layout) +- [Anatomy of a Definition](#anatomy-of-a-definition) + - [Required Fields](#required-fields) + - [Recommended Fields](#recommended-fields) + - [Optional Fields](#optional-fields) +- [ID & Filename Rules](#id--filename-rules) +- [Transports](#transports) + - [`stdio` — Local Command](#stdio--local-command) + - [`http` — Remote Endpoint](#http--remote-endpoint) +- [User Inputs](#user-inputs) + - [Placeholder Syntax](#placeholder-syntax) + - [Input Definition](#input-definition) + - [Input Types](#input-types) + - [The `obtain` Block](#the-obtain-block) +- [Authentication](#authentication) +- [Categories](#categories) +- [Capabilities](#capabilities) +- [Links, Contributor, Platforms, Media](#links-contributor-platforms-media) +- [Platform-Managed Fields (Do Not Set)](#platform-managed-fields-do-not-set) +- [Validation Commands](#validation-commands) +- [PR Workflow](#pr-workflow) +- [PR Checklist](#pr-checklist) +- [Review Criteria](#review-criteria) +- [Updating an Existing Server](#updating-an-existing-server) +- [Removing a Server](#removing-a-server) +- [Trademark & Branding Policy](#trademark--branding-policy) +- [Security Expectations](#security-expectations) +- [Troubleshooting](#troubleshooting) +- [Questions & Help](#questions--help) + +--- + +## License & DCO This repository is licensed under the [Elastic License 2.0 (ELv2)](LICENSE). By contributing, you agree that your contributions will be licensed under the same license. -## Developer Certificate of Origin (DCO) +All contributions require a **Developer Certificate of Origin** sign-off on every commit. Add it automatically with `-s`: + +```bash +git commit -s -m "Add community.my-server" +``` + +That produces a trailer like `Signed-off-by: Your Name ` on the commit. By signing off, you certify the statements in the [Developer Certificate of Origin v1.1](https://developercertificate.org/): + +1. You created the contribution, or +2. It's based on work you have the right to submit under this license, or +3. It was provided to you by someone who certified the above. -All contributions must be signed off: +**CI rejects unsigned commits.** If you forget, amend with `git commit --amend -s --no-edit` and force-push your branch. + +## Prerequisites + +- **Node.js 20+** and **pnpm 9+** — no Rust, no native dependencies. +- A GitHub account with your fork of this repo. +- A text editor with JSON support. VS Code picks up `"$schema": "../schemas/server-definition.schema.json"` and gives you field-level autocomplete and inline errors while you type. + +## Quick Start ```bash -git commit -s -m "Add my-server" +# 1. Fork on github.com, then clone your fork +git clone https://github.com//mcp-servers.git +cd mcp-servers && pnpm install + +# 2. Copy the closest starter template +cp examples/complete-example.json servers/community.my-server.json + +# 3. Edit the file (at minimum: id, name, description, transport, categories, links.repository) + +# 4. Validate locally +pnpm validate servers/community.my-server.json +pnpm check-conflicts +pnpm test + +# 5. Commit (signed off) and open a PR +git checkout -b add-my-server +git add servers/community.my-server.json +git commit -s -m "Add community.my-server" +git push origin add-my-server +# Open the PR in your browser from the link git prints +``` + +Your PR will be validated automatically and reviewed by a maintainer. Once merged, the next registry bundle build publishes the definition to every McpMux install. + +## Repository Layout + +``` +mcp-servers/ +├── servers/ # One JSON file per server — the registry +├── schemas/ +│ └── server-definition.schema.json # JSON Schema 2020-12 — the contract +├── categories.json # Allowed category IDs +├── examples/ +│ ├── complete-example.json # stdio server with API key + obtain +│ ├── remote-hosted-example.json # HTTP server with OAuth +│ ├── read-only-example.json # HTTP docs/search server, no auth +│ └── sponsored-example.json # stdio with integration token +├── scripts/ +│ ├── validate.js # AJV validation + conflict detection +│ └── build-bundle.js # Aggregates definitions into bundle.json +├── tests/ # Vitest — schema, consistency, categories +├── bundle/ # Generated — do not edit +└── CONTRIBUTING.md # This file ``` -By signing off, you certify you have the right to submit the contribution under this license. See [developercertificate.org](https://developercertificate.org/) for details. +Pick the example that most resembles the server you're contributing and start from there — it's faster than building from scratch and ensures you don't miss fields. + +--- + +## Anatomy of a Definition + +Every server is a single JSON file at `servers/.json`. The schema at [`schemas/server-definition.schema.json`](schemas/server-definition.schema.json) is the authoritative spec. This section summarises what you'll actually use. -## Adding a Server +### Required Fields -### 1. Create Server Definition +Three fields are non-negotiable — validation fails without them: -Create a JSON file in `servers/` following this structure: +| Field | Type | Notes | +|-------|------|-------| +| `id` | string | Pattern `^[a-z0-9]+\.[a-z0-9][a-z0-9-]*$`. See [ID & Filename Rules](#id--filename-rules). | +| `name` | string | Human-readable display name. Minimum length 1. | +| `transport` | object | See [Transports](#transports). Must be `stdio` or `http`. | + +### Recommended Fields + +Strongly encouraged — the registry UI shows them prominently and users filter by them: + +| Field | Type | Notes | +|-------|------|-------| +| `$schema` | string | `"../schemas/server-definition.schema.json"` — gives editors autocomplete. | +| `description` | string | One sentence, plain English. Shown in listings. | +| `alias` | string | Short CLI alias, pattern `^[a-z0-9-]+$`. Must not collide with any `id` or other alias. | +| `icon` | string | Emoji (e.g. `"🐙"`) or a stable image URL (avatars, project logos). McpMux does **not** host icon files. | +| `schema_version` | string | Currently `"2.1"`. Bump when the project publishes a new contributor schema version. | +| `categories` | string[] | IDs from [`categories.json`](categories.json). At least one. | +| `tags` | string[] | Lowercase keywords for search (`"git"`, `"search"`, `"wiki"`). 3–8 is a good target. | +| `auth` | object | See [Authentication](#authentication). Tells users what credential they need. | +| `contributor` | object | Who's adding this (`name`, `github`, `url`). | +| `links` | object | `repository`, `homepage`, `documentation`. At least `repository` if one exists. | +| `platforms` | string[] | `["all"]` or any subset of `["windows", "macos", "linux"]`. | +| `capabilities` | object | `tools`, `resources`, `prompts`, `read_only_mode` — see [Capabilities](#capabilities). | + +### Optional Fields + +Use when they add value: + +| Field | Type | Notes | +|-------|------|-------| +| `media.screenshots` | string[] | Up to 5 URLs. Recommended 1200×800. | +| `media.demo_video` | string | YouTube / Vimeo / similar. | +| `media.banner` | string | For featured display (1200×400). | +| `changelog_url` | string | Releases or CHANGELOG URL. | + +--- + +## ID & Filename Rules + +IDs follow the format `{tld}.{publisher}-{name}`: + +| Namespace | Who | Examples | +|-----------|-----|----------| +| `com.*` | Official publisher or a well-known org with legitimate claim to the namespace | `com.github-mcp`, `com.notion-mcp`, `com.cloudflare-docs` | +| `community.*` | Third-party contributors — this is where most submissions live | `community.sqlite`, `community.brave-search` | + +Additional rules the validator enforces: + +- **Lowercase** only. No uppercase, no spaces, no underscores in the publisher or name segment. +- **Regex:** `^[a-z0-9]+\.[a-z0-9][a-z0-9-]*$`. One dot, first segment is TLD-ish, second segment starts with alphanumeric and may contain hyphens. +- **Filename must match ID:** `servers/com.github-mcp.json`. The bundler derives the filename from the ID. +- **Uniqueness:** `pnpm check-conflicts` fails if an ID is reused, or if an `alias` collides with any `id` or other `alias` in the registry. +- **Multiple servers per publisher are fine:** `com.cloudflare-docs` and `com.cloudflare-bindings` coexist happily. + +Pick the alias deliberately — users type it, so short and obvious wins (`gh`, `brave`, `cf-docs`). + +--- + +## Transports + +Exactly one of two transport types is allowed. The `oneOf` in the schema means mixing fields from both will fail validation. + +### `stdio` — Local Command + +Spawns a process on the user's machine; McpMux speaks MCP over stdin/stdout. Use for CLI tools, local SDKs, and anything that already ships as `npx`, `uvx`, `docker`, `python`, or `node`. ```json -{ - "id": "your-server-id", - "name": "Your Server Name", - "description": "What your server does", - "author": "your-github-username", - "repository": "https://github.com/you/your-server", - "transport": { - "type": "stdio", - "command": "npx", - "args": ["-y", "your-package"] +"transport": { + "type": "stdio", + "command": "npx", + "args": ["-y", "@brave/brave-search-mcp-server"], + "env": { + "BRAVE_API_KEY": "${input:BRAVE_API_KEY}" }, - "categories": ["category1", "category2"] + "metadata": { + "inputs": [ + { + "id": "BRAVE_API_KEY", + "label": "Brave Search API Key", + "type": "password", + "required": true, + "secret": true, + "placeholder": "BSAxxxx", + "obtain": { + "url": "https://brave.com/search/api/", + "instructions": "1. Sign up\n2. Subscribe (free tier)\n3. Copy the key", + "button_label": "Get API Key" + } + } + ] + } +} +``` + +Allowed fields: `type`, `command` (required), `args`, `env`, `cwd`, `metadata`. Nothing else — `additionalProperties: false`. + +**Command choice matters:** + +- `npx -y ` and `uvx ` are preferred — they install on first run with no separate setup. +- `docker run --rm -i ...` works too; use `-i` for stdin and `--rm` to clean up. +- `python`, `node`, or a raw binary path only if users realistically have them available. +- **Avoid** `bash -c`, `sh -c`, or anything that invokes a shell to run a script. See [Security Expectations](#security-expectations). + +### `http` — Remote Endpoint + +Points at a hosted Streamable-HTTP MCP server. No local install required. + +```json +"transport": { + "type": "http", + "url": "https://mcp.atlassian.com/v1/mcp", + "headers": { + "X-My-Header": "${input:HEADER_VAL}" + }, + "metadata": { "inputs": [] } +} +``` + +Allowed fields: `type`, `url` (required), `headers`, `metadata`. `headers` values support `${input:ID}` interpolation just like `env`. + +Prefer HTTP transport when the upstream is a SaaS product — users don't have to install anything locally, and OAuth flows stay clean. + +--- + +## User Inputs + +Anything a user has to provide — API keys, file paths, workspace slugs, enable/disable toggles — goes through `transport.metadata.inputs`. McpMux renders a setup form from this array, substitutes values at runtime, and encrypts secrets. + +### Placeholder Syntax + +Reference inputs as `${input:ID}` anywhere inside `env`, `args`, or `headers`: + +```json +"env": { "GITHUB_TOKEN": "${input:GITHUB_TOKEN}" }, +"args": ["--db-path", "${input:DB_PATH}"], +"headers": { "Authorization": "Bearer ${input:TOKEN}" } +``` + +**Every placeholder must have a matching `inputs[].id`.** The `build-bundle.js` step doesn't catch this today, but the UX breaks silently if a user submits the form and McpMux tries to substitute a placeholder that has no corresponding input. + +### Input Definition + +| Property | Required | Notes | +|----------|----------|-------| +| `id` | Yes | Uppercase regex `^[A-Z0-9_]+$` (e.g. `API_KEY`, `DB_PATH`). Matches the `${input:ID}` placeholder. | +| `label` | Yes | Human-readable label shown in the UI. | +| `type` | No | See [Input Types](#input-types). Default `"text"`. | +| `required` | No | Default `false`. Required inputs block form submission until provided. | +| `secret` | No | Default `false`. `true` → stored in the OS keychain, never written to plain SQLite or logged. | +| `description` | No | Help text shown beneath the field. | +| `default` | No | Pre-filled value used when the user provides none. | +| `placeholder` | No | Greyed hint inside the input. | +| `obtain` | No | See [The `obtain` Block](#the-obtain-block). | +| `options` | No | For `type: "select"` only — array of `{ value, label, description? }`. | + +### Input Types + +Pick the type that matches how the value is used: + +| Type | When to use | +|------|-------------| +| `text` | Free-form string (default). | +| `number` | Numeric values — the UI renders a number input. | +| `boolean` | On/off toggles — becomes `"true"` / `"false"` as a string when substituted. | +| `url` | URLs — the UI validates shape. | +| `select` | Closed set of options — pair with `options: [{ value, label, description? }]`. | +| `file_path` | File picker. | +| `directory_path` | Directory picker. | + +There is no dedicated `password` input type in the **schema enum** — use `type: "text"` plus `secret: true` for API keys. (The UI masks secret fields regardless of `type`.) Existing definitions use `type: "password"` informally; the schema's strict input-type enum is the source of truth, so prefer `text + secret: true` for new submissions. + +**Always pair API keys with `secret: true` and `required: true`.** That's how McpMux knows to stash the value in the OS keychain instead of SQLite. + +### The `obtain` Block + +Whenever a value requires the user to visit a dashboard, sign up, or generate a token, include an `obtain` block. It becomes a one-click button next to the field in the setup UI. + +```json +"obtain": { + "url": "https://github.com/settings/tokens/new", + "instructions": "1. Click 'Generate new token (classic)'\n2. Give it a name like 'McpMux'\n3. Select scopes: repo, read:org\n4. Click 'Generate token'\n5. Copy the token (starts with ghp_)", + "button_label": "Create Token" +} +``` + +Guidance: + +- **Number your steps** and use `\n` between them — the UI renders each as a separate line. +- **Be specific about scopes / permissions** users should check. A GitHub token with no scopes is useless; they'll open an issue asking why the server "doesn't work". +- **Link deep** when you can (`.../settings/tokens/new?scopes=repo,read:org&description=McpMux`) — GitHub and a few others pre-fill the form. +- **Keep `button_label` short** (<= 20 characters). "Create Token", "Get API Key", "Open Console". + +--- + +## Authentication + +The top-level `auth` field advertises what kind of credential the server expects, independent of how it's wired up in `transport`. + +| `type` | When to use | +|--------|-------------| +| `none` | No credentials (local filesystem, public docs, open search). | +| `api_key` | A token is required for any useful call. | +| `optional_api_key` | Works without auth (rate-limited or read-only) but unlocks more with a key. | +| `oauth` | Full OAuth 2.1 + PKCE flow. McpMux drives the redirect. | +| `basic` | HTTP Basic auth (username + password). Rare; prefer `api_key` or `oauth`. | + +```json +"auth": { + "type": "api_key", + "instructions": "Get an API key at https://brave.com/search/api/" +} +``` + +`instructions` is free-form. Keep it to one or two sentences — the detailed flow belongs in the input's `obtain` block. + +> **Note:** `auth.type` is a hint to the UI; McpMux doesn't use it to decide whether to inject credentials into the transport — that's driven by `inputs` and `${input:...}` placeholders. Both need to be consistent. + +--- + +## Categories + +Every server should declare at least one category from [`categories.json`](categories.json): + +| ID | Name | +|----|------| +| `developer-tools` | Developer Tools | +| `version-control` | Version Control | +| `cloud` | Cloud Services | +| `productivity` | Productivity | +| `database` | Database | +| `search` | Search & Web | +| `communication` | Communication | +| `file-system` | File System | +| `documentation` | Documentation | +| `ai-ml` | AI & Machine Learning | +| `monitoring` | Monitoring & Observability | +| `security` | Security | +| `design` | Design | + +Multiple categories are fine when they genuinely apply (e.g. `["productivity", "documentation"]` for a wiki tool). Don't stuff every plausible category — it dilutes filtering. + +Need a new category? Open an [issue](https://github.com/mcpmux/mcp-servers/issues/new/choose) **before** opening your PR — category changes touch `categories.json`, the schema tests, and the discovery UI, so they're easier to land separately. + +--- + +## Capabilities + +Declare what the server actually implements — the registry UI uses these as filters. + +```json +"capabilities": { + "tools": true, // Exposes callable MCP tools + "resources": true, // Provides readable MCP resources + "prompts": false, // Provides prompt templates + "read_only_mode": false // true = server never writes or performs destructive actions } ``` -### 2. Validation +- `tools`, `resources`, `prompts` mirror the [MCP capabilities](https://modelcontextprotocol.io/) the server advertises on `initialize`. +- `read_only_mode: true` is a **strong** claim. Set it only for docs lookup, search, observability dashboards, and similar — any write endpoint disqualifies. This drives a filter users rely on to sandbox agents. -Your server definition will be validated against our schema. Ensure: +If you're unsure, install the server locally, run it, and check the `initialize` response. Declaring a capability the server doesn't implement is a reviewer reject. -- `id` is unique and lowercase (e.g., `my-cool-server`) -- `name` is human-readable -- `description` clearly explains what the server does -- `repository` points to the source code -- `transport` specifies how to run the server +--- -### 3. Submit PR +## Links, Contributor, Platforms, Media -1. Fork this repository -2. Add your server file: `servers/your-server-id.json` -3. Sign off your commit: `git commit -s` -4. Create a Pull Request +### `links` -### Review Process +```json +"links": { + "repository": "https://github.com/brave/brave-search-mcp-server", + "homepage": "https://brave.com/search/api/", + "documentation": "https://api.search.brave.com/app/documentation" +} +``` + +At least `repository` when one exists. Format: valid URI. Broken links are a reviewer reject. + +### `contributor` + +```json +"contributor": { + "name": "Brave", + "github": "brave", + "url": "https://brave.com" +} +``` + +This is you, or the org you represent. `github` is a username without the `@`. -- Automated validation checks schema compliance -- Maintainers review for quality and security -- Once approved, your server appears in the MCPMux registry +### `platforms` + +```json +"platforms": ["all"] +// or +"platforms": ["macos", "linux"] +``` -## Updating a Server +Use `["all"]` unless the server genuinely doesn't run on one of Windows / macOS / Linux (e.g. it spawns `.dll` hooks). Containerised servers are typically `all`. -Follow the same process. Update your existing file and submit a PR. +### `media` + +Optional but discoverable — up to 5 screenshots, one demo video, one banner: + +```json +"media": { + "screenshots": [ + "https://example.com/screens/1.png", + "https://example.com/screens/2.png" + ], + "demo_video": "https://youtube.com/watch?v=...", + "banner": "https://example.com/banner-1200x400.png" +} +``` + +Only reference images you have the right to display. McpMux hot-links these; a broken or rotating URL will look bad in the registry. + +--- + +## Platform-Managed Fields (Do Not Set) + +The validator strips and **warns** on these during `pnpm validate`. Setting them in a PR is a review reject: + +- `badges` — computed from publisher verification status +- `stats` — installs, stars, usage metrics (computed) +- `sponsored` — commercial sponsorship slot (McpMux only) +- `featured` — homepage feature selection (McpMux only) +- `publisher.official`, `publisher.verified`, `publisher.domain_verified` — require maintainer verification +- Any top-level key prefixed with `_platform` — reserved for the bundler + +If you believe your server qualifies for verified or official status, say so in the PR description and a maintainer will follow up separately. + +--- + +## Validation Commands + +Run locally before pushing — CI runs the same commands and will fail the PR otherwise: + +```bash +pnpm validate servers/community.my-server.json # Validate a specific file +pnpm validate:all # Validate every server +pnpm check-conflicts # ID / alias collision detection +pnpm test # Full vitest suite (schema, consistency, categories, bundle) +pnpm build # Generate bundle/bundle.json (optional locally) +``` + +`validate` accepts multiple file arguments: `pnpm validate servers/a.json servers/b.json`. It prints: + +- `PASS servers/your-file.json` — structurally valid. +- `FAIL servers/your-file.json` — followed by `- /field/path: reason` lines from AJV. +- `WARNING:` lines when platform-managed fields are present (they'll be stripped at build time). + +`check-conflicts` reports: + +- `CONFLICT Duplicate ID "..."` — same `id` in two files. +- `CONFLICT Duplicate alias "..."` — same `alias` in two files. +- `CONFLICT ID "..." collides with alias in ...` — your ID matches an existing alias (or vice versa). + +--- + +## PR Workflow + +1. **Fork & branch.** Keep unrelated changes on separate branches; one server per PR keeps review fast. + +2. **Add or edit the JSON** in `servers/.json`. + +3. **Validate locally** — all three commands should pass before you push: + ```bash + pnpm validate servers/.json + pnpm check-conflicts + pnpm test + ``` + +4. **Commit with sign-off:** + ```bash + git commit -s -m "Add community.my-server" + ``` + +5. **Push and open a PR.** Use the [PR template](.github/PULL_REQUEST_TEMPLATE.md). A good title is `Add com.example-tool` or `Fix env var name for community.sqlite`. + +6. **CI runs.** The `validate-pr` workflow runs the same commands you ran locally, plus bundle regeneration. Red tick → read the log, fix, push again (no need to close/reopen). + +7. **Review.** A maintainer will sanity-check the definition and, for stdio servers, may test the install locally. Expect feedback within a few days; poke the thread if you don't hear back in a week. + +8. **Merge.** On merge, the registry bundler picks up the new definition and uploads a fresh `bundle.json` to Cloudflare R2. Desktop apps see it on their next refresh (usually under a minute). + +## PR Checklist + +CI automatically verifies: + +- [ ] JSON file placed in `servers/` +- [ ] Filename matches the `id` field (`servers/com.example.json` ↔ `"id": "com.example"`) +- [ ] Schema validates (`pnpm validate`) +- [ ] No ID / alias conflicts (`pnpm check-conflicts`) +- [ ] All required fields present (`id`, `name`, `transport`) +- [ ] DCO sign-off on every commit + +Reviewers additionally check: + +- [ ] `description` is accurate, one sentence, and doesn't oversell +- [ ] `transport.command` / `transport.url` actually works (for stdio, preferably installable via `npx`/`uvx`/`docker`) +- [ ] Every `${input:ID}` placeholder has a matching `inputs[].id` +- [ ] Secrets are marked `secret: true` so they land in the OS keychain +- [ ] `obtain` blocks exist and have usable instructions for every credential +- [ ] At least one valid category from `categories.json` +- [ ] `links.repository` (when one exists) is public and resolves +- [ ] `capabilities` reflect what the server actually implements +- [ ] No platform-managed fields (`badges`, `stats`, `sponsored`, `featured`, `publisher.official`, etc.) +- [ ] No trademark / branding violations (see below) + +## Review Criteria + +Beyond the checklist, reviewers apply judgement on: + +- **Is this useful to more than one person?** The registry isn't a dump for hobby scripts. A "works on my machine" tool with no upstream repo is usually a reject. +- **Is the upstream project alive?** Commit recency, open issue triage, signs of maintenance. Abandoned servers get nudged toward archival. +- **Is the install command correct on every declared platform?** If you claim `platforms: ["all"]` and the command only works on Linux, that's a blocker. +- **Does the description avoid marketing fluff?** "The best MCP server for X" → no. "Search Brave with privacy-focused results" → yes. +- **Does the definition avoid claiming official/verified status it hasn't earned?** That's an auto-reject — see the policy below. + +--- + +## Updating an Existing Server + +Same process as adding one: edit the JSON in `servers/`, validate, sign-off commit, PR. Title the PR `Update : ` so it's obvious at a glance. + +If you're the original contributor, you can make changes freely. If someone else originally submitted the server, prefer opening an issue first to coordinate — especially for breaking changes like renaming inputs, changing the transport, or adjusting scopes. + +**Never change an `id` on an existing server.** Users with the server installed will lose their configuration. If you truly need to rename, add a new file under the new ID and flag the old one for archival in the PR description. + +## Removing a Server + +Open an issue or PR explaining why (upstream archived, security issue, duplicate, trademark takedown). Maintainers handle the actual removal so the bundler knows to signal existing installs. --- ## Trademark & Branding Policy +The registry is community-built but consumed via the McpMux brand, so we're careful here. + +### Names & descriptions + +- **Descriptive use is fine:** "MCP Server for GitHub", "Connects to Notion", "Works with Linear". +- **Implied endorsement is not:** "Official GitHub MCP", "Certified by Notion", "Endorsed by Linear" — unless you actually represent the trademark owner and have been verified. +- Phrases to prefer: *works with*, *for*, *connects to*, *integrates with*. + ### Icons -- You may reference icon URLs in the `icon` field (emoji or external URL) -- McpMux does not host icons — they are loaded directly from the URL you provide -- Do NOT submit URLs to assets you don't have the right to reference -- Prefer emoji icons or GitHub avatar URLs when possible +- McpMux does not host icon files. The `icon` field is either an emoji or a URL to an image. +- **Only reference assets you have the right to use.** Corporate logos are usually fine for descriptive, non-commercial use in a directory listing; but don't hot-link assets with restrictive terms. +- Prefer GitHub avatars (`https://avatars.githubusercontent.com/u/?v=4`) or official brand URLs over random CDN copies that may rotate. + +### Official / verified claims -### Naming & Descriptions +- All community submissions default to unverified. +- `publisher.official`, `publisher.verified`, `publisher.domain_verified`, and `"official"`/`"verified"` badges are maintainer-controlled. PRs that set them are rejected unless submitted by a verified publisher. +- To request verification, open an issue from your org's GitHub account and we'll follow up. -- Server names may reference third-party products for identification - (e.g., "MCP Server for GitHub" is OK) -- Use language like "works with", "for", or "connects to" -- Do NOT use "official", "certified", "endorsed", or "licensed" - unless you represent the trademark owner and have been verified by McpMux +### Takedowns -### Official Status +See [TRADEMARK-TAKEDOWN.md](TRADEMARK-TAKEDOWN.md) for the full IP policy and the maintainer contact path. -- All community submissions default to `official: false` -- To claim `official: true`, you must represent the trademark owner - and go through the McpMux verification process -- False claims of official status will result in submission removal +By opening a PR you agree that: -### Maintainer-Only Fields +1. You have the right to reference any URLs you include. +2. You're not claiming official status or endorsement you don't have. +3. You accept responsibility for trademark compliance of your submission. +4. You grant McpMux a license to display your definition — including rendering any referenced icon URLs — on the discover site and desktop app. +5. McpMux may modify or remove your submission in response to trademark concerns. -The following fields are controlled by McpMux maintainers and must NOT be set -by contributors: +--- + +## Security Expectations -- `publisher.official` — requires proof of authorization from the trademark holder -- `publisher.verified` — granted after McpMux review -- `publisher.domain_verified` — requires DNS verification -- `badges` containing `"official"` or `"verified"` +The registry installs code on end-user machines (for stdio servers) and proxies credentials on their behalf. We hold definitions to a higher bar than typical community packages. -PRs that set these fields will be rejected unless submitted by a verified publisher. +- **No arbitrary shell scripts.** `bash -c "curl ... | sh"` and similar get rejected on sight. Stick to `npx`, `uvx`, `docker`, `python`, `node`, or HTTP endpoints. +- **Credential sanity.** Mark every token/key with `secret: true`. Never bake credentials into `args` that persist in process listings; route them through `env` instead. +- **No network side effects from the definition itself.** The JSON file must be static — no fetched values, no templated install scripts. +- **OAuth prefers PKCE.** If `auth.type: "oauth"`, the upstream should support PKCE; otherwise add a note in `auth.instructions`. +- **Declare `read_only_mode: true` honestly.** A server that deletes calendar events is not read-only, no matter how "safe" the tool author thinks the call is. +- **Report vulnerabilities privately.** If you spot a security issue in an existing definition or upstream server, don't open a public issue — email the maintainers (see repo for current contact) or use GitHub private vulnerability reporting. --- -## Contributor Terms +## Troubleshooting + +### `FAIL servers/foo.json` with `must match pattern` + +You've violated a regex. The two most common culprits: + +- **`id`:** must match `^[a-z0-9]+\.[a-z0-9][a-z0-9-]*$`. No uppercase, no underscores in the publisher segment, exactly one dot. +- **Input `id`:** must match `^[A-Z0-9_]+$`. Uppercase + underscores only. + +### `must match exactly one schema in oneOf` under `transport` -By submitting a Pull Request to this repository, you agree that: +You've mixed fields from both transport types. An `http` transport can't have `command`/`args`/`env`/`cwd`; a `stdio` transport can't have `url`/`headers`. Start fresh from the matching example in `examples/`. -1. You have the right to reference any URLs included in your submission -2. You are not claiming official status or endorsement you do not have -3. You accept responsibility for trademark compliance of your submission -4. You grant McpMux a license to display the submitted definition, including - rendering any referenced icon URLs, on the McpMux discover site and desktop app -5. You understand McpMux may modify or remove your submission at any time - in response to trademark concerns +### `must have required property 'command'` (or `'url'`) + +A transport with `"type": "stdio"` requires `command`. A transport with `"type": "http"` requires `url`. These are enforced by the transport's `oneOf` branches. + +### `CONFLICT Duplicate ID "..."` + +Someone else already registered that ID. Pick another — or if you're updating, make sure you're editing the existing file rather than creating a new one. + +### `CONFLICT Alias "..." collides with ID in ...` + +Aliases share a namespace with IDs. Pick a different alias. + +### `WARNING: "badges" is a platform-managed field and will be stripped` + +You've set a field the platform controls. Remove it from your definition — leaving it in works (the validator strips it) but a reviewer will ask you to clean it up anyway. + +### `must match format "uri"` + +A URL field isn't a valid URI. Common fix: missing scheme. `example.com` fails; `https://example.com` passes. + +### The `$schema` line isn't giving autocomplete in VS Code + +`"$schema": "../schemas/server-definition.schema.json"` works when the file is in `servers/`. If you moved it, adjust the relative path. Restart the JSON language server if it's stuck. --- -## Questions? +## Questions & Help + +- **Ask a question or request a new category:** open an [issue](https://github.com/mcpmux/mcp-servers/issues/new/choose). +- **Discuss designs or roadmap:** [GitHub Discussions](https://github.com/mcpmux/mcp-mux/discussions) on the main repo. +- **Browse before contributing:** the live registry is at [mcpmux.com](https://mcpmux.com) — search first to avoid duplicates. +- **Starter templates:** [`examples/`](examples/) — copy the closest match. -Open an issue if you need help. +Thanks for making the registry better.