# 24,240 MCP Servers In The Official Registry, And Half The Real Ones Are Missing From It

I walked the whole MCP registry and then knocked on every vendor&#39;s door myself. Ten companies run production servers the registry never lists. Here is what to install.

Author: J.A. Watte
Published: August 22, 2026
Source: https://jwatte.com/blog/mcp-servers-for-small-business/

---

I paginated the official Model Context Protocol registry twice today. It took 794 API calls each time.

**24,240 distinct servers.** Roughly seventy percent published under an individual's GitHub account. Eight hundred and ninety six with no package and no remote endpoint at all, meaning there is nothing to run. And the registry's own moderation policy says it will not remove a server for having a security vulnerability.

Then I did something the registry cannot do for you. I knocked on nineteen vendors' doors directly, sending a real protocol handshake to the address you would guess for each. Nine of the servers that answered are listed in the registry. **Ten are not.** HubSpot, Xero, Square, Calendly, Intercom, Pipedrive, Asana, Canva, Sentry and Squarespace all run production first-party MCP servers today, and none of them appears anywhere in the official index.

So the advice "search the registry" fails in both directions at once. It hands you twenty four thousand strangers' projects, and it hides the vendor servers you actually wanted.

Here is what I measured, the ten-second test that separates a vendor's own server from somebody else's, and the short list a small business should actually install.

## What MCP is, in one paragraph

The Model Context Protocol is a standard way to give an AI model tools. Instead of every assistant building a bespoke integration with every application, a program called an MCP server exposes a set of tools, and any MCP-capable client can call them. Anthropic announced it in November 2024 and donated it to the Agentic AI Foundation, a directed fund under the Linux Foundation, in December 2025. It is governed under Specification Enhancement Proposals with a maintainer group that votes fortnightly.

If you have read a description of MCP anywhere, there is a decent chance it is now out of date. **The specification was substantially rewritten on 28 July 2026**, three weeks before I wrote this. That revision made the protocol stateless by removing the initialisation handshake, and it deprecated three of the primitives that every explainer lists: sampling, roots and logging. The near-universal "six primitives" summary no longer matches the spec. Deprecated is not removed, and the policy guarantees at least twelve months, but if you are reading a tutorial written before August 2026 it is describing an older protocol.

None of that matters much to a small business directly. It matters because it tells you how young this is.

## The registry, counted

Measured 22 August 2026 by paginating `registry.modelcontextprotocol.io` to exhaustion.

| | |
|---|---|
| API pages walked | 794 |
| Version records returned | 79,341 |
| **Distinct servers** | **24,240** |
| Distinct remote endpoint hostnames | 9,875 |
| Published under an `io.github.*` namespace | **16,940 servers, 69.9%** |
| Published under a domain-style namespace | 7,296 |
| Servers with neither a package nor a remote | **896** |

I walked it twice, six hours apart. The first pass returned 79,330 records and 24,235 servers; the second returned 79,341 and 24,240. It grew by five servers over a working morning. Treat any count you read, including mine, as a photograph rather than a fact.

Two things worth pulling out.

**The raw record count overstates the registry by more than three times.** The unfiltered listing returns every published version of every server, so 79,341 records is 24,240 servers. If you see a much larger number quoted somewhere, that is probably what happened.

**Almost seventy percent of servers are published under a GitHub account rather than a company domain.** That is not a criticism of the people writing them, plenty of excellent software is written by individuals. It is a statement about what you are agreeing to when you install one.

And the concentration is real. The busiest publishers are not companies you have heard of. Counting by remote endpoint, the single busiest hostname in the registry carries 1,409 records, the next 1,096, then 650, 392 and 374. Stripe, Google, Microsoft and Intuit are nowhere near the top of that list.

## What the registry says about itself

This is the part I would put on a poster.

The registry is **still labelled preview**. It is a community project backed by Anthropic, GitHub, PulseMCP and Microsoft, and it **hosts metadata only, never code**. Listing implies **no code review**; the registry explicitly delegates security scanning to the package registries downstream.

Its own moderation policy tells consumers to assume minimal to no moderation. It removes illegal content, malware, spam and servers that do not function. **It states that it will not remove servers with security vulnerabilities**, and it will not remove low-quality or buggy ones either.

So "it is in the official registry" means the namespace was authenticated and the metadata is well formed. It does not mean anybody looked at the code. Reading it as an app store is the single most expensive mistake available here.

## Thirty two of the listed endpoints are somebody's laptop

The registry lets a server declare a remote endpoint. Thirty two of those endpoints point at a development tunnel: twenty six at Cloudflare quick-tunnel addresses, six at ngrok. Those are the throwaway URLs you get while testing on your own machine, and they die when you close the terminal.

I sampled twelve of them. **All twelve were dead.** The six Cloudflare tunnel names no longer resolve at all. The six ngrok names do resolve, because ngrok answers for its whole domain, but every one returns ngrok's own tunnel-not-found page when you actually connect, checked from two separate networks so it is not a local quirk.

Two of the ngrok addresses have an IP address baked into the subdomain, which is what the free tier hands out to a home connection.

The moderation policy says non-functioning servers get removed. These are still listed. The gap between a written policy and an enforced one is the whole lesson.

## The ten-second test that actually works

I tried to work out which of the tools a small business runs on have a real first-party server, and my first pass got it wrong in an instructive way.

I classified by namespace, which is what a person scanning a list would do. It produced these apparent first-party hits:

- `al.square/fiskalizimi` looked like Square the payments company. It is **square.al**, an Albanian tax and payroll tool.
- `app.seatcanvas/seatcanvas` looked like Canva. It is a seating-plan app; "seatcanvas" contains "canva".
- `ai.intuitek.the-stall` looked like Intuit. It is "Intuitek", a pay-per-call tool chassis, and its endpoint carries 239 records in the registry.
- `com.microsoft.esrp/esrp-oss-mcp-test` looked like Microsoft. The repository behind it is an individual's account and the npm package is literally named `esrp-oss-mcp-test`.

That last one deserves care rather than accusation. It may well be a Microsoft employee's work, and I am not suggesting otherwise. The point is narrower and it holds regardless: **the namespace did not tell me who published it.** A business owner scanning a list would read `com.microsoft` as Microsoft, and the only way to know better is to open the record.

**The test that does work: look at where the server actually connects.** Every genuine first-party server I verified points at the vendor's own domain.

| Server | Remote endpoint | Repository field |
|---|---|---|
| `com.stripe/mcp` | `mcp.stripe.com` | `github.com/stripe/agent-toolkit` |
| `com.cloudflare.mcp/mcp` | `docs.mcp.cloudflare.com` and others | `github.com/cloudflare/mcp-server-cloudflare` |
| `com.atlassian/atlassian-mcp-server` | `mcp.atlassian.com/v1/mcp` | `github.com/atlassian/atlassian-mcp-server` |
| `com.wix/mcp` | `mcp.wix.com/mcp` | `github.com/wix/wix-mcp` |
| `com.webflow/mcp` | `mcp.webflow.com/mcp` | `github.com/webflow/mcp-server` |
| `com.paypal.mcp/mcp` | `mcp.paypal.com/mcp` | empty |
| `com.notion/mcp` | `mcp.notion.com/mcp` | empty |
| `com.airtable/mcp` | `mcp.airtable.com/mcp` | empty |
| `app.linear/linear` | `mcp.linear.app/mcp` | empty |

Note the right-hand column. **Four of these nine leave the repository field blank**, so on those the endpoint domain is the only identifying signal there is. Check the endpoint first, always. The repository is a bonus.

## The registry is not where vendors publish

Here is the finding that changed how I would give this advice.

I took nineteen applications a small business plausibly uses, sent each one a genuine protocol handshake at the obvious address, and recorded what came back. A vendor server answers with a proper authentication challenge, which is a specific, checkable thing rather than a marketing claim. Then I checked every answering endpoint against the full registry walk.

