mcp-use-compat 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +21 -0
  3. package/README.md +375 -0
  4. package/dist/checks/auth.d.ts +2 -0
  5. package/dist/checks/auth.d.ts.map +1 -0
  6. package/dist/checks/auth.js +229 -0
  7. package/dist/checks/auth.js.map +1 -0
  8. package/dist/checks/calls.d.ts +4 -0
  9. package/dist/checks/calls.d.ts.map +1 -0
  10. package/dist/checks/calls.js +192 -0
  11. package/dist/checks/calls.js.map +1 -0
  12. package/dist/checks/discovery.d.ts +3 -0
  13. package/dist/checks/discovery.d.ts.map +1 -0
  14. package/dist/checks/discovery.js +47 -0
  15. package/dist/checks/discovery.js.map +1 -0
  16. package/dist/checks/explanations.d.ts +15 -0
  17. package/dist/checks/explanations.d.ts.map +1 -0
  18. package/dist/checks/explanations.js +346 -0
  19. package/dist/checks/explanations.js.map +1 -0
  20. package/dist/checks/index.d.ts +3 -0
  21. package/dist/checks/index.d.ts.map +1 -0
  22. package/dist/checks/index.js +23 -0
  23. package/dist/checks/index.js.map +1 -0
  24. package/dist/checks/protocol.d.ts +5 -0
  25. package/dist/checks/protocol.d.ts.map +1 -0
  26. package/dist/checks/protocol.js +380 -0
  27. package/dist/checks/protocol.js.map +1 -0
  28. package/dist/checks/resources.d.ts +10 -0
  29. package/dist/checks/resources.d.ts.map +1 -0
  30. package/dist/checks/resources.js +144 -0
  31. package/dist/checks/resources.js.map +1 -0
  32. package/dist/checks/schema.d.ts +21 -0
  33. package/dist/checks/schema.d.ts.map +1 -0
  34. package/dist/checks/schema.js +412 -0
  35. package/dist/checks/schema.js.map +1 -0
  36. package/dist/checks/sdk.d.ts +10 -0
  37. package/dist/checks/sdk.d.ts.map +1 -0
  38. package/dist/checks/sdk.js +68 -0
  39. package/dist/checks/sdk.js.map +1 -0
  40. package/dist/checks/tools.d.ts +18 -0
  41. package/dist/checks/tools.d.ts.map +1 -0
  42. package/dist/checks/tools.js +422 -0
  43. package/dist/checks/tools.js.map +1 -0
  44. package/dist/checks/transport.d.ts +2 -0
  45. package/dist/checks/transport.d.ts.map +1 -0
  46. package/dist/checks/transport.js +123 -0
  47. package/dist/checks/transport.js.map +1 -0
  48. package/dist/checks/types.d.ts +37 -0
  49. package/dist/checks/types.d.ts.map +1 -0
  50. package/dist/checks/types.js +5 -0
  51. package/dist/checks/types.js.map +1 -0
  52. package/dist/checks/ui.d.ts +2 -0
  53. package/dist/checks/ui.d.ts.map +1 -0
  54. package/dist/checks/ui.js +207 -0
  55. package/dist/checks/ui.js.map +1 -0
  56. package/dist/checks/util.d.ts +20 -0
  57. package/dist/checks/util.d.ts.map +1 -0
  58. package/dist/checks/util.js +42 -0
  59. package/dist/checks/util.js.map +1 -0
  60. package/dist/cli.d.ts +110 -0
  61. package/dist/cli.d.ts.map +1 -0
  62. package/dist/cli.js +317 -0
  63. package/dist/cli.js.map +1 -0
  64. package/dist/connect/calls.d.ts +13 -0
  65. package/dist/connect/calls.d.ts.map +1 -0
  66. package/dist/connect/calls.js +130 -0
  67. package/dist/connect/calls.js.map +1 -0
  68. package/dist/connect/http.d.ts +14 -0
  69. package/dist/connect/http.d.ts.map +1 -0
  70. package/dist/connect/http.js +122 -0
  71. package/dist/connect/http.js.map +1 -0
  72. package/dist/connect/index.d.ts +41 -0
  73. package/dist/connect/index.d.ts.map +1 -0
  74. package/dist/connect/index.js +168 -0
  75. package/dist/connect/index.js.map +1 -0
  76. package/dist/connect/lists.d.ts +12 -0
  77. package/dist/connect/lists.d.ts.map +1 -0
  78. package/dist/connect/lists.js +70 -0
  79. package/dist/connect/lists.js.map +1 -0
  80. package/dist/connect/modern.d.ts +13 -0
  81. package/dist/connect/modern.d.ts.map +1 -0
  82. package/dist/connect/modern.js +169 -0
  83. package/dist/connect/modern.js.map +1 -0
  84. package/dist/connect/session.d.ts +29 -0
  85. package/dist/connect/session.d.ts.map +1 -0
  86. package/dist/connect/session.js +96 -0
  87. package/dist/connect/session.js.map +1 -0
  88. package/dist/connect/stdio.d.ts +36 -0
  89. package/dist/connect/stdio.d.ts.map +1 -0
  90. package/dist/connect/stdio.js +127 -0
  91. package/dist/connect/stdio.js.map +1 -0
  92. package/dist/diff.d.ts +23 -0
  93. package/dist/diff.d.ts.map +1 -0
  94. package/dist/diff.js +255 -0
  95. package/dist/diff.js.map +1 -0
  96. package/dist/evaluate.d.ts +70 -0
  97. package/dist/evaluate.d.ts.map +1 -0
  98. package/dist/evaluate.js +104 -0
  99. package/dist/evaluate.js.map +1 -0
  100. package/dist/explain.d.ts +4 -0
  101. package/dist/explain.d.ts.map +1 -0
  102. package/dist/explain.js +46 -0
  103. package/dist/explain.js.map +1 -0
  104. package/dist/fix.d.ts +19 -0
  105. package/dist/fix.d.ts.map +1 -0
  106. package/dist/fix.js +116 -0
  107. package/dist/fix.js.map +1 -0
  108. package/dist/index.d.ts +3 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +54 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/oauth.d.ts +85 -0
  113. package/dist/oauth.d.ts.map +1 -0
  114. package/dist/oauth.js +287 -0
  115. package/dist/oauth.js.map +1 -0
  116. package/dist/policy.d.ts +29 -0
  117. package/dist/policy.d.ts.map +1 -0
  118. package/dist/policy.js +63 -0
  119. package/dist/policy.js.map +1 -0
  120. package/dist/profiles/chatgpt.d.ts +3 -0
  121. package/dist/profiles/chatgpt.d.ts.map +1 -0
  122. package/dist/profiles/chatgpt.js +29 -0
  123. package/dist/profiles/chatgpt.js.map +1 -0
  124. package/dist/profiles/claude-code.d.ts +3 -0
  125. package/dist/profiles/claude-code.d.ts.map +1 -0
  126. package/dist/profiles/claude-code.js +62 -0
  127. package/dist/profiles/claude-code.js.map +1 -0
  128. package/dist/profiles/claude-desktop.d.ts +3 -0
  129. package/dist/profiles/claude-desktop.d.ts.map +1 -0
  130. package/dist/profiles/claude-desktop.js +51 -0
  131. package/dist/profiles/claude-desktop.js.map +1 -0
  132. package/dist/profiles/cline.d.ts +4 -0
  133. package/dist/profiles/cline.d.ts.map +1 -0
  134. package/dist/profiles/cline.js +118 -0
  135. package/dist/profiles/cline.js.map +1 -0
  136. package/dist/profiles/codex.d.ts +4 -0
  137. package/dist/profiles/codex.d.ts.map +1 -0
  138. package/dist/profiles/codex.js +168 -0
  139. package/dist/profiles/codex.js.map +1 -0
  140. package/dist/profiles/continue.d.ts +4 -0
  141. package/dist/profiles/continue.d.ts.map +1 -0
  142. package/dist/profiles/continue.js +93 -0
  143. package/dist/profiles/continue.js.map +1 -0
  144. package/dist/profiles/cursor.d.ts +3 -0
  145. package/dist/profiles/cursor.d.ts.map +1 -0
  146. package/dist/profiles/cursor.js +52 -0
  147. package/dist/profiles/cursor.js.map +1 -0
  148. package/dist/profiles/gemini-cli.d.ts +4 -0
  149. package/dist/profiles/gemini-cli.d.ts.map +1 -0
  150. package/dist/profiles/gemini-cli.js +137 -0
  151. package/dist/profiles/gemini-cli.js.map +1 -0
  152. package/dist/profiles/goose.d.ts +4 -0
  153. package/dist/profiles/goose.d.ts.map +1 -0
  154. package/dist/profiles/goose.js +114 -0
  155. package/dist/profiles/goose.js.map +1 -0
  156. package/dist/profiles/index.d.ts +7 -0
  157. package/dist/profiles/index.d.ts.map +1 -0
  158. package/dist/profiles/index.js +43 -0
  159. package/dist/profiles/index.js.map +1 -0
  160. package/dist/profiles/opencode.d.ts +3 -0
  161. package/dist/profiles/opencode.d.ts.map +1 -0
  162. package/dist/profiles/opencode.js +47 -0
  163. package/dist/profiles/opencode.js.map +1 -0
  164. package/dist/profiles/types.d.ts +86 -0
  165. package/dist/profiles/types.d.ts.map +1 -0
  166. package/dist/profiles/types.js +2 -0
  167. package/dist/profiles/types.js.map +1 -0
  168. package/dist/profiles/vscode-copilot.d.ts +3 -0
  169. package/dist/profiles/vscode-copilot.d.ts.map +1 -0
  170. package/dist/profiles/vscode-copilot.js +71 -0
  171. package/dist/profiles/vscode-copilot.js.map +1 -0
  172. package/dist/profiles/windsurf.d.ts +4 -0
  173. package/dist/profiles/windsurf.d.ts.map +1 -0
  174. package/dist/profiles/windsurf.js +49 -0
  175. package/dist/profiles/windsurf.js.map +1 -0
  176. package/dist/project.d.ts +52 -0
  177. package/dist/project.d.ts.map +1 -0
  178. package/dist/project.js +291 -0
  179. package/dist/project.js.map +1 -0
  180. package/dist/reporters/escape.d.ts +7 -0
  181. package/dist/reporters/escape.d.ts.map +1 -0
  182. package/dist/reporters/escape.js +15 -0
  183. package/dist/reporters/escape.js.map +1 -0
  184. package/dist/reporters/github.d.ts +7 -0
  185. package/dist/reporters/github.d.ts.map +1 -0
  186. package/dist/reporters/github.js +19 -0
  187. package/dist/reporters/github.js.map +1 -0
  188. package/dist/reporters/index.d.ts +6 -0
  189. package/dist/reporters/index.d.ts.map +1 -0
  190. package/dist/reporters/index.js +10 -0
  191. package/dist/reporters/index.js.map +1 -0
  192. package/dist/reporters/json.d.ts +3 -0
  193. package/dist/reporters/json.d.ts.map +1 -0
  194. package/dist/reporters/json.js +4 -0
  195. package/dist/reporters/json.js.map +1 -0
  196. package/dist/reporters/markdown.d.ts +3 -0
  197. package/dist/reporters/markdown.d.ts.map +1 -0
  198. package/dist/reporters/markdown.js +98 -0
  199. package/dist/reporters/markdown.js.map +1 -0
  200. package/dist/run.d.ts +14 -0
  201. package/dist/run.d.ts.map +1 -0
  202. package/dist/run.js +163 -0
  203. package/dist/run.js.map +1 -0
  204. package/dist/sdk-facts.d.ts +27 -0
  205. package/dist/sdk-facts.d.ts.map +1 -0
  206. package/dist/sdk-facts.js +63 -0
  207. package/dist/sdk-facts.js.map +1 -0
  208. package/dist/snapshot.d.ts +189 -0
  209. package/dist/snapshot.d.ts.map +1 -0
  210. package/dist/snapshot.js +22 -0
  211. package/dist/snapshot.js.map +1 -0
  212. package/dist/ui.d.ts +18 -0
  213. package/dist/ui.d.ts.map +1 -0
  214. package/dist/ui.js +22 -0
  215. package/dist/ui.js.map +1 -0
  216. package/dist/upgrade.d.ts +12 -0
  217. package/dist/upgrade.d.ts.map +1 -0
  218. package/dist/upgrade.js +115 -0
  219. package/dist/upgrade.js.map +1 -0
  220. package/dist/version.d.ts +3 -0
  221. package/dist/version.d.ts.map +1 -0
  222. package/dist/version.js +5 -0
  223. package/dist/version.js.map +1 -0
  224. package/package.json +65 -0
  225. package/schema/report.schema.json +327 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # Changelog
