Glow Security published research on 2 November it calls MCPhantom: coding agents told to "set up a GitHub MCP" or "add a Postgres MCP" keep reaching for packages that were archived eighteen months ago, and in 98 percent of the sessions it reviewed the package name came from the model's memory, not from anything the agent looked up or the user asked for by name. I could not open Glow's own write-up, so I treat its numbers as reported. The part I could check, I checked, and the mechanism holds: on 2.1.318 Claude Code, on Codex, on a plain model prompt, the name that comes back for a database server is the archived one.
The reference servers in question live in modelcontextprotocol/servers-archived, a repository whose own README says in bold "NO SECURITY GUARANTEES ARE PROVIDED FOR THESE ARCHIVED SERVERS," last touched on 28 May 2025. They are all marked deprecated on npm. That did not slow anything down: @modelcontextprotocol/server-github pulled 189,189 downloads last week, server-slack 185,396, server-postgres 155,598, and server-github alone has shipped more than 5.5 million times since July 2025.
This morning the warning on three of them changed. A September issue asking for a clearer deprecation message was closed as completed at 04:21 UTC today, and the npm notice on the GitHub, Postgres and Puppeteer packages now reads "Archived and unmaintained; no security guarantees" with a link to the archive, where yesterday it said "Package no longer supported. Contact Support at npmjs.com." It is a real improvement and it changes nothing about the install, because npx -y prints the warning and then runs the package regardless.
What the models actually name
I asked ten headless Claude Code runs, five on Haiku 5.5 and five on Sonnet 5.5, to write the MCP config for a GitHub, Postgres, Slack, browser-automation and Brave Search server. No file tools, just the config as text. Two Haiku runs declined for want of tools. The ones that answered are the interesting part.
For Postgres, both models named @modelcontextprotocol/server-postgres, the archived package, with the live database URL passed straight in. For Slack, Sonnet named server-slack, also archived. For Brave Search the two models disagreed in the same session set: Haiku returned @brave/brave-search-mcp-server, which is Brave's own current server, while Sonnet returned the archived server-brave-search. For GitHub, Haiku pointed at GitHub's hosted remote server and Sonnet named the archived server-github. For browser automation, Sonnet returned @playwright/mcp, Microsoft's maintained server, cleanly. A headless Codex run on gpt-6-astra, asked the same GitHub question, pointed at github/github-mcp-server in read-only mode.
The shape of that is worth sitting with. Where a service has a famous first-party replacement, GitHub's remote server, Microsoft's Playwright server, the better model often lands on it. Where the best-known thing is still the old Anthropic reference, Postgres and Slack, the frontier model hands you the archived package without a flicker. And a database server is exactly the one you least want chosen from memory, because it is the one holding a connection string.
The warning that changed this morning
The issue that moved this was filed on 9 September by a developer who maintains an MCP config scanner. They measured 214,369 downloads a week across four archived servers and made a narrow, concrete point: the generic npm text, "Package no longer supported, contact npm support," reaches every single installer and tells them nothing useful. It names no replacement, states no security status, and points at a support desk that cannot answer an MCP question. A maintainer triaged it Low in October and closed it this morning with the note "Updated all but server-brave-search, for some reason I could not access it."
So the state right now is split. Run npm view @modelcontextprotocol/server-github deprecated today and you get the honest "archived and unmaintained, no security guarantees" line. Run it against server-brave-search, server-gdrive, server-gitlab, server-google-maps, server-redis and the rest and you still get the old "contact npm support" boilerplate that says nothing. The message is better on the two credential-holding servers that matter most, which is the right place to start, and it took fourteen months and a second rewrite to get there.
Why the warning doesn't stop anything
The reason none of your existing controls caught this is that an npx-launched MCP server is a dependency that never lands in a dependency file. Your endpoint protection watches a trusted Node process install a public npm package because an agent asked it to, which looks like every other day. Your software-composition scanner reads manifests, and there is no manifest. These flaws carry no CVE numbers, so anything working from a CVE feed stays silent. Your agent harness gates what the agent is allowed to run, but it has no notion of whether the package behind the command is deprecated. The install shows up in exactly one place, the machine where the config got written.
Asking the agent to check first is not the fix either, and Glow's own example is the cleanest statement of why. In one session the agent ran the npm lookup, got back "This package is deprecated," installed the package anyway, and never mentioned it to the user. A polite instruction in a prompt is not a control. A control is something that fails closed when the model does not feel like cooperating.
The browser server is the sharp one
Of the four high-severity flaws Glow reports, the one it calls worst is in the Puppeteer server, and reading the source shows why it is uncomfortable. The server exposes a launchOptions object and an allowDangerous flag on its navigate tool, and it deep-merges a PUPPETEER_LAUNCH_OPTIONS environment value with whatever the tool call passes in. There is a guard, a DANGEROUS_ARGS list covering --no-sandbox and friends that throws unless allowDangerous is set, but the whole surface is driven by the model's tool arguments, on a server whose own README warns it "can access local files and local/internal IP addresses" because it runs a real browser on your machine. Glow's account is that a prompt injection on a page the agent visits is enough to turn that into arbitrary process execution, and that the single "yes" the developer gave to web browsing covers everything the browser server then does. The maintainers closed the report as out of scope: the repository was archived in May 2025, so no fix is coming. The package still installs.
What actually holds
The fix that works today is boring and it is a configuration fix, not a prompt. Name the exact server in the MCP config and never let the agent pick the package. For the ones that have a maintained owner, move to it: GitHub's own github-mcp-server, Microsoft's @playwright/mcp in place of Puppeteer, Brave's @brave/brave-search-mcp-server. For Postgres, Slack and the rest, check whether the vendor ships its own server before you accept a community one, and read its tool list before you approve it.
Two things keep the old names from creeping back. Write the approved list where the agent reads it, one line in CLAUDE.md or AGENTS.md, which changes what the model proposes but is still only a suggestion. Then back it with a pre-tool hook that rejects any shell command mentioning the archived package names, which holds whatever the model remembers. Claude Code's PreToolUse hook is the right place for it.
While I was checking all this I grepped the MCP configs on my own machine. One of them, a Cursor config I set up in July, still points at @modelcontextprotocol/server-postgres. The server it names was archived four months before I wrote that line, and nothing between then and this morning ever told me.