**Live first-party server, and it is in the registry:**

Stripe, PayPal, Notion, Cloudflare, Airtable, Atlassian, Linear, Wix, Webflow.

**Live first-party server, and it is nowhere in the registry:**

HubSpot (`mcp.hubspot.com`), Xero (`mcp.xero.com`), Square (`mcp.squareup.com`), Calendly (`mcp.calendly.com`), Intercom (`mcp.intercom.com`), Pipedrive (`mcp.pipedrive.com`), Asana (`mcp.asana.com`), Canva (`mcp.canva.com`), Sentry (`mcp.sentry.dev`), Squarespace (`mcp.squarespace.com`).

Not "listed under a different name". Absent. I collected all 9,875 remote endpoint hostnames in the registry and searched them for each of those domains. Zero hits for all ten.

Cloudflare is worth a footnote here, because it caught my first version of the check. A strict hostname match reported it absent, since the registry lists `docs.mcp.cloudflare.com` and two siblings rather than the plain `mcp.cloudflare.com` I had probed. It is listed, just at different addresses. The script in the kit now falls back to the registrable domain and marks that case separately, because the alternative is a tool that quietly slanders a vendor for using a subdomain.

**No public server found:**

- **QuickBooks.** `mcp.intuit.com` exists, and this one is worth a second look. It answers 403 Forbidden to everything, from two separate networks, and its DNS record points at a host whose own name is `gatewaysimulatorser.e2e.api.a.intuit.com`. A gateway simulator in an end-to-end test environment is not a product you can connect to.
- **Mailchimp** and **WooCommerce.** The obvious hostnames do not exist at all.
- **Zoho, Zendesk, Freshworks, Twilio.** Hostnames answer, but with ordinary API errors rather than a protocol handshake.

One honest caveat on that last group, and it is the same caveat that caught me earlier. My probe tests the address you would guess. Shopify, for instance, does not answer at `mcp.shopify.com`, but Shopify's approach is a per-store endpoint rather than one central address, so "nothing at the guessable hostname" is not the same as "the vendor has not built one". Absence of evidence, as ever.

The practical consequence is simple and it is the opposite of what most guides say. **Do not start at the registry. Start at your vendor's own documentation**, then confirm the endpoint answers before you believe it. The registry is a useful cross-check and a terrible index.

## Some vendor servers want no credential at all

Squarespace was the surprise. Its server answers a handshake with no authentication whatsoever, and identifies itself as "Squarespace Domain Search". It offers exactly two tools: search the domain catalogue for a keyword, and generate business name ideas from a description. The first one returns availability, pricing, and what its own tool description calls a pre-rendered purchase link.

That is not an account integration. It is a storefront with a protocol in front of it, and the trade is different from everything else in this article. There is no token to leak, because you never issue one. What you are accepting instead is that a vendor gets to put product suggestions in front of your assistant at the moment you are deciding something.

Neither risk is worse than the other. They are just different, and it is worth knowing which one you took.

## How tightly can you actually scope it

Several of these servers publish a machine-readable description of the permissions they support, which is a rare thing to be able to check before you sign in rather than after.

Counting them is a start. Reading them is better, because the question a small business is actually asking is "can I connect this without giving it the ability to change anything."

| Vendor | Scopes | Read | Write | What that means in practice |
|---|---|---|---|---|
| Square | 49 | 26 | 23 | Paired, `ORDERS_READ` and `ORDERS_WRITE` and so on. Pick the read half. |
| Canva | 16 | 10 | 6 | Same pattern, per resource type |
| **Xero** | **9** | **4** | **0** | **Read-only by construction. See below.** |
| Airtable | 7 | 4 | 3 | Cleanly paired |
| Calendly | 2 | 1 | 1 | `mcp:scheduling:read` or `mcp:scheduling:write` |
| Linear | 2 | 1 | 1 | Literally `read` and `write` |
| Sentry | 4 | 1 | 3 | `org:read`, then `project:write`, `team:write`, `event:write` |
| Notion | 1 | 0 | 0 | A single scope named `default`. All or nothing. |
| Asana | 1 | 0 | 0 | Also `default` |
| Wix | 1 | 0 | 0 | Only `offline_access` |

Two readings of that table matter more than the rest.

**Sentry is the one to look at twice.** It offers four scopes and three of them are write. If you connect it, you are handing an agent the ability to change projects and teams, because reading is not separable from writing there in the way it is at Square.

**A zero in the scope column is not the same as no control.** Stripe, PayPal, Cloudflare, HubSpot and Webflow publish the document without listing scopes, and Pipedrive, Intercom, Atlassian and Squarespace publish no document at all. That is a statement about this one metadata file, not about the product. Stripe's own documentation describes granting an agent a restricted API key with only the permissions it needs, plus dashboard controls that configure access separately for live mode and sandbox, and session revocation. The granularity is real, it just does not live in the file my script reads.

Square is the reason that script checks two locations rather than one. It publishes two of these documents and they disagree: the one tied to the endpoint path lists nothing, the one at the domain root lists all forty nine. Reading only the first would have under-reported the vendor with the finest-grained permissions in the whole set.

### The bookkeeping server that cannot write

Xero is the useful surprise, and it is the answer to the thing every small business owner flinches at.

Its hosted server declares nine scopes. Four are the ordinary sign-in ones. The other five are `accounting.settings`, `accounting.invoices.read`, `accounting.reports.aged.read`, `accounting.reports.balancesheet.read` and `accounting.reports.profitandloss.read`. Its authorisation server is `identity.xero.com`, which is Xero's real identity system.

**There is no write scope on offer.** Not "you should choose read-only", not "read-only is available if you ask". The hosted Xero MCP server cannot be granted the ability to change your books, because Xero did not build that door. Aged receivables, balance sheet, profit and loss, invoices, all readable, none writable.

That is the correct shape for this category and I would like more vendors to copy it.

One wrinkle worth naming, because it cuts against my own advice above. Xero's developer FAQ describes its AI toolkit as a local server you run yourself, published as an npm package, and says development experience is required to use it. Read only that page and you would conclude a small business cannot use Xero this way. The hosted endpoint says otherwise, and it answered every request I sent it.

So neither the registry nor the vendor's documentation is reliable on its own. The endpoint is the thing that is actually true.

## The security record is not hypothetical

I searched the National Vulnerability Database for Model Context Protocol. **Seventy four results.**

The instructive part is not that community servers have bugs. It is where several of the serious ones are:

- **CVE-2025-34072, CVSS 9.3 critical**, published 2 July 2025. A data exfiltration flaw in **Anthropic's own deprecated Slack MCP server**, via automatic link unfurling. An agent processing untrusted content could be manipulated into producing a message containing an attacker-crafted link with sensitive data embedded in it, and Slack's own link-preview bots would then fetch that link. The data leaves through a feature nobody thinks of as an output channel.
- **CVE-2025-53109, CVSS 7.3 high**, same day. The **Filesystem reference server** allowed access to unintended files through symlinks inside its allowed directories. The sandbox did not hold its own boundary.
- **CVE-2025-53365, CVSS 8.7 high**, 4 July 2025. A crash in the **official MCP Python SDK** triggered by a deliberately malformed client session.

Reference implementations, an official SDK, and an Anthropic-published server. This is young software written quickly, which is what you would expect, and it is the correct baseline for judging a project written by one person in a weekend.

And these are not obscure packages. The Filesystem reference server that carried the symlink escape was downloaded 621,657 times from npm in the week ending 21 August 2026, more than a year after the advisory. Patched versions exist. Whether the running copies are patched is a different question, and not one the registry will answer for you.

The Claude Code documentation states the trust position plainly: verify you trust each server before connecting it, and servers that fetch external content can expose you to prompt injection. That is not boilerplate. An MCP server that reads a web page, an inbox or a ticket queue is a path from whoever wrote that content into your agent's instructions.