2
+
3
+ ## 0.3.0
4
+
5
+ - Commands: `check` (default), `upgrade`, `diff`, `call`, `oauth`, `fix`, `explain`, `list-checks`, `list-clients`.
6
+ - Twelve clients: Claude Desktop, Claude Code, ChatGPT, Cursor, VS Code (GitHub Copilot), OpenCode, Codex CLI, Gemini CLI, Cline, Goose, Continue and Windsurf. Every fact links to its source.
7
+ - All published protocol versions: `--version-matrix` for 2024-11-05 to 2025-11-25, and full support for the stateless 2026-07-28 revision.
8
+ - `upgrade` detects the server's MCP SDK, shows installed and latest versions, prints the command for your package manager, and with `--apply` upgrades and re-checks the server.
9
+ - Tool calls: `--probe-calls` (read-only tools only) and `call <tool>`, with result, output schema, size and timeout checks.
10
+ - `oauth login` runs and reports the full OAuth flow; `--oauth` reuses the stored token.
11
+ - `diff` classifies breaking changes between two snapshots.
12
+ - `fix` applies safe mechanical fixes to tool definitions.
13
+ - Rules from other linters were verified against client source before being adopted.
14
+
15
+ ## 0.2.0
16
+
17
+ - Real connection layer for stdio and Streamable HTTP, replacing the simulated clients of 0.1.
18
+ - Checks run on what the server actually returns; client-specific results come from sourced client profiles.
19
+ - Markdown, JSON and GitHub annotation reports, `--fail-on`, snapshots.
20
+
21
+ ## 0.1.0
22
+
23
+ - First prototype.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 VrajVed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,375 @@
1
+ # mcp-use-compat
2
+
3
+ Find the problems that break an MCP server in specific MCP clients, before your users do.
4
+
5
+ MCP is one protocol, but every client reads it differently: Claude Desktop, Claude Code, ChatGPT, Cursor, VS Code, OpenCode, Codex, Gemini CLI, Cline, Goose, Continue and Windsurf each rename, truncate, validate, cache and render things their own way. `mcp-use-compat` connects to your server, records what it actually exposes, and checks it against sourced facts about each client. Every client-specific result links to where the fact comes from (docs, pinned client source, or maintainer statements), so a report tells you what breaks, where, and how we know.
6
+
7
+ ```bash
8
+ npx mcp-use-compat -- node dist/server.js
9
+ ```
10
+
11
+ ## Installation
12
+
13
+ Requires Node.js 20 or newer. Your server can be written in any language.
14
+
15
+ ```bash
16
+ npx mcp-use-compat --help # run without installing
17
+ npm install -g mcp-use-compat # install the CLI globally
18
+ npm install --save-dev mcp-use-compat # add it to a project, e.g. for CI
19
+ ```
20
+
21
+ To try the latest code from GitHub: `npm install -g github:VrajVed/mcp-use-compat`.
22
+
23
+ ## Quick start
24
+
25
+ ```bash
26
+ # A local server: put its start command after --
27
+ npx mcp-use-compat -- node dist/server.js
28
+ npx mcp-use-compat -- uv run server.py
29
+
30
+ # A remote server
31
+ npx mcp-use-compat --url https://example.com/mcp
32
+
33
+ # Is its MCP SDK up to date?
34
+ npx mcp-use-compat upgrade -- node dist/server.js
35
+ ```
36
+
37
+ You get a report per client, with a fix for every problem, and an exit code for CI. New here? Start with the [getting started guide](docs/getting-started.md).
38
+
39
+ ## What it finds
40
+
41
+ Real examples:
42
+
43
+ - **`description: null` on a tool.** Absent is allowed, null is not: the TypeScript SDK rejects the whole `tools/list` response, so SDK-based clients see no tools at all.
44
+ - **`files.read` and `files_read` in one server.** Cursor, VS Code and OpenCode replace `.` with `_`, so the two collide and one tool disappears.
45
+ - **Long tool names.** Cursor, VS Code and Gemini CLI count their server prefix and then truncate, so the model sees a mangled name.
46
+ - **A large input schema.** Codex compacts schemas over 5,000 characters and strips your descriptions first.
47
+ - **A root-level `anyOf` without `"type": "object"`.** Cline fails to register it and drops every tool from the server.
48
+ - **Structured results without a text copy.** Gemini CLI, Goose and Continue only pass text to the model, so it gets an empty result.
49
+ - **Logs on stdout.** SDK clients drop the lines, and a log write without a newline corrupts the next protocol message.
50
+ - **OAuth metadata without PKCE S256.** Spec-following clients must refuse to connect, and ChatGPT does.
51
+ - **An outdated SDK.** `mcp` 1.27.2 when 2.2.0 is out: you get the exact upgrade command for your package manager, and `upgrade --apply` can run it and re-check the server.
52
+
53
+ ## Commands
54
+
55
+ | Command | What it does |
56
+ |---|---|
57
+ | `check` (default) | Connect to a server and report issues per client |
58
+ | `upgrade` | Find the server's MCP SDK, compare with the latest release, print or apply the upgrade |
59
+ | `diff <before> <after>` | Compare two snapshots: breaking changes and new compatibility failures |
60
+ | `call <tool>` | Call one tool and check its result |
61
+ | `oauth login \| status \| logout` | Log in to an OAuth-protected server and reuse the token |
62
+ | `fix <snapshot>` | Apply safe mechanical fixes to tool definitions |
63
+ | `explain <CHECK_ID>` | Why a check exists, its sources, and the client facts it uses |
64
+ | `list-checks`, `list-clients` | Print all checks, or the client profiles and how fresh their facts are |
65
+
66
+ ## Guides
67
+
68
+ - [Getting started](docs/getting-started.md): install, first check, troubleshooting
69
+ - [Reading reports](docs/reading-reports.md): statuses, `--fail-on`, output formats, the JSON report
70
+ - [Using it in CI](docs/ci.md): GitHub Actions, gating builds, artifacts
71
+ - [Comparing releases](docs/snapshots-and-diff.md): snapshots and `diff`
72
+ - [Upgrading your MCP SDK](docs/upgrading-sdks.md): `upgrade` and `--apply`
73
+ - [Testing tool calls](docs/tool-calls.md): `--probe-calls` and `call`
74
+ - [OAuth-protected servers](docs/oauth.md): `oauth login` and `--oauth`
75
+ - [Client profiles](docs/client-profiles.md): how client facts are sourced and used
76
+
77
+ ## Checking a server
78
+
79
+ ```bash
80
+ # stdio: pass the full command after --
81
+ npx mcp-use-compat -- node dist/server.js
82
+ npx mcp-use-compat -- uv run server.py
83
+ npx mcp-use-compat --env API_KEY=test -- npx -y @acme/mcp-server
84
+
85
+ # Streamable HTTP
86
+ npx mcp-use-compat --url https://example.com/mcp
87
+ npx mcp-use-compat --url https://example.com/mcp --header "Authorization: Bearer $TOKEN"
88
+
89
+ # Only some clients (ids or aliases such as claude, vscode, gemini)
90
+ npx mcp-use-compat --clients cursor,vscode,codex -- node dist/server.js
91
+
92
+ # Also try every published protocol version, and call read-only tools
93
+ npx mcp-use-compat --version-matrix --probe-calls -- node dist/server.js
94
+
95
+ # Save what the server exposed and re-check it later without running it
96
+ npx mcp-use-compat --save-snapshot snap.json -- node dist/server.js
97
+ npx mcp-use-compat --from-snapshot snap.json
98
+ ```
99
+
100
+ | Option | Default | |
101
+ |---|---|---|
102
+ | `--url <url>` | | Streamable HTTP endpoint instead of a stdio command |
103
+ | `-c, --clients <list>` | all | Comma-separated client ids or aliases |
104
+ | `-f, --format <md\|json\|github>` | `md` | `json` follows [`schema/report.schema.json`](schema/report.schema.json); `github` prints workflow annotations and a job summary |
105
+ | `-o, --out <file>` | stdout | Write the report to a file |
106
+ | `--fail-on <spec>` | `error` | `error`, `warn`, `none`, or check ids, globs and areas (`TOOL_*,auth`) |
107
+ | `--timeout <ms>` | `10000` | Per request; startup gets twice this |
108
+ | `--env KEY=VAL` | | Environment for the stdio server (repeatable) |
109
+ | `--header "Name: Value"` | | HTTP header for `--url` (repeatable) |
110
+ | `--cwd <dir>` | `.` | Working directory for the stdio server |
111
+ | `--oauth` | | Use credentials from `oauth login` (with `--url`) |
112
+ | `--probe-calls` | | Call tools that declare `readOnlyHint: true` and check their results |
113
+ | `--version-matrix` | | Also connect with each handshake version (2024-11-05 to 2025-11-25) |
114
+ | `--save-snapshot <file>`, `--from-snapshot <file>` | | Save or re-check a snapshot |
115
+ | `--no-auth-probe` | | Skip the unauthenticated OAuth discovery requests |
116
+ | `--offline` | | Don't look up the latest SDK versions |
117
+
118
+ Exit codes: `0` nothing matched `--fail-on`, `1` something did, `2` usage error, `3` the server could not be started or reached.
119
+
120
+ **What it sends to your server:** `initialize`, the tools, resources, resource templates and prompts list methods, `resources/read` for UI resources that tools link to, and a separate 2026-07-28 session (`server/discover` and the same list methods). Over HTTP it also makes one unauthenticated `initialize` POST and GETs the OAuth well-known URLs. For stdio servers it reads the project's manifest and lockfiles to find the MCP SDK, and looks up the latest SDK release on the package registry (skip with `--offline`).
121
+
122
+ **Tool calls happen only when you ask.** `--probe-calls` calls tools that explicitly declare `readOnlyHint: true`, never ones that also claim to be destructive or are named like writes (for example `place_order`), with the minimal arguments their schema requires. `call <tool>` calls exactly the tool you name:
123
+
124
+ ```bash
125
+ npx mcp-use-compat call get_quote --args '{"symbol":"INFY"}' -- node dist/server.js
126
+ ```
127
+
128
+ ## Keeping the SDK current
129
+
130
+ ```bash
131
+ npx mcp-use-compat upgrade -- node dist/server.js # what to upgrade, and the command
132
+ npx mcp-use-compat upgrade --apply -- node dist/server.js # run it, then re-check the server
133
+ npx mcp-use-compat upgrade --apply --major -- node dist/server.js
134
+ ```
135
+
136
+ `upgrade` finds the server's project from its command and working directory and detects the MCP SDK it uses: `@modelcontextprotocol/sdk`, `@modelcontextprotocol/server`, `mcp-use`, `fastmcp` and others on npm, `mcp` and `fastmcp` on PyPI, the Go SDKs and `rmcp`. It reads the installed version (`node_modules`, the virtualenv, lockfiles), looks up the latest release, and prints the command for the package manager the project uses (npm, pnpm, yarn, bun, uv, poetry, pipenv, pip, go or cargo).
137
+
138
+ `--apply` runs minor upgrades, and major ones only with `--major`. It updates `==` pins in requirements files, and when you pass the server command it checks the server before and after, then reports the protocol change and any breaking changes to its tools. Moving from `@modelcontextprotocol/sdk` v1 to the v2 packages is a migration, so it is explained but never applied automatically.
139
+
140
+ `check` uses the same detection: when a server negotiates an old protocol version, the finding includes the exact upgrade command.
141
+
142
+ ## Comparing versions
143
+
144
+ ```bash
145
+ npx mcp-use-compat check --save-snapshot before.json -- node old/server.js
146
+ npx mcp-use-compat check --save-snapshot after.json -- node dist/server.js
147
+ npx mcp-use-compat diff before.json after.json # exits 1 on breaking changes
148
+ ```
149
+
150
+ Breaking: removed tools, resources, templates, prompts or capabilities; new required arguments; arguments that become required or change type; removed enum values; removed or no-longer-guaranteed output fields; and compatibility errors that are new in the second snapshot. Description and annotation changes are reported as notable.
151
+
152
+ ## OAuth-protected servers
153
+
154
+ ```bash
155
+ npx mcp-use-compat oauth login --url https://example.com/mcp
156
+ npx mcp-use-compat check --oauth --url https://example.com/mcp
157
+ npx mcp-use-compat oauth status
158
+ npx mcp-use-compat oauth logout --url https://example.com/mcp
159
+ ```
160
+
161
+ `oauth login` runs the flow MCP clients use and reports each step: discovery, client registration (Client ID Metadata Documents, Dynamic Client Registration, or `--client-id` for a pre-registered client), the authorization request (PKCE S256 and `resource`), the callback (`state` and `iss`), the token exchange, and an authenticated `tools/list`. Credentials are stored in `~/.config/mcp-use-compat/oauth.json`, readable only by you. Runs with `--oauth` never register a client or open a browser; they refresh stored tokens or tell you to log in again.
162
+
163
+ ## Fixing tool definitions
164
+
165
+ ```bash
166
+ npx mcp-use-compat fix snap.json --out fixed-tools.json
167
+ npx mcp-use-compat fix snap.json --rename # also rename tools that clients would rewrite
168
+ ```
169
+
170
+ `fix` never invents content. It removes `description: null`, adds a missing `inputSchema`, sets an object-shaped root to `"type": "object"`, drops `required` entries that aren't properties, and removes invalid `required` values and empty `enum`s. Anything that needs judgement, such as a non-object root schema or a missing description, is listed as a TODO. Tool definitions live in your code, so apply the listed changes there.
171
+
172
+ ## In CI
173
+
174
+ Copy [`examples/github-workflow.yml`](examples/github-workflow.yml). With `--format github`, findings show up as annotations on the pull request, and `diff` can gate releases on breaking changes.
175
+
176
+ ## How results are decided
177
+
178
+ - **FAIL and WARN only for what the server was seen doing:** a null description, a colliding name, a missing OAuth field. A client limitation your server doesn't trigger is never reported as a failure.
179
+ - **Client-specific results cite a source.** If a client's behaviour is unknown, the check doesn't guess; it passes.
180
+ - **INFO** covers things worth knowing that break nothing today, such as no `server/discover` yet.
181
+ - Rules borrowed from other linters were checked against client source before being adopted. Most were wrong or unsourced and were left out.
182
+
183
+ Example rows from a report:
184
+
185
+ ```markdown
186
+ | Status | Check | Subject | Message |
187
+ |---|---|---|---|
188
+ | ❌ FAIL | `TOOL_NAME_CLIENT_COLLISION` | files.read, files_read | "files.read" and "files_read" both become "files_read" in Cursor, so only one of them is usable. |
189
+ | ⚠️ WARN | `SCHEMA_TOO_LARGE` | create_update_strategy | inputSchema is about 12540 characters; OpenAI Codex CLI compacts schemas over 5000. |
190
+ | ⚠️ WARN | `SDK_OUTDATED` | mcp | mcp 1.27.2 → 2.2.0 (major version: check the changelog for breaking changes); adds protocol 2026-07-28. |
191
+ ```
192
+
193
+ ## Clients
194
+
195
+ <!-- clients:start -->
196
+ | Client | stdio | HTTP | Tool list refresh | Resources | Prompts | OAuth | CIMD | MCP Apps UI | Limits |
197
+ |---|---|---|---|---|---|---|---|---|---|
198
+ | Claude Desktop / claude.ai | [✅](https://claude.com/docs/connectors/building/mcpb) | [✅](https://claude.com/docs/connectors/building/index) | ? | [✅](https://claude.com/docs/connectors/building/index) | [✅](https://claude.com/docs/connectors/building/index) | [✅](https://claude.com/docs/connectors/building/index) | [✅](https://claude.com/docs/connectors/building/authentication) | [✅](https://claude.com/docs/connectors/building/mcp-apps/getting-started) | chars `[A-Za-z0-9_-]` (unknown) |
199
+ | Claude Code | [✅](https://code.claude.com/docs/en/mcp) | [✅](https://code.claude.com/docs/en/mcp) | [✅](https://code.claude.com/docs/en/mcp) | [✅](https://code.claude.com/docs/en/mcp) | [✅](https://code.claude.com/docs/en/mcp) | [✅](https://code.claude.com/docs/en/mcp) | [✅](https://code.claude.com/docs/en/mcp) | [❌](https://code.claude.com/docs/en/mcp) | prefix `mcp__{server}__`; name ≤ 128 (unknown); chars `[A-Za-z0-9_-]` (unknown); descriptions ≤ 2048 chars |
200
+ | ChatGPT (Apps SDK / connectors) | [⚠️](https://developers.openai.com/apps-sdk/deploy/connect-chatgpt) | [✅](https://developers.openai.com/apps-sdk/deploy/connect-chatgpt) | [❌](https://developers.openai.com/apps-sdk/deploy/connect-chatgpt) | ? | ? | [✅](https://developers.openai.com/apps-sdk/build/auth) | [✅](https://developers.openai.com/apps-sdk/build/auth) | [✅](https://developers.openai.com/apps-sdk/reference) | none |
201
+ | Cursor | [✅](https://cursor.com/docs/mcp) | [✅](https://cursor.com/docs/mcp) | [⚠️](https://forum.cursor.com/t/mcp-server-regression-does-not-reload-tools-disconnect-does-nothing-ignores-mcp-json-changes-etc/166216) | [✅](https://cursor.com/docs/mcp) | [✅](https://cursor.com/docs/mcp) | [✅](https://cursor.com/docs/mcp) | ? | [✅](https://cursor.com/docs/mcp) | prefix `{server}`; name ≤ 60 (truncateWithHash); chars `[A-Za-z0-9_-]` (replace) |
202
+ | VS Code (GitHub Copilot) | [✅](https://code.visualstudio.com/api/extension-guides/ai/mcp) | [✅](https://code.visualstudio.com/api/extension-guides/ai/mcp) | [✅](https://github.com/microsoft/vscode/blob/a460613c57b4c1eb2bc8edc97be694e05ae286b2/src/vs/workbench/contrib/mcp/common/mcpServer.ts#L1224-L1227) | [✅](https://code.visualstudio.com/api/extension-guides/ai/mcp) | [✅](https://code.visualstudio.com/api/extension-guides/ai/mcp) | [✅](https://code.visualstudio.com/api/extension-guides/ai/mcp) | [✅](https://github.com/microsoft/vscode/blob/a460613c57b4c1eb2bc8edc97be694e05ae286b2/src/vs/workbench/api/browser/mainThreadAuthentication.ts#L178-L192) | [✅](https://code.visualstudio.com/api/extension-guides/ai/mcp) | prefix `mcp_{server}_`; name ≤ 64 (truncate); chars `[A-Za-z0-9_-]` (replace); ≤ 128 tools |
203
+ | OpenCode | [✅](https://opencode.ai/docs/mcp-servers/) | [✅](https://github.com/anomalyco/opencode/blob/a42f393c850bec0c0f395fb91bf19b1ee8b31666/packages/opencode/src/mcp/index.ts#L268-L283) | [✅](https://github.com/anomalyco/opencode/blob/a42f393c850bec0c0f395fb91bf19b1ee8b31666/packages/opencode/src/mcp/index.ts#L461-L471) | [✅](https://github.com/anomalyco/opencode/blob/a42f393c850bec0c0f395fb91bf19b1ee8b31666/packages/opencode/src/mcp/catalog.ts#L130-L134) | [✅](https://github.com/anomalyco/opencode/blob/a42f393c850bec0c0f395fb91bf19b1ee8b31666/packages/opencode/src/mcp/catalog.ts#L122-L126) | [✅](https://opencode.ai/docs/mcp-servers/) | ? | [❌](https://github.com/anomalyco/opencode/blob/a42f393c850bec0c0f395fb91bf19b1ee8b31666/packages/opencode/src/mcp/) | prefix `{server}_`; chars `[A-Za-z0-9_-]` (replace) |
204
+ | OpenAI Codex CLI | [✅](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) | [✅](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) | [❌](https://github.com/openai/codex/blob/8f195c93d7e7acfef95acf273f0e49cce917e291/codex-rs/rmcp-client/src/logging_client_handler.rs#L82-L92) | [✅](https://github.com/openai/codex/blob/8f195c93d7e7acfef95acf273f0e49cce917e291/codex-rs/core/src/tools/handlers/mcp_resource/read_mcp_resource.rs) | ? | [✅](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) | [✅](https://learn.chatgpt.com/docs/extend/mcp?surface=cli) | ? | prefix `mcp__{server}__`; name ≤ 128 (truncateWithHash); chars `[A-Za-z0-9_]` (replaceUnique) |
205
+ | Gemini CLI | [✅](https://github.com/google-gemini/gemini-cli/blob/2fe7c2d3f065dc40ad573d50b2091116f8a4aa18/docs/tools/mcp-server.md#L55-L61) | [✅](https://github.com/google-gemini/gemini-cli/blob/2fe7c2d3f065dc40ad573d50b2091116f8a4aa18/docs/tools/mcp-server.md#L55-L61) | [✅](https://github.com/google-gemini/gemini-cli/blob/2fe7c2d3f065dc40ad573d50b2091116f8a4aa18/packages/core/src/tools/mcp-client.ts#L417) | [✅](https://github.com/google-gemini/gemini-cli/blob/2fe7c2d3f065dc40ad573d50b2091116f8a4aa18/docs/tools/mcp-server.md#L63-L88) | [✅](https://github.com/google-gemini/gemini-cli/blob/2fe7c2d3f065dc40ad573d50b2091116f8a4aa18/docs/tools/mcp-server.md#L1030-L1105) | [✅](https://github.com/google-gemini/gemini-cli/blob/2fe7c2d3f065dc40ad573d50b2091116f8a4aa18/docs/tools/mcp-server.md#L271-L300) | ? | [❌](https://github.com/google-gemini/gemini-cli/blob/2fe7c2d3f065dc40ad573d50b2091116f8a4aa18/packages/core/src/tools/) | prefix `mcp_{server}_`; name ≤ 63 (truncateMiddle); chars `[A-Za-z0-9_.:-]` (replace) |
206
+ | Cline | [✅](https://github.com/cline/cline/blob/252082b9e93b4f91253876391e35b4c13326f5e6/apps/vscode/src/services/mcp/constants.ts#L4) | [✅](https://github.com/cline/cline/blob/252082b9e93b4f91253876391e35b4c13326f5e6/apps/vscode/src/services/mcp/constants.ts#L4) | [✅](https://github.com/cline/cline/blob/252082b9e93b4f91253876391e35b4c13326f5e6/apps/vscode/src/services/mcp/McpHub.ts#L767-L769) | [✅](https://github.com/cline/cline/blob/252082b9e93b4f91253876391e35b4c13326f5e6/apps/vscode/src/services/mcp/McpHub.ts#L915-L930) | [✅](https://github.com/cline/cline/blob/252082b9e93b4f91253876391e35b4c13326f5e6/apps/vscode/src/services/mcp/McpHub.ts#L974-L990) | [✅](https://github.com/cline/cline/blob/252082b9e93b4f91253876391e35b4c13326f5e6/apps/vscode/src/services/mcp/McpOAuthManager.ts) | ? | ? | prefix `{server}__`; name ≤ 64 (truncateWithHash); chars `[A-Za-z0-9_-]` (truncateWithHash) |
207
+ | Goose | [✅](https://github.com/block/goose/blob/04ed836c8cde23e540cc77d256992e00be99298b/crates/goose/src/agents/extension.rs#L157-L158) | [✅](https://github.com/block/goose/blob/04ed836c8cde23e540cc77d256992e00be99298b/crates/goose/src/agents/extension.rs#L207-L208) | [✅](https://github.com/block/goose/blob/04ed836c8cde23e540cc77d256992e00be99298b/crates/goose/src/agents/mcp_client.rs#L377-L379) | [✅](https://github.com/block/goose/blob/04ed836c8cde23e540cc77d256992e00be99298b/crates/goose/src/agents/extension_manager/mod.rs#L1067) | [✅](https://github.com/block/goose/blob/04ed836c8cde23e540cc77d256992e00be99298b/crates/goose/src/agents/extension_manager/mod.rs#L1450) | [✅](https://github.com/block/goose/blob/04ed836c8cde23e540cc77d256992e00be99298b/crates/goose/src/oauth/mod.rs#L255-L276) | [✅](https://github.com/block/goose/blob/04ed836c8cde23e540cc77d256992e00be99298b/crates/goose/src/oauth/mod.rs#L273-L275) | [✅](https://github.com/block/goose/blob/04ed836c8cde23e540cc77d256992e00be99298b/crates/goose/src/agents/mcp_client.rs#L300-L311) | prefix `{server}__` |
208
+ | Continue | [✅](https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/context/mcp/MCPConnection.ts#L391) | [✅](https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/context/mcp/MCPConnection.ts#L535-L550) | [❌](https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/context/mcp/MCPConnection.ts#L286) | [✅](https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/context/mcp/MCPConnection.ts#L292-L300) | [✅](https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/context/mcp/MCPConnection.ts#L343-L350) | [✅](https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/context/mcp/MCPOauth.ts) | ? | [⚠️](https://github.com/continuedev/continue/blob/5522c6f44ca0ac3528b37244818fbfa39b5af470/core/tools/callTool.ts#L115-L142) | prefix `{server}_` |
209
+ | Windsurf / Devin Desktop | [✅](https://docs.devin.ai/desktop/cascade/mcp) | [✅](https://docs.devin.ai/desktop/cascade/mcp) | ? | [✅](https://docs.devin.ai/desktop/cascade/mcp) | [✅](https://docs.devin.ai/desktop/cascade/mcp) | [✅](https://docs.devin.ai/desktop/cascade/mcp) | ? | ? | ≤ 100 tools |
210
+
211
+ ✅ supported · ❌ not supported · ⚠️ partial or unreliable · ? unknown. Every mark links to its source. Facts verified 2026-09-26 to 2026-09-27; run `mcp-use-compat list-clients` for details.
212
+ <!-- clients:end -->
213
+
214
+ Client behaviour changes quickly. If a fact is wrong or stale, please open an issue or PR against `src/profiles/` with a source.
215
+
216
+ ## Checks
217
+
218
+ <!-- checks:start -->
219
+ **transport**
220
+
221
+ | Check | What it verifies |
222
+ |---|---|
223
+ | `TRANSPORT_CONNECT_FAILED` | The server starts and answers initialize |
224
+ | `TRANSPORT_AUTH_REQUIRED` | Notes when an HTTP server needs credentials before initialize |
225
+ | `TRANSPORT_STDOUT_POLLUTION` | stdout carries only JSON-RPC messages |
226
+ | `TRANSPORT_SLOW_STARTUP` | initialize answers within 5s of launch |
227
+ | `TRANSPORT_SLOW_LIST` | list requests answer within 3s |
228
+ | `TRANSPORT_STDERR_ERRORS` | stderr shows no errors during the session |
229
+
230
+ **protocol**
231
+
232
+ | Check | What it verifies |
233
+ |---|---|
234
+ | `PROTOCOL_MODERN_ONLY` | Server still accepts the initialize handshake most clients use |
235
+ | `PROTOCOL_DISCOVER_MISSING` | Server implements server/discover (required from protocol 2026-07-28) |
236
+ | `PROTOCOL_MODERN_RESULT_TYPE` | 2026-07-28 results carry a valid resultType |
237
+ | `PROTOCOL_MODERN_CACHE_FIELDS` | 2026-07-28 list and discover results carry ttlMs and cacheScope |
238
+ | `PROTOCOL_MODERN_SERVERINFO` | 2026-07-28 results identify the server in _meta |
239
+ | `PROTOCOL_MODERN_VERSION_ERROR` | 2026-07-28 servers reject unsupported versions with UnsupportedProtocolVersion (-32022) |
240
+ | `PROTOCOL_MODERN_SURFACE_DIFFERS` | Tools are the same over the initialize handshake and 2026-07-28 |
241
+ | `PROTOCOL_VERSION_UNSUPPORTED` | Negotiated protocol version is one the SDK supports |
242
+ | `PROTOCOL_VERSION_OLD` | Server speaks the latest protocol version |
243
+ | `PROTOCOL_VERSIONS_REJECTED` | Server handles every published protocol version clients may request (--version-matrix) |
244
+ | `PROTOCOL_VERSION_SURFACE_DIFFERS` | The tool list is the same whichever protocol version a client negotiates |
245
+ | `PROTOCOL_SERVERINFO_MISSING` | initialize returns serverInfo with name and version |
246
+ | `PROTOCOL_CAPABILITY_UNDECLARED` | Every feature the server serves is declared in capabilities |
247
+ | `PROTOCOL_CAPABILITY_BROKEN` | Every declared capability's list method works |
248
+ | `PROTOCOL_PAGINATION_BROKEN` | List pagination terminates |
249
+
250
+ **tools**
251
+
252
+ | Check | What it verifies |
253
+ |---|---|
254
+ | `TOOL_NONE` | A server declaring tools exposes at least one |
255
+ | `TOOL_NAME_INVALID` | Tool names match the MCP spec format (A-Z a-z 0-9 _ - ., 1-128 chars) |
256
+ | `TOOL_NAME_DUPLICATE` | Tool names are unique |
257
+ | `TOOL_NAME_CLIENT_CHARS` | Tool names use only characters each client accepts as-is |
258
+ | `TOOL_NAME_TOO_LONG` | Prefixed tool names fit each client's length limit |
259
+ | `TOOL_NAME_CLIENT_COLLISION` | Tool names stay unique after a client renames or truncates them |
260
+ | `TOOL_COUNT_OVER_LIMIT` | Tool count fits each client's limit |
261
+ | `TOOL_DESCRIPTION_MISSING` | Every tool has a non-empty description |
262
+ | `TOOL_DESCRIPTION_SHORT` | Tool descriptions are at least 20 characters |
263
+ | `TOOL_DESCRIPTION_TRUNCATED` | Tool descriptions and server instructions fit each client's length limit |
264
+ | `TOOL_STRUCTURED_OUTPUT_HANDLING` | Notes how each client passes structured tool output to the model |
265
+ | `TOOL_ANNOTATIONS_CONFLICT` | Tool annotations are consistent with each other and with the tool's name |
266
+ | `TOOL_TITLE_MISSING` | Tools have a human-readable title |
267
+ | `TOOL_ANNOTATIONS_MISSING` | Read-only tools declare readOnlyHint |
268
+
269
+ **schema**
270
+
271
+ | Check | What it verifies |
272
+ |---|---|
273
+ | `SCHEMA_MISSING` | Every tool has an inputSchema object |
274
+ | `SCHEMA_NOT_OBJECT` | inputSchema and outputSchema have type "object" at the root |
275
+ | `SCHEMA_INVALID` | Schemas are valid JSON Schema |
276
+ | `SCHEMA_REQUIRED_UNKNOWN` | required only lists declared properties |
277
+ | `SCHEMA_TOP_LEVEL_COMBINATOR` | inputSchema has no root-level oneOf/anyOf/allOf/not |
278
+ | `SCHEMA_UNSUPPORTED_KEYWORD` | Schemas avoid keywords a client rejects or drops |
279
+ | `SCHEMA_PROPERTY_NAME_REJECTED` | Top-level input property names match each client's rules |
280
+ | `SCHEMA_EMPTY_ENUM` | enum lists have at least one value |
281
+ | `SCHEMA_ROOT_COMBINATOR_CLIENT` | Root-level oneOf/anyOf/allOf is shaped the way each client can handle |
282
+ | `SCHEMA_TYPE_ARRAY_CLIENT` | Type arrays (e.g. ["string","null"]) avoided for clients that fail on them |
283
+ | `SCHEMA_KEYWORDS_DROPPED` | Notes schema constraints a client removes before the model sees them |
284
+ | `SCHEMA_TOO_LARGE` | inputSchema fits each client's size limit |
285
+ | `SCHEMA_PROPERTY_NO_TYPE` | Every input property declares a type |
286
+ | `SCHEMA_TOO_DEEP` | inputSchema nests at most 5 levels |
287
+
288
+ **discovery**
289
+
290
+ | Check | What it verifies |
291
+ |---|---|
292
+ | `DISCOVERY_TOOLS_LIST_CHANGED` | Notes clients that ignore tools/list_changed when the server declares it |
293
+ | `DISCOVERY_RESOURCES_LIST_CHANGED` | Notes clients that ignore resources/list_changed when the server declares it |
294
+ | `DISCOVERY_PROMPTS_LIST_CHANGED` | Notes clients that ignore prompts/list_changed when the server declares it |
295
+ | `DISCOVERY_RESOURCES_UNSUPPORTED` | Clients without resources support are flagged when the server exposes resources |
296
+ | `DISCOVERY_PROMPTS_UNSUPPORTED` | Clients without prompts support are flagged when the server exposes prompts |
297
+
298
+ **resources**
299
+
300
+ | Check | What it verifies |
301
+ |---|---|
302
+ | `RESOURCE_URI_INVALID` | Resource URIs are absolute and parse |
303
+ | `RESOURCE_URI_DUPLICATE` | Resource URIs are unique |
304
+ | `RESOURCE_NAME_MISSING` | Resources and templates have a name (required by the spec) |
305
+ | `RESOURCE_MIME_MISSING` | Resources declare a mimeType |
306
+ | `RESOURCE_TEMPLATE_INVALID` | Resource templates are valid RFC 6570 URI templates |
307
+
308
+ **ui**
309
+
310
+ | Check | What it verifies |
311
+ |---|---|
312
+ | `UI_RESOURCE_MIME` | UI resources use text/html;profile=mcp-app |
313
+ | `UI_RESOURCE_SCHEME` | UI resources use the ui:// scheme |
314
+ | `UI_TOOL_LINK_BROKEN` | UI resources that tools link to can be read |
315
+ | `UI_TOOL_LINK_KEY` | Tools link UI with _meta.ui.resourceUri |
316
+ | `UI_CSP_LOCAL_ORIGIN` | A remote server's UI resources don't point their CSP at localhost |
317
+ | `UI_CSP_INSECURE` | UI resource CSP origins use HTTPS |
318
+ | `UI_VISIBILITY_INVALID` | Tool _meta.ui.visibility only uses "model" and "app" |
319
+ | `UI_UNSUPPORTED` | Clients that don't render MCP Apps are flagged when tools rely on UI |
320
+
321
+ **auth**
322
+
323
+ | Check | What it verifies |
324
+ |---|---|
325
+ | `AUTH_CHALLENGE_MISSING` | 401 responses carry a WWW-Authenticate challenge |
326
+ | `AUTH_PRM_MISSING` | Protected resource metadata (RFC 9728) is discoverable |
327
+ | `AUTH_PRM_INVALID` | Protected resource metadata names the resource and its authorization servers |
328
+ | `AUTH_ASM_MISSING` | Authorization server metadata (RFC 8414 / OIDC) is discoverable |
329
+ | `AUTH_ISSUER_MISMATCH` | Authorization server metadata issuer matches the advertised issuer |
330
+ | `AUTH_PKCE_S256_MISSING` | Authorization server advertises PKCE S256 |
331
+ | `AUTH_CLIENT_REGISTRATION` | Clients can register themselves (CIMD or DCR) |
332
+ | `AUTH_INSECURE_URL` | Remote servers and OAuth endpoints use HTTPS |
333
+
334
+ **calls**
335
+
336
+ | Check | What it verifies |
337
+ |---|---|
338
+ | `CALL_RESULT_INVALID` | tools/call results match the MCP result schema |
339
+ | `CALL_OUTPUT_SCHEMA_MISMATCH` | Tools with an outputSchema return matching structuredContent |
340
+ | `CALL_STRUCTURED_WITHOUT_TEXT` | Structured results also carry a text copy |
341
+ | `CALL_RESULT_TOO_LARGE` | Tool results fit each client's result size limit |
342
+ | `CALL_SLOW` | Tool calls finish well within each client's timeout |
343
+ | `CALL_FAILED` | Reports tool calls that errored |
344
+
345
+ **sdk**
346
+
347
+ | Check | What it verifies |
348
+ |---|---|
349
+ | `SDK_OUTDATED` | The server's MCP SDK is the latest release |
350
+ <!-- checks:end -->
351
+
352
+ ## Protocol versions
353
+
354
+ Every published revision is covered:
355
+
356
+ - **2024-11-05 to 2025-11-25** (the `initialize` handshake, which current clients use): the checks run over the latest version the server supports. `--version-matrix` also connects once per revision and reports versions the server rejects, answers incorrectly, or serves different tools on.
357
+ - **2026-07-28** (stateless): always probed in a separate session with the `_meta` envelope and the required HTTP headers. For servers that speak it, the tool checks `resultType`, `ttlMs` and `cacheScope`, `serverInfo` in `_meta`, the `-32022` unsupported-version error, and whether the tools match the handshake's. Servers that only speak 2026-07-28 get every check run over the new protocol.
358
+
359
+ With `--version-matrix` the report shows a line like `Protocol versions: 2024-11-05 ✅ · 2025-03-26 ✅ · 2025-06-18 ✅ · 2025-11-25 ✅ · 2026-07-28 ❌`.
360
+
361
+ ## Contributing
362
+
363
+ Corrections to client facts are the most useful contribution: client behaviour changes often. See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, how facts must be sourced, and how to add a check.
364
+
365
+ ```bash
366
+ npm install
367
+ npm test # unit, fixture and end-to-end tests
368
+ npm run readme # regenerate the Clients and Checks sections
369
+ ```
370
+
371
+ Security issues: see [SECURITY.md](SECURITY.md).
372
+
373
+ ## License
374
+
375
+ [MIT](LICENSE)
@@ -0,0 +1,2 @@
1
+ export declare const authChecks: import("./types.js").Check[];
2
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/checks/auth.ts"],"names":[],"mappings":"AAqBA,eAAO,MAAM,UAAU,8BA4NtB,CAAC"}