The Agent Supply Chain Report, edition one
Nobody looks inside.
One pass over the public agent supply chain, on 30 and 31 July 2026. It collected 53,580 items from the sources that permit automated collection, and counted what each source itself publishes about them. The method comes first here, then the counts, each one carrying the denominator it was taken from. What the method could not see is published with them. No publisher and no item is named in it.
What we did
Method before findings, because a reader has to be able to judge a number before seeing it.
The corpus is a public index of agent machinery: the servers, plugins, skills and extensions a person installs to give an agent more reach on the machine in front of them. A run passes over every source that permits automated collection and records what that source itself publishes about each item. Then it counts. Nothing in the corpus comes from a customer, a fleet or any private environment, and nothing in it is extrapolated to one.
The run reported here is 20260730T203216Z. It started at 20:32 UTC on 30 July 2026 and finished at 01:29 UTC on 31 July, making 1,066 requests and collecting 53,580 items. Nineteen sources are registered in the collector, and nine of them produced items: a public registry of servers at 19,299, an editor extension marketplace at 10,000, a browser extension store subset at 9,744, a package registry subset at 7,956, two curated link lists at 3,653 distinct repositories, a community plugin catalogue at 2,307, a curated server catalogue at 328, an official plugin catalogue at 276, and a reference set of skills at 17.
Sources are described here by role rather than by name, and no item and no publisher is named anywhere in this edition. That is the disclosure policy for edition one, not a hole in the data. The run manifest carries every source identifier, the exact URLs fetched, the coverage claim each source makes and the terms evidence for each, so the full list is there for anyone who wants it, at github.com/Northbeams-Labs/corpus.
Three sources were excluded before a single request was made, for one reason each: their own terms of service forbid automated access. One is a browser extension store, one is an editor extension marketplace, and one is a vendor catalogue of connectors and extensions reachable only inside its own application. For each of the three, the clause and the evidence URL sit in the collector, which refuses to collect them and fails its own build if anyone adds a collector for them by accident. They were dropped rather than worked around. No attempt to reach them was made.
Four more sources contributed nothing, and the reasons are worth separating from the three above. Two were refused by their own robots file at collection time. One of those disallows the JSON path that is also its public API. The other publishes a robots file that both allows and disallows the same path for the same user agent, and an ambiguous robots file is not permission. Two publish no terms either way and are unresolved, so they are absent rather than sampled. Two further sources are excluded on merit: they re-index sources already counted here, and including them would count the same items twice.
Coverage is stated per source rather than implied. Six sources were a full pass. Three are a documented subset: the extension store subset is every add-on matching any of sixteen published query terms, deduplicated by add-on id; the editor marketplace served the first 10,000 results of a reported 16,184 and then stopped; the package registry was queried on two published keywords rather than enumerated. One source was counted and never enumerated at all, at 1,191 candidate repositories of independently hosted plugin marketplaces, because enumerating them needs an authenticated token and that is an open question. Where a source holds fewer items than the total the source itself publishes, and there is no documented reason for the gap, the run fails rather than earning itself a footnote.
Politeness is in the code rather than in a promise. One connection and at most one request a second, per host. A source’s own published rate is honoured wherever it states one. Requests are conditional, so a re-run costs a source a 304 and nothing else, and robots files are re-fetched and hashed at the start of every run.
The inventory logic and the collector are two separate programs, and only one of them touches a network. The program that produced the inventory logic in this report reads files on the machine it runs on and makes no network request of any kind. The corpus was gathered by a separate internal program, in its own repository, that runs on our own infrastructure and is not part of anything released. The released side fails its own build if a network library appears in its dependency graph, so that is checkable rather than promised.
Every figure below comes from the counts of that one run. Where a source publishes no field for a measure, the item is recorded as not observable and left out of that measure’s denominator. Not observable is never reported as zero.
Findings
The open registry held 19,299 servers, and grew by 87 of them in four hours
One pass over the open server registry, at each server’s latest version, returned 19,299 servers across 193 pages. It ended when the registry stopped issuing a cursor. The registry publishes no population total of its own; its pages carry a per-page count and nothing else. So the only evidence that this was a complete pass is that the cursor chain ran out, and there is no number of theirs to check ours against. That belongs in the finding rather than in a footnote.
Two earlier runs the same day give a window. The registry held 19,212 servers at 16:13 UTC on 30 July and 19,299 at 20:32 UTC. That is 87 more servers in 4 hours and 19 minutes, or 0.45% of 19,212. Two runs four hours apart is a window and not a trend, and it is not published as one.
More than half of those servers declare that something runs on the machine that installs them
The rule reads only what the source published. A server counts as declaring local execution when its own entry declares an installable package (npm, PyPI, OCI, NuGet, mcpb, gem or cargo), or when it names a shell or a code runner in a runtime hint, a command or an argument. A server that declares only a remote endpoint counts as declaring none. A server that declares neither is not observable, and is never counted as none.
In the open registry, 10,329 of the 18,957 servers where the declaration was observable declare local execution, which is 54% of those 18,957. Another 8,628 of the 18,957 declare none. For 342 of the 19,299 servers collected the field was not observable at all.
The curated catalogue does not run lower. Of its 328 entries, 249 publish a declaration we can read, and all 249 of those declare local execution. The other 79 publish no field to read. Curation there is not selecting for less local execution: every curated entry we could observe declares it, against 54% of 18,957 in the open registry.
Neither plugin catalogue asserts that anything was verified, and some entries name no publisher at all
The two catalogued sets of plugins hold 2,583 entries between them, 276 in one and 2,307 in the other. The number carrying any verification assertion from the catalogue itself is zero: all 2,583 are recorded as the catalogue asserting nothing. That is silence rather than a statement that anything failed a check, and the silence is the catalogue’s rather than ours.
195 of those 2,583 entries name no publisher at all: no author field, no namespace, and no source repository we can read an owner from. That is 4 of the 276 in one catalogue and 191 of the 2,307 in the other. Of the rest, 223 of 2,583 publish an author or a namespace, and 2,165 of 2,583 name only a repository. For most of this population, then, the publisher is inferred from a code host account rather than declared to the catalogue.
Two nearby populations show that a registry can assert something when it chooses to. Every one of the 19,299 servers in the open registry carries a namespace whose form records how it was proven: 13,778 of 19,299 through a code host account and 5,521 of 19,299 through a domain challenge. The editor extension marketplace asserts verified for 9,834 of the 10,000 items it served us, and not verified for 166. Namespace authentication establishes who published something. It is not a review of what was published.
Declared reach is mostly not observable in the plugin catalogues, because a catalogue entry is an index record rather than a manifest. Only 14 of the 2,583 entries, 12 in one catalogue and 2 in the other, declare a server the catalogue itself can see. No percentage for that measure is reported here, because not observable is not zero.
Browser extensions are the blind spot, and 2,560 of the 9,378 we could read declare script injection
One extension store publishes an API that permits collection. Its full population on the day was 94,703 extensions. Our subset is 9,744 unique add-ons, being every add-on matching any of sixteen published query terms, deduplicated by add-on id. It is a subset by construction, and it is not a count of AI extensions on that store. An AI add-on matching none of the sixteen terms is absent from it, and an add-on that matched on an unrelated word is present in it. 9,744 of 94,703 is 10% of the store, and that is the only relationship between the two numbers.
Within the subset, 2,560 of the 9,378 add-ons whose permissions were observable declare a permission that injects or runs script in a page the add-on does not own, which is 27% of those 9,378. 170 of the 9,378 declare a permission that reaches a process outside the browser. 6,648 of the 9,378 declare permissions with neither. Permissions were not observable for 366 of the 9,744.
The store asserts a review status for 13 of the 9,744. Separately, 3,514 of the 9,744 have published nothing new for twelve months or more, and the median across the subset is six months since the last release. Twelve months is a measurement threshold, defined once and used the same way everywhere in this report. A last release date is a fact about a listing. It is not a statement about anyone’s intentions.
Some of the busiest venues cannot be counted, by us or by anybody else
Three of the nineteen registered sources forbid automated access in their own published terms, so nobody who follows those terms can publish a count of what is in them. Two of the three are widely described as the biggest venues in their categories, which we cannot confirm, for the same reason: we are not permitted to count them. No figure for any of the three appears anywhere in this report, because there is none we are permitted to produce and none we could check. Third parties publish estimates. We do not carry a number we cannot verify.
The effect is on the denominator rather than on our opinion of those stores, which are entitled to set the terms they like. Nineteen sources registered, nine counted: three closed by their terms, two refused by their own robots files, two unresolved because nobody has published a term either way, two excluded because they would double count what is already here, and one counted at 1,191 candidates but never enumerated. Put plainly, the countable part of this ecosystem is the part that permits counting, and the rest is not knowable to anyone outside the companies hosting it.
No figure here is one the method section does not explain how to reproduce, and every percentage carries the denominator it was taken from.
Two things other people say
Both are statements of published policy rather than anything found in the corpus, and both were read from the primary source on 31 July 2026.
The official registry says it does not remove servers with security vulnerabilities
Its moderation policy has a list of what it will not remove. "Servers with security vulnerabilities" is an item on that list, alongside low quality and duplicate servers. The same page states that the registry "does not make guarantees about moderation, and consumers should assume minimal-to-no moderation", and describes relying on upstream package registries and downstream subregistries for deeper moderation. Source: The MCP Registry Moderation Policy, read 31 July 2026.
The disclosure route for a third-party item is the third party’s own
Anthropic’s responsible disclosure policy covers systems it owns, operates or controls. It states that it "does not cover any information systems, websites, or applications that are owned, operated, or controlled by any third party", and adds that a researcher should follow those parties’ own disclosure efforts. We read four published documentation pages on 31 July 2026, covering installing plugins, distributing a plugin marketplace, the connector directory and connector verification. None of them publishes a channel for reporting a third-party plugin, skill, connector or extension. Sources: Responsible Disclosure Policy, last updated 14 February 2025, and the connector directory documentation, both read 31 July 2026.
Both are defensible positions for the organisations publishing them, and neither is quoted here as an accusation. Read together, though, they leave the checking of a third-party item with the person installing it.
What this does not show
Published with the findings rather than after somebody asks for them.
- Declared capability is not observed behaviour. Every count here reads a field the source itself published. Nothing in this report ran, installed, unpacked or watched any item, so nothing here says what any of it actually does.
- A declared shell command is often exactly what the tool is for. A server that declares an installable package is describing how it works. These are population facts about published software rather than defects, and not one of them is a finding about any particular item.
- Nothing here measures malice, and nothing here could. We did not measure how much of this population is harmful, we have no method that would, and no figure in this report should be read as one. Intent is not observable from a manifest.
- Not observable is not zero. Declared reach was not observable for 342 of 19,299 servers, for 2,569 of 2,583 plugin catalogue entries, for 366 of 9,744 add-ons, and for every one of the 10,000 editor marketplace items and 7,956 package registry items in this run. Those are excluded from that measure’s denominator rather than counted as none.
- Three of the counted populations are subsets, and they are labelled as such. The extension subset is defined by sixteen query terms and is not a count of AI extensions on that store. The editor marketplace served the first 10,000 of a reported 16,184. The package registry was queried on two keywords rather than enumerated.
- The sources we may not count are missing entirely, so no total here is a total of the ecosystem. One registered source of roughly 1,191 candidate repositories was counted and never enumerated, and no item from it is in the snapshot or in any count above.
- Two runs on one day are not a growth trend, and the 87 servers added in 4 hours and 19 minutes are not published as a rate.
- A re-run months from now will not match perfectly, because listings get edited and deleted. Expect decay against these hashes rather than an exact match. Treat a mismatch as something to go and look at rather than as proof of an error either way.
How to check us
Every number above comes from one run, and that run is public: the collector, the run manifest and the snapshot are at github.com/Northbeams-Labs/corpus.
The snapshot is one row per item and eight fields, all of them facts about our own fetch: the source identifier, the exact URL fetched, the registry’s own identifier for the item, the version string as the registry gave it, the fetch time in UTC, the HTTP status we got, a SHA-256 of the exact bytes we classified, and the length of those bytes. This run’s snapshot holds 53,580 rows.
The manifest beside it carries the run id, the start and finish times, the collector version, the user agent every request was sent with, each source’s terms verdict and coverage claim, per-host request counts, robots hashes and per-source item counts. A checksum file covers the whole snapshot.
Two things the snapshot deliberately does not contain: the third party’s text, and our classification of any item. No descriptions, no manifests, no permission lists, and no verdict of ours about anything. That is a decision rather than an oversight. Publishing per-item verdicts would name every publisher in a spreadsheet, however carefully the prose avoided it.
Reproducing a figure does not need our verdicts. Take the classifier, re-fetch the identifiers in the snapshot from the same sources, check each hash against ours, and re-derive the counts. A hash that does not match is either a listing that changed or an error of ours, and both are worth knowing.
The commands
One polite pass over the permitted sources. Then the aggregate counts, each with its denominator. Then every source with its terms verdict and the URL of the evidence for it, the sources we are not allowed to touch included. The last of the four re-derives every number from the cache and contacts nobody.
These run against the collector at github.com/Northbeams-Labs/corpus, which is public.
make collectmake report-numbersmake sourcescorpus collect -offline
The offline pass exists so that developing a classifier costs the sources nothing.
Corrections
None so far. Each one gets a date and one line saying what changed, and nothing is edited silently.