## The cost nobody mentions

Every MCP server you connect used to consume context whether you used it or not, because all its tool definitions loaded at session start.

That changed. **Tool search is on by default now**: only tool names and server instructions load up front, and full definitions are fetched when the model needs them. Adding servers has much less impact than it did, and there is no fixed per-server tool cap. The practical limit is your context budget.

Two caveats. Tool search is not supported on Microsoft Foundry deployments hosted on Azure, which reject it server-side and force tools to load up front. And Anthropic's own cost guidance still recommends preferring a CLI tool where one exists, because a command-line tool adds no per-tool listing to the context at all.

That last point is the one small businesses should hear. If the job is "check my site is up" or "pull yesterday's orders", a scheduled script is cheaper, more reliable and easier to reason about than a server that runs continuously with a token in its environment.

## Three businesses, three different answers

**A two-person online shop.** Payments in Stripe, storefront on Squarespace, books in Xero. Two servers here, not one. Stripe so you can ask questions about yesterday's charges without exporting a spreadsheet, and Xero, which I would normally tell you to leave until last and instead recommend without much hesitation, because its hosted server has no write scope at all. An agent connected to it can read your profit and loss and your aged receivables and cannot alter a single figure. Squarespace's server sells domains and will not touch your site.

**A twelve-person services firm.** Deals in Pipedrive or HubSpot, support in Intercom, docs in Notion, scheduling in Calendly. Every one of those has a live first-party server and only Notion is in the registry, so a person searching the official index would conclude the opposite and go looking at community projects instead. Start with Notion, because documentation is the lowest-stakes thing you own and it is where an assistant helps most. Add the CRM second, read-only, and only if you can say what question you keep failing to answer.

**A forty-person shop with an engineering team.** Sentry, Linear, Atlassian and Cloudflare all publish servers, and you have somebody who can read a repository and set a scope properly. This is the only one of the three where a community server is a defensible risk, and it is defensible because a person there can evaluate it. Even then: not for anything holding customer or financial data.

The pattern across all three is the same. The right number is small, the right source is the vendor, and the right default is read-only.

## So what should a small business actually do

**Install nothing for the first month.** Use the assistant without tools and find out where you actually hit a wall. Most people discover the wall is somewhere they did not expect, and half the time a file and a good prompt solve it.

**When you do install, take only first-party, and find it at the vendor rather than in the registry.** Search your vendor's own documentation for MCP. If they have one, they document it. Then confirm the endpoint answers before you believe a third-party list that says it does.

**Prefer a remote server over one that runs on your machine.** A remote server on the vendor's domain authenticates with OAuth and never has a long-lived secret sitting in a config file on your laptop. A local server is a program you downloaded, running with your credentials in its environment.

**Use read-only credentials wherever the vendor offers them.** Upgrade to write access for one specific job, and downgrade afterwards. This is the single highest-value habit and it costs nothing.

**For everything else, ask whether a CLI or a scheduled script would do.** Usually it would.

**If you are tempted by a community server for something important, do not.** If you are tempted by one for something unimportant, read the repository first, check when it was last updated, and give it a token scoped to nothing you would mind losing.

## Installing without a developer

Three paths, in increasing order of fiddliness.

**Claude Desktop connectors.** The least technical route. You are clicking a button and completing an OAuth sign-in, which is the same flow as connecting any app to any other app.

**Claude Code, one command per server.** `claude mcp add` writes to local scope by default, which means only you and only this project. `--scope user` makes it available everywhere for you; `--scope project` writes a `.mcp.json` that your whole team gets, and which every teammate has to approve before it connects. That approval step is deliberate and you should not route around it.

**A config file by hand.** Only if you have a reason.

Whichever you use, `claude mcp list` and `claude mcp get <name>` tell you what is connected and what is pending. Check it. A server that failed to connect is not the same as a server that is working, and the difference is not always obvious from the conversation.

## When MCP is the wrong answer

- **The vendor has no first-party server.** Which, for small business software, is still a good number of them.
- **A CLI already exists.** Cheaper, simpler, no persistent process.
- **The task runs once a day on a schedule.** That is a cron job, not a protocol.
- **The data is sensitive and the server is not the vendor's.** No.
- **You cannot answer "what token does this have and what can it do with it."** Stop until you can.

## The kit

Three files, free, no signup. The third is the probe I used for this article, so you can check your own vendors rather than trusting my list six months from now.

| File | What it is |
|---|---|
| [mcp-small-business-starter.md](/downloads/mcp-small-business-starter.md) | What MCP is without the jargon, the do-you-even-need-it test, the short install list, the three install paths and the context cost |
| [mcp-server-vetting-checklist.md](/downloads/mcp-server-vetting-checklist.md) | The ten-second first-party test, the full vetting checklist, credential rules, and what to do when a server misbehaves |
| [check-mcp-endpoints.mjs](/downloads/check-mcp-endpoints.mjs) | The probe. Give it a list of vendors and it reports which run a real server, and how tightly each one lets you scope the grant |

<!-- The blocks below are verbatim copies of the files in src/downloads/. Regenerate with scripts/embed-mcp-kit.mjs after editing either side. -->

### The starter

<details>
  <summary><strong>Expand <code>mcp-small-business-starter.md</code></strong></summary>

<!-- MCPKIT-EMBED:mcp-small-business-starter -->

````markdown
# MCP for a Small Business: The Starter

What the Model Context Protocol is without the jargon, whether you need it at all, the short list
worth installing, and the three ways to install it.

Version 1.1, 2026-08-22. Every figure measured that day.
Free to copy, fork and reuse. Attribution appreciated, not required.
Source article: https://jwatte.com/blog/mcp-servers-for-small-business/

---

## 0. What it is, in plain terms

An AI assistant on its own can only read what you paste into it. **MCP is a standard way to give
it tools**, so it can look something up or do something in another system without you copying and
pasting.

A **server** is a small program that offers a set of tools. A **client** is the assistant that
calls them. The protocol is just the agreement between them, so anybody's server works with
anybody's assistant.

That is the whole idea. Everything else is detail.

Four things worth knowing before you read anything else about it:

* **It is young.** The specification was substantially rewritten on 28 July 2026, which
  deprecated several features every older tutorial describes. If a guide is more than a few
  months old, it is describing an older protocol.
* **The official registry lists 24,240 servers and reviews none of them.** It hosts metadata, not
  code, and its own moderation policy says it will not remove a server for having a security
  vulnerability.
* **The registry is also not where vendors publish.** Of nineteen live first-party servers found
  by asking the vendors directly, ten were absent from the registry entirely. Start at your
  vendor's documentation, not at the index.
* **A server runs with whatever credentials you give it.** That is the trade. Everything in the
  vetting checklist follows from that one sentence.

---

## 1. Do you even need one? The honest test

Answer these before installing anything.

```
[ ] Have I used the assistant for a month WITHOUT tools and hit a specific wall?
[ ] Can I name the wall in one sentence?
[ ] Is the thing behind that wall a system I pay a vendor for?
[ ] Does that vendor publish its own MCP server? (Check the vendor's docs, not a list.)
[ ] Would a scheduled script or a CLI tool solve it just as well?
```

**If you cannot answer the first two, stop.** Installing tools to find a use for them is how
people end up with nine servers, a slower assistant and a credential inventory they cannot
recite.

**If the answer to the last one is yes, do that instead.** Anthropic's own cost guidance
recommends preferring a CLI tool where one exists, because a command-line tool adds nothing to
the assistant's context, while a server adds at least its tool names.

---

## 2. The short list

Verified on 22 August 2026 by sending a real protocol handshake to each vendor's own address, not
by reading a directory. Re-check with `check-mcp-endpoints.mjs` before you rely on it.

### Runs a first-party server, and is in the official registry

