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
@@ -0,0 +1,229 @@
1
+ import { isObject, str } from "./util.js";
2
+ import { defineCheck } from "./types.js";
3
+ const DISCOVERY_SPEC = "https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/authorization-server-discovery";
4
+ const REGISTRATION_SPEC = "https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/client-registration";
5
+ /** The server demanded credentials for an unauthenticated initialize. */
6
+ const protectedServer = (s) => {
7
+ const status = s.http?.unauthenticated.status;
8
+ return status === 401 || status === 403;
9
+ };
10
+ const okJson = (r) => r.status === 200 && isObject(r.json);
11
+ const prm = (s) => s.http?.protectedResource.find(okJson);
12
+ const asm = (s) => s.http?.authorizationServer.find(okJson);
13
+ const json = (r) => (r?.json ?? {});
14
+ const withoutTrailingSlash = (u) => u.replace(/\/+$/, "");
15
+ export const authChecks = [
16
+ defineCheck({
17
+ id: "AUTH_CHALLENGE_MISSING",
18
+ area: "auth",
19
+ description: "401 responses carry a WWW-Authenticate challenge",
20
+ appliesTo: protectedServer,
21
+ run: (s) => s.http.unauthenticated.headers?.["www-authenticate"]
22
+ ? []
23
+ : [
24
+ {
25
+ checkId: "AUTH_CHALLENGE_MISSING",
26
+ severity: "warn",
27
+ message: `HTTP ${s.http.unauthenticated.status} without a WWW-Authenticate header; clients must guess where the protected resource metadata is.`,
28
+ affects: ["oauth"],
29
+ source: DISCOVERY_SPEC,
30
+ fix: 'Return WWW-Authenticate: Bearer resource_metadata="https://<host>/.well-known/oauth-protected-resource/<path>".',
31
+ },
32
+ ],
33
+ }),
34
+ defineCheck({
35
+ id: "AUTH_PRM_MISSING",
36
+ area: "auth",
37
+ description: "Protected resource metadata (RFC 9728) is discoverable",
38
+ appliesTo: protectedServer,
39
+ run: (s) => prm(s)
40
+ ? []
41
+ : [
42
+ {
43
+ checkId: "AUTH_PRM_MISSING",
44
+ severity: "error",
45
+ message: "No protected resource metadata found, so clients can't find the authorization server.",
46
+ evidence: { tried: s.http.protectedResource.map((r) => `${r.url} → ${r.status ?? r.error}`) },
47
+ affects: ["oauth"],
48
+ source: DISCOVERY_SPEC,
49
+ fix: "Serve /.well-known/oauth-protected-resource (path-suffixed for your MCP endpoint) with resource and authorization_servers.",
50
+ },
51
+ ],
52
+ }),
53
+ defineCheck({
54
+ id: "AUTH_PRM_INVALID",
55
+ area: "auth",
56
+ description: "Protected resource metadata names the resource and its authorization servers",
57
+ appliesTo: (s) => protectedServer(s) && !!prm(s),
58
+ run: (s) => {
59
+ const metadata = json(prm(s));
60
+ const findings = [];
61
+ const servers = metadata.authorization_servers;
62
+ if (!Array.isArray(servers) || !servers.some((a) => typeof a === "string")) {
63
+ findings.push({
64
+ checkId: "AUTH_PRM_INVALID",
65
+ severity: "error",
66
+ message: "Protected resource metadata has no authorization_servers.",
67
+ affects: ["oauth"],
68
+ source: DISCOVERY_SPEC,
69
+ fix: 'Add "authorization_servers": ["https://<issuer>"].',
70
+ });
71
+ }
72
+ const resource = str(metadata.resource);
73
+ const url = s.target.kind === "http" ? s.target.url : "";
74
+ if (!resource) {
75
+ findings.push({
76
+ checkId: "AUTH_PRM_INVALID",
77
+ severity: "error",
78
+ message: "Protected resource metadata has no resource.",
79
+ affects: ["oauth"],
80
+ source: DISCOVERY_SPEC,
81
+ fix: `Add "resource": "${url}".`,
82
+ });
83
+ }
84
+ else if (withoutTrailingSlash(resource) !== withoutTrailingSlash(url)) {
85
+ findings.push({
86
+ checkId: "AUTH_PRM_INVALID",
87
+ severity: "error",
88
+ subject: resource,
89
+ message: `resource is ${resource} but the server is at ${url}; clients must reject metadata for a different resource (RFC 9728 §3.3).`,
90
+ affects: ["oauth"],
91
+ source: DISCOVERY_SPEC,
92
+ fix: "Set resource to the exact MCP endpoint URL.",
93
+ });
94
+ }
95
+ return findings;
96
+ },
97
+ }),
98
+ defineCheck({
99
+ id: "AUTH_ASM_MISSING",
100
+ area: "auth",
101
+ description: "Authorization server metadata (RFC 8414 / OIDC) is discoverable",
102
+ appliesTo: (s) => protectedServer(s) && s.http.authorizationServer.length > 0,
103
+ run: (s) => asm(s)
104
+ ? []
105
+ : [
106
+ {
107
+ checkId: "AUTH_ASM_MISSING",
108
+ severity: "error",
109
+ message: "No authorization server metadata at any well-known location.",
110
+ evidence: { tried: s.http.authorizationServer.map((r) => `${r.url} → ${r.status ?? r.error}`) },
111
+ affects: ["oauth"],
112
+ source: DISCOVERY_SPEC,
113
+ fix: "Serve /.well-known/oauth-authorization-server or /.well-known/openid-configuration for the issuer.",
114
+ },
115
+ ],
116
+ }),
117
+ defineCheck({
118
+ id: "AUTH_ISSUER_MISMATCH",
119
+ area: "auth",
120
+ description: "Authorization server metadata issuer matches the advertised issuer",
121
+ appliesTo: (s) => protectedServer(s) && !!asm(s),
122
+ run: (s) => {
123
+ const servers = json(prm(s)).authorization_servers;
124
+ // Malformed authorization_servers is reported by AUTH_PRM_INVALID.
125
+ const advertised = Array.isArray(servers) ? servers.find((a) => typeof a === "string") : undefined;
126
+ const issuer = str(json(asm(s)).issuer);
127
+ if (!advertised || (issuer && withoutTrailingSlash(issuer) === withoutTrailingSlash(advertised)))
128
+ return [];
129
+ return [
130
+ {
131
+ checkId: "AUTH_ISSUER_MISMATCH",
132
+ severity: "error",
133
+ message: `Metadata issuer is ${JSON.stringify(issuer ?? null)} but the resource names ${advertised}; spec-following clients reject the authorization server.`,
134
+ affects: ["oauth"],
135
+ source: DISCOVERY_SPEC,
136
+ fix: "Make the issuer in the metadata identical to the URL in authorization_servers.",
137
+ },
138
+ ];
139
+ },
140
+ }),
141
+ defineCheck({
142
+ id: "AUTH_PKCE_S256_MISSING",
143
+ area: "auth",
144
+ description: "Authorization server advertises PKCE S256",
145
+ appliesTo: (s) => protectedServer(s) && !!asm(s),
146
+ run: (s) => {
147
+ const methods = json(asm(s)).code_challenge_methods_supported;
148
+ if (Array.isArray(methods) && methods.includes("S256"))
149
+ return [];
150
+ return [
151
+ {
152
+ checkId: "AUTH_PKCE_S256_MISSING",
153
+ severity: "error",
154
+ message: Array.isArray(methods)
155
+ ? `code_challenge_methods_supported is ${JSON.stringify(methods)} without S256.`
156
+ : "Authorization server metadata omits code_challenge_methods_supported; MCP clients must refuse to proceed (ChatGPT rejects the server).",
157
+ affects: ["oauth"],
158
+ source: DISCOVERY_SPEC,
159
+ fix: 'Advertise "code_challenge_methods_supported": ["S256"].',
160
+ },
161
+ ];
162
+ },
163
+ }),
164
+ defineCheck({
165
+ id: "AUTH_CLIENT_REGISTRATION",
166
+ area: "auth",
167
+ description: "Clients can register themselves (CIMD or DCR)",
168
+ appliesTo: (s) => protectedServer(s) && !!asm(s),
169
+ run: (s) => {
170
+ const metadata = json(asm(s));
171
+ const cimd = metadata.client_id_metadata_document_supported === true;
172
+ const dcr = typeof metadata.registration_endpoint === "string";
173
+ if (cimd)
174
+ return [];
175
+ if (dcr) {
176
+ return [
177
+ {
178
+ checkId: "AUTH_CLIENT_REGISTRATION",
179
+ severity: "info",
180
+ message: "Only Dynamic Client Registration is offered. It works with today's clients but is deprecated in protocol 2026-07-28 in favour of Client ID Metadata Documents.",
181
+ source: REGISTRATION_SPEC,
182
+ fix: "Also advertise client_id_metadata_document_supported: true.",
183
+ },
184
+ ];
185
+ }
186
+ return [
187
+ {
188
+ checkId: "AUTH_CLIENT_REGISTRATION",
189
+ severity: "warn",
190
+ message: "Neither Client ID Metadata Documents nor Dynamic Client Registration is offered, so users must obtain and paste a client ID/secret for every client.",
191
+ affects: ["oauth"],
192
+ source: REGISTRATION_SPEC,
193
+ fix: "Support CIMD (client_id_metadata_document_supported: true) or a registration_endpoint.",
194
+ },
195
+ ];
196
+ },
197
+ }),
198
+ defineCheck({
199
+ id: "AUTH_INSECURE_URL",
200
+ area: "auth",
201
+ description: "Remote servers and OAuth endpoints use HTTPS",
202
+ appliesTo: (s) => s.target.kind === "http",
203
+ run: (s) => {
204
+ const urls = [
205
+ s.target.kind === "http" ? s.target.url : "",
206
+ ...Object.entries(json(asm(s)))
207
+ .filter(([k]) => k.endsWith("_endpoint"))
208
+ .map(([, v]) => str(v) ?? ""),
209
+ ];
210
+ const insecure = urls.filter((u) => {
211
+ try {
212
+ const url = new URL(u);
213
+ return url.protocol === "http:" && !["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
214
+ }
215
+ catch {
216
+ return false;
217
+ }
218
+ });
219
+ return [...new Set(insecure)].map((u) => ({
220
+ checkId: "AUTH_INSECURE_URL",
221
+ severity: "warn",
222
+ subject: u,
223
+ message: "Plain http:// on a non-loopback host; OAuth 2.1 requires HTTPS and hosted clients will refuse it.",
224
+ fix: "Serve over HTTPS.",
225
+ }));
226
+ },
227
+ }),
228
+ ];
229
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/checks/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /** Validates structuredContent against outputSchema; undefined if the schema can't be compiled. */
2
+ export declare function validateStructured(schema: Record<string, unknown>, value: unknown): string[] | undefined;
3
+ export declare const callChecks: import("./types.js").Check[];
4
+ //# sourceMappingURL=calls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calls.d.ts","sourceRoot":"","sources":["../../src/checks/calls.ts"],"names":[],"mappings":"AAmBA,mGAAmG;AACnG,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAUxG;AAID,eAAO,MAAM,UAAU,8BAyKtB,CAAC"}
@@ -0,0 +1,192 @@
1
+ import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js";
2
+ import { Ajv } from "ajv";
3
+ import { Ajv2020 } from "ajv/dist/2020.js";
4
+ import { isObject, items } from "./util.js";
5
+ import { defineCheck } from "./types.js";
6
+ const ajv2020 = new Ajv2020({ strict: false, allErrors: false, logger: false });
7
+ const ajv07 = new Ajv({ strict: false, allErrors: false, logger: false });
8
+ const answered = (s) => (s.calls ?? []).filter((c) => c.result);
9
+ const hasCalls = (s) => (s.calls?.length ?? 0) > 0;
10
+ const isToolError = (c) => c.result?.isError === true;
11
+ function outputSchemaFor(s, tool) {
12
+ const t = items(s, "tools").find((t) => t.name === tool);
13
+ return t && isObject(t.outputSchema) ? t.outputSchema : undefined;
14
+ }
15
+ /** Validates structuredContent against outputSchema; undefined if the schema can't be compiled. */
16
+ export function validateStructured(schema, value) {
17
+ const validator = /draft-0[67]/.test(String(schema.$schema ?? "")) ? ajv07 : ajv2020;
18
+ let validate;
19
+ try {
20
+ validate = validator.compile(schema);
21
+ }
22
+ catch {
23
+ return undefined;
24
+ }
25
+ if (validate(value))
26
+ return [];
27
+ return (validate.errors ?? []).map((e) => `${e.instancePath || "/"} ${e.message ?? "is invalid"}`);
28
+ }
29
+ const call = (c) => `${c.tool}(${JSON.stringify(c.args)})`;
30
+ export const callChecks = [
31
+ defineCheck({
32
+ id: "CALL_RESULT_INVALID",
33
+ area: "calls",
34
+ description: "tools/call results match the MCP result schema",
35
+ appliesTo: hasCalls,
36
+ run: (s) => answered(s).flatMap((c) => {
37
+ const parsed = CallToolResultSchema.safeParse(c.result);
38
+ if (parsed.success)
39
+ return [];
40
+ const issue = parsed.error.issues[0];
41
+ return [
42
+ {
43
+ checkId: "CALL_RESULT_INVALID",
44
+ severity: "error",
45
+ subject: c.tool,
46
+ message: `Result of ${call(c)} is not a valid CallToolResult (${issue?.path.join(".") || "result"}: ${issue?.message}); SDK-based clients throw instead of showing it.`,
47
+ evidence: { issues: parsed.error.issues.slice(0, 5) },
48
+ fix: 'Return { content: [{ type: "text", text: "..." }] } (plus structuredContent/isError as needed).',
49
+ },
50
+ ];
51
+ }),
52
+ }),
53
+ defineCheck({
54
+ id: "CALL_OUTPUT_SCHEMA_MISMATCH",
55
+ area: "calls",
56
+ description: "Tools with an outputSchema return matching structuredContent",
57
+ appliesTo: (s) => answered(s).some((c) => outputSchemaFor(s, c.tool)),
58
+ run: (s) => answered(s).flatMap((c) => {
59
+ const schema = outputSchemaFor(s, c.tool);
60
+ if (!schema || isToolError(c))
61
+ return [];
62
+ if (!("structuredContent" in c.result)) {
63
+ return [
64
+ {
65
+ checkId: "CALL_OUTPUT_SCHEMA_MISMATCH",
66
+ severity: "error",
67
+ subject: c.tool,
68
+ message: `${c.tool} declares an outputSchema but ${call(c)} returned no structuredContent; the spec requires it, and SDK clients reject the result.`,
69
+ fix: "Return structuredContent matching outputSchema (and keep a text copy for older clients).",
70
+ },
71
+ ];
72
+ }
73
+ const errors = validateStructured(schema, c.result.structuredContent);
74
+ if (!errors?.length)
75
+ return [];
76
+ return [
77
+ {
78
+ checkId: "CALL_OUTPUT_SCHEMA_MISMATCH",
79
+ severity: "error",
80
+ subject: c.tool,
81
+ message: `structuredContent from ${call(c)} doesn't match outputSchema: ${errors.slice(0, 3).join("; ")}. SDK clients reject such results.`,
82
+ evidence: { errors },
83
+ fix: "Make the returned data match outputSchema, or update the schema.",
84
+ },
85
+ ];
86
+ }),
87
+ }),
88
+ defineCheck({
89
+ id: "CALL_STRUCTURED_WITHOUT_TEXT",
90
+ area: "calls",
91
+ description: "Structured results also carry a text copy",
92
+ appliesTo: (s) => answered(s).some((c) => c.result && "structuredContent" in c.result),
93
+ run: (s, { profiles }) => answered(s).flatMap((c) => {
94
+ const content = Array.isArray(c.result.content) ? c.result.content : [];
95
+ if (!("structuredContent" in c.result) || content.some((i) => isObject(i) && i.type === "text"))
96
+ return [];
97
+ const textOnly = profiles.filter((p) => p.limits.structuredContent?.value === "textOnly");
98
+ return [
99
+ {
100
+ checkId: "CALL_STRUCTURED_WITHOUT_TEXT",
101
+ severity: "warn",
102
+ subject: c.tool,
103
+ message: `${call(c)} returned structuredContent with no text content. The spec says tools SHOULD also return the JSON as text for clients that don't read structuredContent.`,
104
+ fix: 'Add { type: "text", text: JSON.stringify(structuredContent) } to content.',
105
+ },
106
+ ...textOnly.map((p) => ({
107
+ checkId: "CALL_STRUCTURED_WITHOUT_TEXT",
108
+ severity: "error",
109
+ subject: c.tool,
110
+ client: p.id,
111
+ source: p.limits.structuredContent.source,
112
+ message: `${p.displayName} only passes text content to the model, so it gets an empty result from ${c.tool}.`,
113
+ fix: 'Add { type: "text", text: JSON.stringify(structuredContent) } to content.',
114
+ })),
115
+ ];
116
+ }),
117
+ }),
118
+ defineCheck({
119
+ id: "CALL_RESULT_TOO_LARGE",
120
+ area: "calls",
121
+ description: "Tool results fit each client's result size limit",
122
+ appliesTo: (s) => answered(s).length > 0,
123
+ run: (s, { profiles }) => profiles.flatMap((p) => {
124
+ const limit = p.limits.maxToolResult;
125
+ if (!limit)
126
+ return [];
127
+ return answered(s).flatMap((c) => {
128
+ const chars = c.resultChars ?? 0;
129
+ // Tokens are estimated at ~4 characters each; bytes ≈ characters for ASCII.
130
+ const size = limit.value.unit === "tokens" ? Math.round(chars / 4) : chars;
131
+ if (size <= limit.value.max)
132
+ return [];
133
+ const what = { truncate: "truncates it", file: "saves it to a file and gives the model a reference instead", unknown: "may cut it off" }[limit.value.onExceed];
134
+ return [
135
+ {
136
+ checkId: "CALL_RESULT_TOO_LARGE",
137
+ severity: "warn",
138
+ subject: c.tool,
139
+ client: p.id,
140
+ source: limit.source,
141
+ message: `${call(c)} returned about ${size.toLocaleString("en")} ${limit.value.unit}${limit.value.unit === "tokens" ? " (estimated)" : ""}; ${p.displayName} allows ${limit.value.max.toLocaleString("en")} and ${what}.`,
142
+ fix: "Paginate or summarise large results, or return a resource link instead of inlining data.",
143
+ },
144
+ ];
145
+ });
146
+ }),
147
+ }),
148
+ defineCheck({
149
+ id: "CALL_SLOW",
150
+ area: "calls",
151
+ description: "Tool calls finish well within each client's timeout",
152
+ appliesTo: (s) => answered(s).length > 0,
153
+ run: (s, { profiles }) => profiles.flatMap((p) => {
154
+ const timeout = p.limits.toolTimeoutMs;
155
+ if (!timeout)
156
+ return [];
157
+ return answered(s)
158
+ .filter((c) => c.durationMs > timeout.value / 2)
159
+ .map((c) => ({
160
+ checkId: "CALL_SLOW",
161
+ severity: c.durationMs > timeout.value ? "error" : "warn",
162
+ subject: c.tool,
163
+ client: p.id,
164
+ source: timeout.source,
165
+ message: `${call(c)} took ${(c.durationMs / 1000).toFixed(1)} s; ${p.displayName} times out after ${timeout.value / 1000} s.`,
166
+ fix: "Return quickly and report progress, or move long work behind a job id the model can poll.",
167
+ }));
168
+ }),
169
+ }),
170
+ defineCheck({
171
+ id: "CALL_FAILED",
172
+ area: "calls",
173
+ description: "Reports tool calls that errored",
174
+ appliesTo: hasCalls,
175
+ run: (s) => (s.calls ?? [])
176
+ .filter((c) => c.error || isToolError(c))
177
+ .map((c) => {
178
+ const text = Array.isArray(c.result?.content)
179
+ ? c.result.content.map((i) => (isObject(i) && typeof i.text === "string" ? i.text : "")).join(" ").slice(0, 200)
180
+ : "";
181
+ return {
182
+ checkId: "CALL_FAILED",
183
+ severity: "info",
184
+ subject: c.tool,
185
+ message: c.error
186
+ ? `${call(c)} failed with a protocol error${c.error.code !== undefined ? ` ${c.error.code}` : ""}: ${c.error.message}${c.origin === "probe" ? " (arguments were generated from the schema, so this may be expected)" : ""}.`
187
+ : `${call(c)} returned isError: ${text}`,
188
+ };
189
+ }),
190
+ }),
191
+ ];
192
+ //# sourceMappingURL=calls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calls.js","sourceRoot":"","sources":["../../src/checks/calls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type Check } from "./types.js";
2
+ export declare const discoveryChecks: Check[];
3
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/checks/discovery.ts"],"names":[],"mappings":"AAGA,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AA2CrD,eAAO,MAAM,eAAe,SAM3B,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { connected, featureGap, isObject, items } from "./util.js";
2
+ import { defineCheck } from "./types.js";
3
+ function listChangedCheck(kind, feature) {
4
+ const id = `DISCOVERY_${kind.toUpperCase()}_LIST_CHANGED`;
5
+ return defineCheck({
6
+ id,
7
+ area: "discovery",
8
+ description: `Notes clients that ignore ${kind}/list_changed when the server declares it`,
9
+ appliesTo: (s) => {
10
+ const cap = s.initialize?.capabilities?.[kind];
11
+ return connected(s) && isObject(cap) && cap.listChanged === true;
12
+ },
13
+ run: (s, { profiles }) =>
14
+ // INFO, not WARN: declaring listChanged (the SDK default) doesn't mean the list ever changes.
15
+ featureGap(profiles, feature, (p, partial) => ({
16
+ checkId: id,
17
+ severity: "info",
18
+ message: `Server declares ${kind}.listChanged, but ${p.displayName} ${partial ? "does not reliably refresh" : "does not refresh"} its ${kind} list during a session. If ${kind} change at runtime, users must reconnect to see them.`,
19
+ fix: `Register all ${kind} at startup if you can; enable/disable them instead of adding new ones later.`,
20
+ })),
21
+ });
22
+ }
23
+ function unsupportedFeatureCheck(kind, feature) {
24
+ const id = `DISCOVERY_${kind.toUpperCase()}_UNSUPPORTED`;
25
+ return defineCheck({
26
+ id,
27
+ area: "discovery",
28
+ description: `Clients without ${kind} support are flagged when the server exposes ${kind}`,
29
+ appliesTo: (s) => connected(s) && items(s, kind).length > 0,
30
+ run: (s, { profiles }) => featureGap(profiles, feature, (p, partial) => ({
31
+ checkId: id,
32
+ severity: "warn",
33
+ message: `Server exposes ${items(s, kind).length} ${kind}, but ${p.displayName} ${partial ? "only partly supports" : "does not support"} MCP ${kind}. Anything only reachable through them may be missing there.`,
34
+ fix: kind === "prompts"
35
+ ? "Don't rely on prompts for core functionality; mention workflows in tool descriptions too."
36
+ : "Offer important resource content through a tool as well.",
37
+ })),
38
+ });
39
+ }
40
+ export const discoveryChecks = [
41
+ listChangedCheck("tools", "toolsListChanged"),
42
+ listChangedCheck("resources", "resourcesListChanged"),
43
+ listChangedCheck("prompts", "promptsListChanged"),
44
+ unsupportedFeatureCheck("resources", "resources"),
45
+ unsupportedFeatureCheck("prompts", "prompts"),
46
+ ];
47
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/checks/discovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AACnE,OAAO,EAAE,WAAW,EAAc,MAAM,YAAY,CAAC;AAErD,SAAS,gBAAgB,CAAC,IAAuC,EAAE,OAAsB;IACvF,MAAM,EAAE,GAAG,aAAa,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC;IAC1D,OAAO,WAAW,CAAC;QACjB,EAAE;QACF,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,6BAA6B,IAAI,2CAA2C;QACzF,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE;YACf,MAAM,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC;YAC/C,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC;QACnE,CAAC;QACD,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACvB,8FAA8F;QAC9F,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;YAC7C,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,mBAAmB,IAAI,qBAAqB,CAAC,CAAC,WAAW,IAAI,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,kBAAkB,QAAQ,IAAI,8BAA8B,IAAI,uDAAuD;YACrO,GAAG,EAAE,gBAAgB,IAAI,+EAA+E;SACzG,CAAC,CAAC;KACN,CAAC,CAAC;AACL,CAAC;AAED,SAAS,uBAAuB,CAAC,IAA0C,EAAE,OAAsB;IACjG,MAAM,EAAE,GAAG,aAAa,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC;IACzD,OAAO,WAAW,CAAC;QACjB,EAAE;QACF,IAAI,EAAE,WAAW;QACjB,WAAW,EAAE,mBAAmB,IAAI,gDAAgD,IAAI,EAAE;QAC1F,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC;QAC3D,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CACvB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;YAC7C,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,kBAAkB,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,IAAI,IAAI,SAAS,CAAC,CAAC,WAAW,IAAI,OAAO,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,kBAAkB,QAAQ,IAAI,8DAA8D;YACjN,GAAG,EACD,IAAI,KAAK,SAAS;gBAChB,CAAC,CAAC,2FAA2F;gBAC7F,CAAC,CAAC,0DAA0D;SACjE,CAAC,CAAC;KACN,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,gBAAgB,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAC7C,gBAAgB,CAAC,WAAW,EAAE,sBAAsB,CAAC;IACrD,gBAAgB,CAAC,SAAS,EAAE,oBAAoB,CAAC;IACjD,uBAAuB,CAAC,WAAW,EAAE,WAAW,CAAC;IACjD,uBAAuB,CAAC,SAAS,EAAE,SAAS,CAAC;CAC9C,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { ClientFeature, ClientProfile } from "../profiles/types.js";
2
+ type LimitKey = keyof ClientProfile["limits"];
3
+ export interface Explanation {
4
+ /** Why the check exists, in one or two sentences. */
5
+ why: string;
6
+ /** Spec pages, RFCs or SDK source backing the check itself. */
7
+ sources?: string[];
8
+ /** Client profile limits the check reads; `explain` prints them per client. */
9
+ limits?: LimitKey[];
10
+ /** Client features the check depends on; `explain` prints them per client. */
11
+ features?: ClientFeature[];
12
+ }
13
+ export declare const EXPLANATIONS: Record<string, Explanation>;
14
+ export {};
15
+ //# sourceMappingURL=explanations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explanations.d.ts","sourceRoot":"","sources":["../../src/checks/explanations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAEzE,KAAK,QAAQ,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,+EAA+E;IAC/E,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;IACpB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;CAC5B;AASD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAkVpD,CAAC"}