| Tool | Endpoint | Worth it if |
|---|---|---|
| Stripe | `mcp.stripe.com` | You take payments and want to ask questions about them |
| PayPal | `mcp.paypal.com` | Same, on PayPal |
| Notion | `mcp.notion.com` | Your documentation or CRM lives in Notion |
| Cloudflare | `mcp.cloudflare.com` | You manage your own DNS or hosting |
| Airtable | `mcp.airtable.com` | Airtable is your operational database |
| Atlassian | `mcp.atlassian.com` | Jira or Confluence is where the work lives |
| Linear | `mcp.linear.app` | You track issues in Linear |
| Wix | `mcp.wix.com` | Your site is on Wix |
| Webflow | `mcp.webflow.com` | Your site is on Webflow |

### Runs a first-party server that the registry does NOT list

These are real, live and published by the vendor. Searching the official registry will not find
them, which is exactly why the registry is the wrong place to start.

| Tool | Endpoint |
|---|---|
| Square | `mcp.squareup.com` |
| Canva | `mcp.canva.com` |
| Xero | `mcp.xero.com` |
| Sentry | `mcp.sentry.dev` |
| Calendly | `mcp.calendly.com` |
| Asana | `mcp.asana.com` |
| HubSpot | `mcp.hubspot.com/anthropic` |
| Pipedrive | `mcp.pipedrive.com` |
| Intercom | `mcp.intercom.com` |
| Squarespace | `mcp.squarespace.com` |

### Can you connect it WITHOUT granting write access?

The real question. These are the permission scopes each server declares, read on 22 August 2026.

| Vendor | Scopes | Read | Write | Notes |
|---|---|---|---|---|
| Square | 49 | 26 | 23 | Paired per resource: take `ORDERS_READ`, leave `ORDERS_WRITE` |
| Canva | 16 | 10 | 6 | Same pattern |
| **Xero** | **9** | **4** | **0** | **No write scope exists. See below.** |
| Airtable | 7 | 4 | 3 | Cleanly paired |
| Calendly | 2 | 1 | 1 | `mcp:scheduling:read` / `:write` |
| Linear | 2 | 1 | 1 | Literally `read` and `write` |
| Sentry | 4 | 1 | 3 | `org:read`, then three write scopes. Look twice. |
| Notion | 1 | 0 | 0 | One scope named `default`. All or nothing. |
| Asana | 1 | 0 | 0 | Also `default` |
| Wix | 1 | 0 | 0 | Only `offline_access` |
| Stripe, PayPal, Cloudflare, HubSpot, Webflow | 0 | | | Document published, no scopes in it |
| Pipedrive, Intercom, Atlassian, Squarespace | | | | No document |

**A blank row is not "no control".** It means this one metadata file is empty. Stripe, for
instance, scopes through restricted API keys plus dashboard controls set separately for live mode
and sandbox. Read the vendor's own permission documentation before concluding anything.

**Sentry is the one to look at twice.** Three of its four scopes are write scopes.

**If you check this yourself, fetch both locations.** Square publishes two of these documents and
they disagree: the one tied to the endpoint path lists nothing, the one at the domain root lists
all forty nine. `check-mcp-endpoints.mjs` checks both and takes the richer one.

### Xero: the bookkeeping server that cannot write

Worth its own heading, because bookkeeping is the thing everyone is right to be nervous about.

Xero's hosted server offers nine scopes. Four are ordinary sign-in. The rest are
`accounting.settings`, `accounting.invoices.read`, `accounting.reports.aged.read`,
`accounting.reports.balancesheet.read` and `accounting.reports.profitandloss.read`. Its
authorisation server is `identity.xero.com`.

**There is no write scope on offer at all.** Not "choose read-only", not "read-only if you ask".
An agent connected to it can read your profit and loss, balance sheet, aged receivables and
invoices, and cannot change any of them, because Xero did not build that door.

One wrinkle: Xero's developer FAQ describes a *local* server you run yourself and says
development experience is required. Read only that page and you would conclude a small business
cannot use Xero this way. The hosted endpoint says otherwise. Neither the registry nor the
vendor's docs is reliable alone; the endpoint is what is actually true.

### No public server found, as of 22 August 2026

QuickBooks, Mailchimp, WooCommerce, Zoho, Zendesk, Freshworks, Twilio.

Two notes on that list. `mcp.intuit.com` does exist, but it refuses every request and its DNS
record points at a host named `gatewaysimulatorser.e2e.api.a.intuit.com`, which is a test
environment rather than a product. And "no server found" means nothing answered at the address
you would guess. Shopify, for example, uses a per-store endpoint rather than one central address,
so a hostname probe reads as absent when it is not.

Community servers exist for most of the missing ones. **Think hard before using one for anything
holding customer or financial data.** A community accounting server is a program written by a
stranger, which you would be handing a token that can read every invoice you have ever issued,
listed in a registry that has stated in writing that it will not remove it if it turns out to be
vulnerable.

Some of those projects are good. You have no practical way to tell which from the outside.

---

## 3. Remote beats local, almost always

Two kinds of server:

| | Remote | Local |
|---|---|---|
| Runs on | The vendor's servers | Your machine |
| Authenticates with | OAuth, in a browser | A secret you paste into a config file |
| You are trusting | The vendor you already pay | Whoever wrote the code, plus their dependencies |
| Secret sitting on your laptop | No | Yes, usually a long-lived one |

**Prefer remote.** Every server in the short list above is remote, on the vendor's own domain.
You sign in the same way you sign in to anything else, and there is no API key living in a text
file on your laptop until you leave the company.

Use local servers for things that must touch your own machine, such as a filesystem tool, and
understand that you are running somebody's code.

### The third kind: servers that want nothing from you

Squarespace's server takes no credential at all. It has two tools, both about searching for a
domain to buy, and one of them returns a purchase link. That is a storefront with a protocol in
front of it.

There is no token to leak, which is genuinely safer in one dimension. What you accept instead is
a vendor putting product suggestions in front of your assistant while you are deciding something.
Neither risk is worse. Just know which one you took.

---

## 4. Installing, three ways

### The least technical: Claude Desktop connectors

Click, sign in through the vendor's normal OAuth screen, done. Same flow as connecting any app to
any other app. If this covers what you need, stop here.

### Claude Code, one command

```bash
claude mcp add <name> --transport http <url>
```

Scopes decide who gets it:

| Scope | Flag | Who sees it |
|---|---|---|
| Local | default | Only you, only this project |
| User | `--scope user` | Only you, everywhere |
| Project | `--scope project` | Everyone on the team, via a committed `.mcp.json` |

**Project scope requires each teammate to approve the server before it connects.** That approval
step is deliberate. Do not look for a way around it; it is the only thing standing between a
cloned repository and a server you never agreed to.

Check your work:

```bash
claude mcp list
claude mcp get <name>
```

A server that failed to connect is not the same as one that is working, and the conversation will
not always make that obvious.

### By hand

Editing the config file directly. Only if you have a reason.

---

## 5. What it costs you

**Context, less than it used to.** Tool definitions used to load at session start for every
connected server. Tool search is now on by default: only tool names and server instructions load
up front, and full definitions are fetched when needed. Adding servers is cheaper than it was.

Two caveats: tool search is not supported on Microsoft Foundry deployments hosted on Azure, which
force tools to load up front; and a CLI tool still costs less than any server, because it adds
nothing at all.

**Attention.** Every server is a thing to keep updated, a credential to rotate and a decision to
revisit. Three servers is a Saturday morning twice a year. Twelve is a job.

---

## 6. A sensible first ninety days

**Month one.** No servers. Use the assistant, notice where you actually get stuck, write it down.

**Month two.** Install exactly one, first-party, remote, read-only if the vendor offers it. Use it
for a month before adding anything else.

**Month three.** Add a second only if you can say what the first one saved you. If you cannot,
remove the first one instead.

**Every six months, ongoing.** Read your own list. For each server: do I still use it, is the
credential still scoped correctly, has the project been updated this year. Remove anything that
fails.

That cadence sounds slow. It is the difference between a tool you understand and a pile of
software with tokens in it.

---

## 7. Three shapes of business, three answers

**Two-person online shop.** Stripe, so you can ask about yesterday's charges without exporting a
spreadsheet, and Xero, which normally I would tell you to leave until last and here recommend
without much hesitation, because its hosted server offers no write scope at all.

**Twelve-person services firm.** Pipedrive or HubSpot for deals, Intercom for support, Notion for
docs, Calendly for scheduling. All four run first-party servers and only Notion is in the
registry, so an owner searching the official index would wrongly conclude none exist. Start with
Notion, lowest stakes and highest payoff. Add the CRM second, read-only.

**Forty-person shop with engineers.** Sentry, Linear, Atlassian, Cloudflare. This is the only one
of the three where a community server is a defensible risk, because somebody there can actually
read the code. Even then, not for anything holding customer or financial data.

The pattern is the same in all three: small number, vendor source, read-only default.

---

Companion files at https://jwatte.com/downloads/

* `mcp-server-vetting-checklist.md` : the ten-second first-party test, the full checklist, and what to do when a server misbehaves
* `check-mcp-endpoints.mjs` : the probe used to produce the tables above, so you can re-run it yourself

Written by J.A. Watte. https://jwatte.com
````

</details>

### The vetting checklist

<details>
  <summary><strong>Expand <code>mcp-server-vetting-checklist.md</code></strong></summary>

<!-- MCPKIT-EMBED:mcp-server-vetting-checklist -->

````markdown
# MCP Server Vetting Checklist

How to tell a vendor's own server from a stranger's in ten seconds, what to check before you
install anything, how to scope the credential, and what to do when something looks wrong.

Companion to `mcp-small-business-starter.md` and `check-mcp-endpoints.mjs`. Version 1.1, 2026-08-22.
Source article: https://jwatte.com/blog/mcp-servers-for-small-business/

---

## 0. The one thing to internalise

**An MCP server is a program you are running with your credentials.** Not a plugin, not an
integration, not an app-store listing. A program, with a token, acting on your behalf, that you
usually did not write and cannot read.

Everything below follows from that.

The official registry does not change it. Listing there means the namespace was authenticated and
the metadata parsed. It hosts metadata, never code, performs no code review, and its own
moderation policy says it will not remove a server for having a security vulnerability. Reading
the registry as an app store is the expensive mistake.

---

## 1. The ten-second test

Look at exactly two things, wherever you found the server.

```
REMOTE ENDPOINT   Is the URL on the vendor's own domain?
REPOSITORY        Is it in the vendor's own GitHub organisation?
```

**Both yes:** it is the vendor's. Proceed to section 2.
**Both no:** it is somebody else's, whatever the name says. Section 4.
**Mixed:** treat as somebody else's until you can explain the mismatch.

The endpoint is the field that matters. Of nine registry-listed first-party servers checked on
22 August 2026, four left the repository field empty, so on those the domain is the only
identifying signal there is.

### Do not use the registry as your index

Being absent from the official registry says nothing about a vendor. Ten companies running live
production MCP servers on 22 August 2026 were not in it at all: HubSpot, Xero, Square, Calendly,
Intercom, Pipedrive, Asana, Canva, Sentry and Squarespace.

**Search the vendor's own documentation first.** Then confirm the endpoint answers, with
`check-mcp-endpoints.mjs` or by hand. The registry is a cross-check, and a poor index.

### Why the name is not enough

Real examples from the registry, all checked on 22 August 2026:

| Looks like | Actually is |
|---|---|
| `al.square/fiskalizimi` | square.al, an Albanian tax and payroll tool. Not Square. |
| `app.seatcanvas/seatcanvas` | A seating-plan app. "seatcanvas" contains "canva". Not Canva. |
| `ai.intuitek.the-stall` | "Intuitek", a pay-per-call tool chassis. Not Intuit. |
| `com.microsoft.esrp/esrp-oss-mcp-test` | Repository is an individual's account; the npm package is named `...-test`. |

None of these are necessarily doing anything wrong, and the last one may well be an employee's
legitimate work. That is the point: **you cannot tell from the namespace, and the namespace is
what a list shows you.**

Known-good examples, for calibration. Note how many have no repository at all:

```
com.stripe/mcp                     -> mcp.stripe.com        + github.com/stripe/agent-toolkit
com.cloudflare.mcp/mcp             -> docs.mcp.cloudflare.com and siblings
                                                             + github.com/cloudflare/mcp-server-cloudflare
com.atlassian/atlassian-mcp-server -> mcp.atlassian.com/v1   + github.com/atlassian/atlassian-mcp-server
com.wix/mcp                        -> mcp.wix.com            + github.com/wix/wix-mcp
com.webflow/mcp                    -> mcp.webflow.com        + github.com/webflow/mcp-server
com.paypal.mcp/mcp                 -> mcp.paypal.com         (no repository field)
com.notion/mcp                     -> mcp.notion.com         (no repository field)
com.airtable/mcp                   -> mcp.airtable.com       (no repository field)
app.linear/linear                  -> mcp.linear.app         (no repository field)
```

Cloudflare is the reason to compare domains rather than exact hostnames. It publishes under
`docs.mcp.cloudflare.com` and two siblings, not the bare `mcp.cloudflare.com` you would guess.

---

## 2. Before installing a first-party server

Even the vendor's own server deserves five minutes.

```
[ ] Is it remote (OAuth) rather than local (a secret in a file)? Prefer remote.
[ ] What scope does the OAuth consent screen actually ask for? Read it, do not click through.
[ ] Does the vendor offer read-only credentials? Use them.
[ ] Read its permission scopes, do not just count them. Fetch
    /.well-known/oauth-protected-resource at BOTH the endpoint path and the domain
    root. Square publishes two of these and they disagree: 0 at the path, 49 at the
    root. Then ask the only question that matters: is there a read scope I can take
    WITHOUT the matching write scope?
      - Square 26 read / 23 write, Canva 10/6, Airtable 4/3: yes, take the read half.
      - Xero 4 read / 0 write: no write scope exists at all. Best case.
      - Sentry 1 read / 3 write: mostly write. Look twice before connecting it.
      - Notion, Asana: a single scope named `default`. All or nothing.
[ ] An empty scope list is NOT "no control". Stripe scopes through restricted API
    keys and dashboard settings instead. Check the vendor's permission docs.
[ ] Which of my data can this reach? Write the answer down in one sentence.
[ ] What is the worst case if this token leaks? If you cannot say, do not install it yet.
[ ] Am I installing at local scope, or pushing it to my whole team?
```

**The read-only habit is the highest-value item on this list and it costs nothing.** Grant write
access for one specific job, then take it away again.

---

## 3. Before installing a community server

If you have decided to anyway, this is the minimum.

```
[ ] Open the repository. Does it exist, and is it public?
[ ] When was the last commit? Older than a year is abandonware.
[ ] How many people have contributed? One person who stopped is a risk.
[ ] Read the tool descriptions in the source. Those strings go into the model's context and
    are exactly where a tool-poisoning attack would live.
[ ] Does it phone anywhere other than the service it claims to talk to?
[ ] Check the package registry for the published artefact. Does the name match the repository?
[ ] Search the CVE databases for the package name.
[ ] Pin a version. Do not float on latest for something holding a credential.
[ ] Give it a token scoped to the least it can possibly do.
[ ] Would I be comfortable if this token appeared in a public paste tomorrow?
```

**If the answer to the last one is no, and you cannot scope the token down further, do not
install it.** That is the whole decision.

### Never for these, regardless

- Accounting and bookkeeping systems
- Payroll
- Anything holding customer payment details
- Anything holding health, immigration or legal information
- Your primary email account, with write access
- Production databases, with write access

For those categories, use the vendor's own server or nothing.

---

## 4. The threat you are actually defending against

Not "the author is malicious", usually. Three more likely shapes:

**The code has a hole.** This is young software. A search of the National Vulnerability Database
for "Model Context Protocol" returns 74 results, and several of the serious ones are in official
code rather than community projects: a critical data-exfiltration flaw in Anthropic's own
deprecated Slack server, a high-severity symlink escape in the reference Filesystem server, and a
high-severity crash in the official Python SDK, all disclosed in early July 2025. If the
reference implementations had holes, a weekend project certainly can.

**Tool descriptions are model instructions.** The text describing what a tool does is fed to the
model. A server can therefore influence the assistant's behaviour through a field nobody reads
during install. Read those strings before you trust a server with anything.

**Untrusted content becomes instructions.** Any server that fetches a web page, an inbox, a
ticket queue or a document is a path from whoever wrote that content into your agent. The Claude
Code documentation says this directly: verify you trust each server, and servers that fetch
external content can expose you to prompt injection.

**The exfiltration channel is rarely the obvious one.** In the Slack case the data left through
link previews: the agent was induced to write a message containing a crafted URL with data in it,
and Slack's own preview bots fetched the URL. Nobody thinks of a link preview as an output.

---

## 5. Credential rules

```
1. Read-only by default. Write access is a temporary, specific grant.
2. One credential per server. Never reuse a token across two servers.
3. Prefer OAuth over a static key, because you can revoke it from the vendor's side.
4. Never paste a key into a file that a repository might contain. Check your .gitignore.
5. Write down, somewhere you will find it: what each token is, what it can do, when to rotate.
6. Rotate anything a server has held when you remove the server.
7. If a laptop with local servers is lost, rotate every credential on it. All of them.
```

Point five is the one that decays. A list of tokens you cannot explain is the same as no list.

---

## 6. Ongoing, twice a year

```
[ ] Run `claude mcp list`. Is anything connected that you forgot about?
[ ] For each server: still used? If not, remove it and rotate its credential.
[ ] For each community server: last commit date, any new advisories?
[ ] For each token: still scoped to the minimum? Still needed at write level?
[ ] Re-read your own one-sentence note about what each server can reach. Still true?
```

Twice a year, thirty minutes. Put it in the calendar or it does not happen.

---

## 7. When something looks wrong

The signals, in the order you will notice them:

* The assistant does something you did not ask for, in a system you did not mention.
* It references data from a source that was not part of the task.
* A tool call fails in a way that mentions an unfamiliar host.
* Your spend jumps with no change in your usage.
* The vendor emails you about an API call you did not make.

The response:

```
STEP 1  Disconnect the server. Do not investigate first.
STEP 2  Revoke its credential at the vendor, not just in your config.
STEP 3  Write down what happened, with times, before you forget.
STEP 4  Check the vendor's audit log for what the token actually did.
STEP 5  Only then work out whether it was the server, the content it read, or a coincidence.
STEP 6  If it was a community server, open an issue with what you saw. Others are running it.
```

Disconnecting first costs you almost nothing and preserves every option. Investigating first
while a suspect program keeps running is how a small problem becomes a long afternoon.

---

## 8. The summary, if you read nothing else

* An MCP server is a program running with your credentials.
* The registry lists 24,240 of them and reviews none.
* Roughly seventy percent are published under an individual's GitHub account.
* The registry is also missing ten major vendors' real servers, so start at the vendor's docs.
* Check the remote endpoint's domain. Nothing else reliably identifies a publisher, and four of
  nine verified first-party records had no repository field at all.
* First-party or nothing, for anything that matters.
* Read-only by default, one credential per server, rotate on removal.
* If a CLI tool would do the job, use that instead.

---

Companion file at https://jwatte.com/downloads/

* `mcp-small-business-starter.md` : what it is, whether you need it, the short list and the install paths
* `check-mcp-endpoints.mjs` : asks each vendor directly whether it runs a server, and how tightly you can scope it

Written by J.A. Watte. https://jwatte.com
````

</details>

### The probe

<details>
  <summary><strong>Expand <code>check-mcp-endpoints.mjs</code></strong></summary>

<!-- MCPKIT-EMBED:check-mcp-endpoints -->

````javascript
#!/usr/bin/env node
/*
 * check-mcp-endpoints.mjs
 *
 * Ask a vendor directly whether it runs an MCP server, instead of trusting a list.
 *
 * For each vendor it does three things:
 *   1. Sends a real MCP `initialize` request over Streamable HTTP.
 *   2. Reads the RFC 9728 protected-resource document, which says how many
 *      permission scopes the server will let you pick from.
 *   3. Checks whether the endpoint appears anywhere in the official registry.
 *
 * Step 3 is the interesting one. When I ran this on 22 August 2026, ten vendors
 * with live production servers were absent from the registry entirely: HubSpot,
 * Xero, Square, Calendly, Intercom, Pipedrive, Asana, Canva, Sentry and
 * Squarespace. The registry is a cross-check, not an index.
 *
 * Nothing here authenticates. No token is sent, none is needed, and the script
 * cannot touch your data even if you point it at a server you own.
 *
 * Usage:
 *   node check-mcp-endpoints.mjs                  # the built-in vendor list
 *   node check-mcp-endpoints.mjs --add acme=https://mcp.acme.com/mcp
 *   node check-mcp-endpoints.mjs --only stripe,xero
 *   node check-mcp-endpoints.mjs --registry       # also cross-check the registry (slow, ~800 calls)
 *   node check-mcp-endpoints.mjs --json           # machine-readable output
 *
 * Requires Node 18 or later. No dependencies.
 *
 * Companion to https://jwatte.com/blog/mcp-servers-for-small-business/
 * Free to copy, fork and reuse.
 */

const UA = 'mcp-endpoint-check (+https://jwatte.com)';
const TIMEOUT_MS = 15000;

// The address you would guess for each vendor. Guessing is the point: if a
// business owner cannot find it in ten seconds, the vendor has not published it
// anywhere useful. Add your own with --add.
const VENDORS = {
  stripe: 'https://mcp.stripe.com',
  paypal: 'https://mcp.paypal.com/mcp',
  square: 'https://mcp.squareup.com/mcp',
  notion: 'https://mcp.notion.com/mcp',
  airtable: 'https://mcp.airtable.com/mcp',
  cloudflare: 'https://mcp.cloudflare.com/mcp',
  hubspot: 'https://mcp.hubspot.com/anthropic',
  xero: 'https://mcp.xero.com/mcp',
  pipedrive: 'https://mcp.pipedrive.com/mcp',
  intercom: 'https://mcp.intercom.com/mcp',
  calendly: 'https://mcp.calendly.com/',
  asana: 'https://mcp.asana.com/sse',
  atlassian: 'https://mcp.atlassian.com/v1/mcp',
  linear: 'https://mcp.linear.app/mcp',
  canva: 'https://mcp.canva.com/mcp',
  sentry: 'https://mcp.sentry.dev/mcp',
  wix: 'https://mcp.wix.com/mcp',
  webflow: 'https://mcp.webflow.com/sse',
  squarespace: 'https://mcp.squarespace.com/mcp',
  quickbooks: 'https://mcp.intuit.com/mcp',
  zendesk: 'https://mcp.zendesk.com/mcp',
  twilio: 'https://mcp.twilio.com/mcp',
  mailchimp: 'https://mcp.mailchimp.com/mcp',
  shopify: 'https://mcp.shopify.com/mcp',
};

const argv = process.argv.slice(2);
const flag = (name) => argv.includes(`--${name}`);
const value = (name) => {
  const i = argv.indexOf(`--${name}`);
  return i === -1 ? null : argv[i + 1];
};

const targets = { ...VENDORS };
for (let i = 0; i < argv.length; i++) {
  if (argv[i] !== '--add') continue;
  const pair = argv[i + 1] || '';
  const eq = pair.indexOf('=');
  if (eq === -1) { console.error(`--add needs name=url, got "${pair}"`); process.exit(2); }
  targets[pair.slice(0, eq)] = pair.slice(eq + 1);
}
const only = (value('only') || '').split(',').map((s) => s.trim()).filter(Boolean);
const names = only.length ? only.filter((n) => targets[n]) : Object.keys(targets);
if (only.length && names.length !== only.length) {
  const missing = only.filter((n) => !targets[n]);
  console.error(`unknown vendor(s): ${missing.join(', ')}`);
  process.exit(2);
}

const INIT = {
  jsonrpc: '2.0',
  id: 1,
  method: 'initialize',
  params: {
    protocolVersion: '2025-06-18',
    capabilities: {},
    clientInfo: { name: 'mcp-endpoint-check', version: '1.0' },
  },
};

async function handshake(url) {
  try {
    const r = await fetch(url, {
      method: 'POST',
      headers: {
        'content-type': 'application/json',
        accept: 'application/json, text/event-stream',
        'user-agent': UA,
      },
      body: JSON.stringify(INIT),
      redirect: 'follow',
      signal: AbortSignal.timeout(TIMEOUT_MS),
    });
    const auth = r.headers.get('www-authenticate') || '';
    const text = (await r.text()).slice(0, 4000);

    // A 200 with a protocolVersion means an open server: it wants no credential.
    if (r.status === 200 && text.includes('protocolVersion')) {
      let serverName = '';
      try { serverName = JSON.parse(text.match(/\{[\s\S]*\}/)[0]).result?.serverInfo?.name || ''; } catch {}
      return { state: 'open', status: r.status, note: serverName || 'answered without authentication' };
    }
    // A 401 carrying a Bearer challenge is the normal, healthy answer.
    if (r.status === 401 && /bearer/i.test(auth)) {
      return { state: 'live', status: r.status, note: 'OAuth challenge' };
    }
    if (r.status === 401) return { state: 'live', status: r.status, note: 'authentication required' };
    if (r.status === 403) return { state: 'blocked', status: r.status, note: 'refused this request' };
    if (r.status === 404) return { state: 'none', status: r.status, note: 'nothing at this address' };
    return { state: 'unclear', status: r.status, note: text.slice(0, 60).replace(/\s+/g, ' ') };
  } catch (e) {
    const msg = String(e.message || e);
    // A name that does not resolve and a name that refuses a connection look the
    // same from here. Both mean you cannot use it, which is the answer you needed.
    return { state: 'none', status: 0, note: /timeout|abort/i.test(msg) ? 'no answer in time' : 'did not connect' };
  }
}

async function scopes(url) {
  const base = new URL(url);
  // Both locations, not the first that answers. Square publishes two of these
  // documents and they disagree: the path-specific one lists nothing, the one at
  // the root lists 49 scopes. Stopping at the first hit would have under-reported
  // the vendor that offers the finest-grained permissions of the lot.
  const paths = [
    '/.well-known/oauth-protected-resource' + base.pathname.replace(/\/$/, ''),
    '/.well-known/oauth-protected-resource',
  ];
  const found = [];
  for (const p of paths) {
    try {
      const r = await fetch(base.origin + p, {
        headers: { accept: 'application/json', 'user-agent': UA },
        signal: AbortSignal.timeout(TIMEOUT_MS),
      });
      if (r.status !== 200) continue;
      const j = await r.json();
      found.push({ path: p, resource: j.resource || '', count: (j.scopes_supported || []).length,
        scopes: j.scopes_supported || [], authz: (j.authorization_servers || [])[0] || '' });
    } catch { /* try the next path */ }
  }
  if (!found.length) return null;
  const best = found.reduce((a, b) => (b.count > a.count ? b : a));
  const disagree = found.length > 1 && found.some((f) => f.count !== found[0].count);
  // Counting scopes answers the wrong question. What a business wants to know is
  // whether it can connect this thing without granting the power to change data.
  // Classifying by name is rough, and deliberately so: treat it as a prompt to go
  // read the actual strings, which --json prints.
  const list = best.scopes || [];
  const read = list.filter((x) => /(^|[._:-])(read|view|readonly|read_only)([._:-]|$)/i.test(x)).length;
  const write = list.filter((x) => /(write|manage|create|update|delete|admin|full)/i.test(x)).length;
  return { resource: best.resource, count: best.count, disagree, list, read, write, authz: best.authz };
}

// Walking the whole registry costs ~800 requests, so it is opt-in. It collects
// every remote endpoint hostname, which is the only way to prove absence: the
// registry's keyword search will not find a server whose name does not match.
async function registryHosts() {
  const hosts = new Set();
  let cursor = '', pages = 0;
  process.stderr.write('  walking the registry');
  while (true) {
    // version=latest returns one record per server instead of every published
    // version, which cuts this from 794 requests to 243 (about 11 seconds). It
    // yields a slightly smaller hostname set than a full walk (9,454 vs 9,875 on
    // 22 Aug 2026) because retired endpoints from older versions drop out. That
    // makes this the stricter test for "listed today", and it returns the same
    // ten absent vendors either way.
    const url = 'https://registry.modelcontextprotocol.io/v0/servers?limit=100&version=latest'
      + (cursor ? `&cursor=${encodeURIComponent(cursor)}` : '');
    let j;
    try {
      const r = await fetch(url, { headers: { accept: 'application/json', 'user-agent': UA }, signal: AbortSignal.timeout(30000) });
      j = await r.json();
    } catch { break; }
    const rows = j.servers || [];
    if (!rows.length) break;
    pages++;
    if (pages % 100 === 0) process.stderr.write('.');
    for (const row of rows) {
      for (const rm of row.server?.remotes || []) {
        try { hosts.add(new URL(rm.url).hostname.toLowerCase()); } catch {}
      }
    }
    cursor = j.metadata?.nextCursor || j.metadata?.next_cursor || '';
    if (!cursor) break;
  }
  process.stderr.write(` ${pages} pages, ${hosts.size} hostnames\n`);
  return hosts;
}

const listed = flag('registry') ? await registryHosts() : null;

const results = [];
for (const name of names) {
  const url = targets[name];
  const hs = await handshake(url);
  const sc = (hs.state === 'live' || hs.state === 'open') ? await scopes(url) : null;
  let inRegistry = null, viaSibling = false;
  if (listed) {
    const host = (() => { try { return new URL(url).hostname.toLowerCase(); } catch { return ''; } })();
    if (host) {
      inRegistry = listed.has(host);
      // Exact-hostname matching alone is too strict and will mislabel a vendor.
      // Cloudflare registers docs.mcp.cloudflare.com and two siblings, but not the
      // bare mcp.cloudflare.com this script probes, so a strict match reported a
      // listed vendor as absent. Fall back to the registrable domain.
      if (!inRegistry) {
        const domain = host.split('.').slice(-2).join('.');
        for (const h of listed) {
          if (h === domain || h.endsWith('.' + domain)) { inRegistry = true; viaSibling = true; break; }
        }
      }
    }
  }
  results.push({ vendor: name, url, ...hs, scopes: sc ? sc.count : null,
    scopeList: sc ? sc.list : null, read: sc ? sc.read : null, write: sc ? sc.write : null,
    authServer: sc ? sc.authz : null,
    scopesDisagree: sc ? !!sc.disagree : false, inRegistry, viaSibling });
}

if (flag('json')) {
  console.log(JSON.stringify(results, null, 2));
} else {
  const LABEL = {
    live: 'LIVE    ',
    open: 'OPEN    ',
    blocked: 'BLOCKED ',
    none: 'none    ',
    unclear: 'unclear ',
  };
  console.log('');
  console.log('  vendor        state     scopes   r/w   registry  detail');
  console.log('  ' + '-'.repeat(80));
  for (const r of results) {
    const sc = r.scopes === null ? '     .' : (String(r.scopes) + (r.scopesDisagree ? '*' : '')).padStart(6);
    const rw = r.scopes === null ? '  .  '
      : r.write === 0 && r.read > 0 ? ' RO  '
      : `${r.read}/${r.write}`.padStart(5);
    const reg = r.inRegistry === null ? '   .    '
      : r.viaSibling ? ' listed~'
      : r.inRegistry ? ' listed '
      : ' ABSENT ';
    console.log(`  ${r.vendor.padEnd(13)} ${LABEL[r.state]}${sc}  ${rw}  ${reg}  ${r.note}`);
  }
  console.log('');
  const live = results.filter((r) => r.state === 'live' || r.state === 'open');
  console.log(`  ${live.length} of ${results.length} vendors answered.`);
  if (listed) {
    const absent = live.filter((r) => r.inRegistry === false);
    console.log(`  ${absent.length} of those are absent from the official registry: ${absent.map((r) => r.vendor).join(', ') || 'none'}`);
  } else {
    console.log('  Re-run with --registry to check which of these the official registry actually lists.');
  }
  console.log('');
  console.log('  LIVE    the vendor runs a server and wants you to sign in. Normal.');
  console.log('  OPEN    it answered with no credential at all. Read what it does before using it.');
  console.log('  BLOCKED something is there but it refused. Not usable, and not proof of a product.');
  console.log('  none    nothing at the guessable address. Check the vendor docs before concluding.');
  console.log('');
  console.log('  r/w is read-flavoured / write-flavoured scopes. RO means it offers NO write scope at all,');
  console.log('  which is the best answer available: the vendor did not build the door. Xero reads RO.');
  console.log('  A high scope count is good news: it means you can grant something narrow.');
  console.log('  A dot is not "no control": some vendors scope through restricted API keys instead.');
  console.log('  A * means the vendor publishes two scope documents that disagree; the higher one is shown.');
  console.log('  listed~ means the registry lists the vendor at a different hostname than the one probed.');
  console.log('');
}
````

</details>

## If you do one thing

Before you install any MCP server somebody recommends, send a handshake to its endpoint yourself and look at where it lives. If the address is not on the vendor's own domain, it is a stranger's project, whatever the name says and whatever list you found it on.

That takes ten seconds. It would have caught every false positive in my own first pass, and it is the only step in this article that stays true after the numbers go stale.

## Fact-check notes and sources

Everything measured or read on 22 August 2026.

- **The registry counts** are my own, produced by paginating the public API at `https://registry.modelcontextprotocol.io/v0/servers` to exhaustion: 794 pages, 79,341 version records, 24,240 distinct servers, 9,875 distinct remote endpoint hostnames. To reproduce the headline number without the full walk, add `version=latest`, which returns one record per server: 243 pages in about eleven seconds. Run an hour after my second walk, it returned 24,244, the same number still climbing. An earlier walk the same morning returned 79,330 records and 24,235 servers, which is where the growth figure comes from. The namespace split (16,940 under `io.github.*`, 7,296 domain-style, 896 with neither a package nor a remote) is from that earlier walk.
- **The registry's own policy** on review, moderation and what it will and will not remove comes from the registry project's published documentation and moderation policy at [github.com/modelcontextprotocol/registry](https://github.com/modelcontextprotocol/registry).
- **The protocol, its revisions and governance**: [modelcontextprotocol.io](https://modelcontextprotocol.io) and its specification. Current revision 2026-07-28; sampling, roots and logging deprecated under SEP-2577; Anthropic donated MCP to the Agentic AI Foundation on 9 December 2025.
- **The vendor probe** is mine and reproducible with the script in the kit. Each endpoint received a real `initialize` request over the Streamable HTTP transport. A server counted as live only if it answered with a protocol response or an OAuth challenge naming itself, not merely because the hostname resolved. The permission-scope counts come from each server's RFC 9728 protected-resource document. The registry cross-check compared each answering hostname against all 9,875 remote endpoint hostnames collected in the full walk, so "absent" means absent from every remote endpoint in the registry, not merely absent from a keyword search.
- **The Intuit finding**: `mcp.intuit.com` answers 403 Forbidden from two independent networks, and its A record resolves through `gatewaysimulatorser.e2e.api.a.intuit.com`, checked over DNS-over-HTTPS against Cloudflare's resolver.
- **The dead tunnels**: 32 remote endpoint hostnames in the registry are Cloudflare quick-tunnel or ngrok addresses. Twelve were sampled. The six Cloudflare names returned NXDOMAIN. The six ngrok names resolved but returned ngrok's tunnel-not-found page, confirmed from a second network so the result is not local to my machine.
- **CVE data** from the [NIST National Vulnerability Database](https://services.nvd.nist.gov/rest/json/cves/2.0), keyword "Model Context Protocol", 74 results. CVE-2025-34072 (9.3, 2 July 2025), CVE-2025-53109 (7.3, 2 July 2025) and CVE-2025-53365 (8.7, 4 July 2025) quoted from their NVD entries. Severity scores are the CVSS base scores recorded there.
- **The permission scopes** are the `scopes_supported` arrays from each server's RFC 9728 protected-resource document, read on 22 August 2026. The read and write columns classify scope strings by name, which is a rough method and is meant as one. Xero's document names `identity.xero.com` as its authorisation server and lists no write scope of any kind. Stripe's restricted-key and dashboard controls come from [Stripe's own MCP documentation](https://docs.stripe.com/mcp).
- **The Xero discrepancy**: Xero's developer FAQ describes a local server requiring development experience, while `mcp.xero.com/mcp` answers as a hosted, OAuth-protected, read-only endpoint. Both are Xero's. I have reported the endpoint's behaviour because I tested it directly, and flagged the documentation because a reader checking only the docs would reach the wrong conclusion.
- **The npm figure** for the Filesystem reference server is from the [npm downloads API](https://api.npmjs.org/downloads/point/2026-08-15:2026-08-21/@modelcontextprotocol/server-filesystem): 621,657 downloads for 15 to 21 August 2026.
- **Tool search behaviour, scopes and the trust warning**: [Connect Claude Code to tools via MCP](https://code.claude.com/docs/en/mcp). The recommendation to prefer CLI tools is from [Manage costs effectively](https://code.claude.com/docs/en/costs).
- **What I did not do**: sign in to, install, or run any of these servers. Every result here comes from an unauthenticated handshake, public metadata documents, registry records and vendor documentation. No credential was issued to anything.
- **The limits of the probe**: it tests the address you would guess. A vendor that publishes at a per-store or per-account endpoint, as Shopify does, will read as absent. "No server found" in this article means "nothing answered at the obvious address", and I have said so rather than rounding it up to a stronger claim.

Registry contents change daily, and this one grew by five servers while I was measuring it. The counts are a snapshot; the ratios and the method are the durable part.

## Related reading

- [The best MCP servers by industry](/blog/blog-mcp-servers-by-industry-guide/) is the companion catalogue, written for a technical audience and organised by function rather than by risk.
- [The MCP server recommender](/tools/mcp-server-recommender/) turns a checklist of what you use into a paste-ready configuration, free and with no signup.
- [Claude in Chrome](/blog/claude-in-chrome-browser-extension/) is the other way to give an assistant access to your systems, and for a lot of small-business tasks it is the better one, because it uses a session you already control instead of a token you have to issue.
- [Two lead agents that restart each other](/blog/claude-code-agent-fleet-org-chart/) covers the permission and blast-radius thinking that applies to any tool you hand an agent.
- [Delete yourself from 603 data brokers](/blog/delete-yourself-from-data-brokers/) is a useful reminder of where data goes once it leaves your control, which is the right frame of mind for issuing an API token to somebody else's software.


---

Canonical HTML: https://jwatte.com/blog/mcp-servers-for-small-business/
RSS: https://jwatte.com/feed.xml
JSON Feed: https://jwatte.com/feed.json
Hero image: https://jwatte.com/images/mcp-servers-for-small-business.webp
