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,422 @@
1
+ import { connected, declared, isObject, items, str, withNote } from "./util.js";
2
+ import { defineCheck } from "./types.js";
3
+ /** Tool name format from the MCP spec (SEP-986), as enforced by the SDK. */
4
+ export const SPEC_TOOL_NAME = /^[A-Za-z0-9._-]{1,128}$/;
5
+ const SHORT_DESCRIPTION = 20;
6
+ const hasTools = (s) => connected(s) && items(s, "tools").length > 0;
7
+ const toolName = (t) => str(t.name) ?? "(unnamed)";
8
+ const toolNames = (s) => items(s, "tools").flatMap((t) => (typeof t.name === "string" ? [t.name] : []));
9
+ const serverName = (s) => str(s.initialize?.serverInfo?.name) ?? "server";
10
+ const READ_VERBS = new Set("get list search find read fetch query describe show lookup count check view browse retrieve inspect preview download export".split(" "));
11
+ const WRITE_VERBS = new Set("create add update edit delete remove place cancel modify send post write set move rename execute run deploy transfer buy sell pay charge drop insert upsert archive publish submit approve reject revoke grant invite kill stop start restart reset clear purge destroy close open merge push".split(" "));
12
+ /** The first word of a tool name, lowercased: get_user → get, createEvent → create, files.read → files. */
13
+ export function leadingVerb(name) {
14
+ return name.replace(/([a-z0-9])([A-Z])/g, "$1_$2").split(/[_\-.\s]+/)[0]?.toLowerCase() ?? "";
15
+ }
16
+ /** "read" / "write" from the tool name's leading verb, or undefined if it doesn't say. */
17
+ export function nameIntent(name) {
18
+ const verb = leadingVerb(name);
19
+ return READ_VERBS.has(verb) ? "read" : WRITE_VERBS.has(verb) ? "write" : undefined;
20
+ }
21
+ const annotations = (t) => (isObject(t.annotations) ? t.annotations : {});
22
+ /** Replaces characters outside the allowed class with "_". */
23
+ export function sanitize(name, allowed) {
24
+ return name.replace(new RegExp(`[^${allowed}]`, "g"), "_");
25
+ }
26
+ /** The prefix a client puts in front of this server's tool names ("" if none/unknown). */
27
+ export function clientPrefix(s, p) {
28
+ const rule = p.limits.toolNamePrefix?.value;
29
+ if (!rule)
30
+ return "";
31
+ let server = serverName(s);
32
+ if (rule.lowercase)
33
+ server = server.toLowerCase();
34
+ const allowed = p.limits.toolNameChars?.value;
35
+ if (allowed?.onInvalid === "replace")
36
+ server = sanitize(server, allowed.allowed);
37
+ const prefix = rule.format.replace("{server}", server);
38
+ return rule.maxLength ? prefix.slice(0, rule.maxLength) : prefix;
39
+ }
40
+ /** The name the client ends up using, applying only documented replace/truncate behaviour. */
41
+ export function clientToolName(s, p, name) {
42
+ const chars = p.limits.toolNameChars?.value;
43
+ let result = clientPrefix(s, p) + (chars?.onInvalid === "replace" ? sanitize(name, chars.allowed) : name);
44
+ const length = p.limits.maxToolNameLength?.value;
45
+ if (length && result.length > length.max) {
46
+ if (length.onExceed === "truncate")
47
+ result = result.slice(0, length.max);
48
+ if (length.onExceed === "truncateMiddle")
49
+ result = truncateMiddle(result, length.max);
50
+ }
51
+ return result;
52
+ }
53
+ /** Start and end joined by "..." (Gemini CLI's scheme: 30 + "..." + 30 for a 63 limit). */
54
+ export function truncateMiddle(name, max) {
55
+ if (name.length <= max)
56
+ return name;
57
+ const keep = Math.floor((max - 3) / 2);
58
+ return `${name.slice(0, keep)}...${name.slice(name.length - keep)}`;
59
+ }
60
+ export const toolChecks = [
61
+ defineCheck({
62
+ id: "TOOL_NONE",
63
+ area: "tools",
64
+ description: "A server declaring tools exposes at least one",
65
+ appliesTo: (s) => connected(s) && declared(s, "tools") && !!s.lists.tools?.ok,
66
+ run: (s) => items(s, "tools").length > 0
67
+ ? []
68
+ : [
69
+ {
70
+ checkId: "TOOL_NONE",
71
+ severity: "warn",
72
+ message: 'Server declares the "tools" capability but tools/list is empty.',
73
+ fix: "Register tools before connecting the transport, or drop the capability.",
74
+ },
75
+ ],
76
+ }),
77
+ defineCheck({
78
+ id: "TOOL_NAME_INVALID",
79
+ area: "tools",
80
+ description: "Tool names match the MCP spec format (A-Z a-z 0-9 _ - ., 1-128 chars)",
81
+ appliesTo: hasTools,
82
+ run: (s) => items(s, "tools")
83
+ .filter((t) => typeof t.name !== "string" || !SPEC_TOOL_NAME.test(t.name))
84
+ .map((t) => ({
85
+ checkId: "TOOL_NAME_INVALID",
86
+ severity: "error",
87
+ subject: toolName(t),
88
+ message: typeof t.name !== "string"
89
+ ? "Tool has no string name."
90
+ : `Tool name ${JSON.stringify(t.name)} is not a valid MCP tool name.`,
91
+ fix: "Use only letters, digits, underscore, dash and dot (max 128 characters).",
92
+ })),
93
+ }),
94
+ defineCheck({
95
+ id: "TOOL_NAME_DUPLICATE",
96
+ area: "tools",
97
+ description: "Tool names are unique",
98
+ appliesTo: hasTools,
99
+ run: (s) => {
100
+ const counts = new Map();
101
+ for (const t of items(s, "tools")) {
102
+ if (typeof t.name === "string")
103
+ counts.set(t.name, (counts.get(t.name) ?? 0) + 1);
104
+ }
105
+ return [...counts]
106
+ .filter(([, n]) => n > 1)
107
+ .map(([name, n]) => ({
108
+ checkId: "TOOL_NAME_DUPLICATE",
109
+ severity: "error",
110
+ subject: name,
111
+ message: `${n} tools are named ${JSON.stringify(name)}; clients keep only one or reject the list.`,
112
+ fix: "Give every tool a unique name.",
113
+ }));
114
+ },
115
+ }),
116
+ defineCheck({
117
+ id: "TOOL_NAME_CLIENT_CHARS",
118
+ area: "tools",
119
+ description: "Tool names use only characters each client accepts as-is",
120
+ appliesTo: hasTools,
121
+ run: (s, { profiles }) => profiles.flatMap((p) => {
122
+ const rule = p.limits.toolNameChars;
123
+ if (!rule)
124
+ return [];
125
+ return toolNames(s)
126
+ .filter((name) => sanitize(name, rule.value.allowed) !== name)
127
+ .map((name) => {
128
+ const { onInvalid } = rule.value;
129
+ const renamed = sanitize(name, rule.value.allowed);
130
+ return {
131
+ checkId: "TOOL_NAME_CLIENT_CHARS",
132
+ severity: onInvalid === "reject" ? "error" : "warn",
133
+ subject: name,
134
+ client: p.id,
135
+ source: rule.source,
136
+ message: onInvalid === "reject"
137
+ ? `${p.displayName} rejects tool names with characters outside [${rule.value.allowed}].`
138
+ : onInvalid === "replace"
139
+ ? `${p.displayName} renames it to "${renamed}" (only [${rule.value.allowed}] allowed).`
140
+ : onInvalid === "replaceUnique"
141
+ ? `${p.displayName} renames it to "${renamed}" (only [${rule.value.allowed}] allowed; clashing names get a hash suffix).`
142
+ : onInvalid === "truncateWithHash"
143
+ ? `${p.displayName} renames it to "${renamed}" plus a hash suffix (only [${rule.value.allowed}] allowed), so the model sees a mangled name.`
144
+ : withNote(`${p.displayName} only accepts [${rule.value.allowed}].`, rule.note),
145
+ fix: "Use only letters, digits, underscores and dashes in tool names.",
146
+ };
147
+ });
148
+ }),
149
+ }),
150
+ defineCheck({
151
+ id: "TOOL_NAME_TOO_LONG",
152
+ area: "tools",
153
+ description: "Prefixed tool names fit each client's length limit",
154
+ appliesTo: hasTools,
155
+ run: (s, { profiles }) => profiles.flatMap((p) => {
156
+ const limit = p.limits.maxToolNameLength;
157
+ if (!limit)
158
+ return [];
159
+ const prefix = clientPrefix(s, p);
160
+ const { max, onExceed } = limit.value;
161
+ return toolNames(s)
162
+ .filter((name) => prefix.length + name.length > max)
163
+ .map((name) => {
164
+ const full = prefix + name;
165
+ const what = onExceed === "reject"
166
+ ? "rejects it"
167
+ : onExceed === "truncate"
168
+ ? `truncates it to "${full.slice(0, max)}"`
169
+ : onExceed === "truncateWithHash"
170
+ ? "truncates it and appends a hash, so the model sees a mangled name"
171
+ : onExceed === "truncateMiddle"
172
+ ? `shortens it to "${truncateMiddle(full, max)}"`
173
+ : "may reject or rewrite it";
174
+ return {
175
+ checkId: "TOOL_NAME_TOO_LONG",
176
+ severity: onExceed === "reject" ? "error" : "warn",
177
+ subject: name,
178
+ client: p.id,
179
+ source: limit.source,
180
+ message: prefix
181
+ ? `With ${p.displayName}'s server prefix ("${prefix}", assuming the server is registered as "${serverName(s)}") the name is ${full.length} characters; the limit is ${max} and ${p.displayName} ${what}.`
182
+ : `The name is ${full.length} characters; ${p.displayName} allows ${max} and ${what}.`,
183
+ fix: "Shorten the tool name, and suggest a short server name in your install instructions.",
184
+ };
185
+ });
186
+ }),
187
+ }),
188
+ defineCheck({
189
+ id: "TOOL_NAME_CLIENT_COLLISION",
190
+ area: "tools",
191
+ description: "Tool names stay unique after a client renames or truncates them",
192
+ appliesTo: hasTools,
193
+ run: (s, { profiles }) => profiles.flatMap((p) => {
194
+ const byClientName = new Map();
195
+ for (const name of new Set(toolNames(s))) {
196
+ const sent = clientToolName(s, p, name);
197
+ byClientName.set(sent, [...(byClientName.get(sent) ?? []), name]);
198
+ }
199
+ const chars = p.limits.toolNameChars;
200
+ return [...byClientName]
201
+ .filter(([, names]) => names.length > 1)
202
+ .map(([sent, names]) => {
203
+ // Blame character replacement when it alone makes the names equal.
204
+ const renamed = chars?.value.onInvalid === "replace" ? names.map((n) => sanitize(n, chars.value.allowed)) : names;
205
+ const byReplacement = new Set(renamed).size === 1;
206
+ const quoted = names.map((n) => `"${n}"`);
207
+ const list = quoted.length === 2 ? quoted.join(" and ") : quoted.join(", ");
208
+ return {
209
+ checkId: "TOOL_NAME_CLIENT_COLLISION",
210
+ severity: "error",
211
+ subject: names.join(", "),
212
+ client: p.id,
213
+ source: (byReplacement ? chars : p.limits.maxToolNameLength)?.source,
214
+ message: byReplacement
215
+ ? `${list} ${names.length === 2 ? "both" : "all"} become "${renamed[0]}" in ${p.displayName}, so only one of them is usable.`
216
+ : `${list} are truncated to the same name "${sent}" in ${p.displayName}, so only one of them is usable.`,
217
+ fix: byReplacement
218
+ ? "Use only letters, digits, _ and - in tool names."
219
+ : "Make tool names differ within their first characters.",
220
+ };
221
+ });
222
+ }),
223
+ }),
224
+ defineCheck({
225
+ id: "TOOL_COUNT_OVER_LIMIT",
226
+ area: "tools",
227
+ description: "Tool count fits each client's limit",
228
+ appliesTo: hasTools,
229
+ run: (s, { profiles }) => {
230
+ const count = items(s, "tools").length;
231
+ return profiles.flatMap((p) => {
232
+ const limit = p.limits.maxTools;
233
+ if (!limit || count <= limit.value)
234
+ return [];
235
+ return [
236
+ {
237
+ checkId: "TOOL_COUNT_OVER_LIMIT",
238
+ severity: "warn",
239
+ client: p.id,
240
+ source: limit.source,
241
+ message: withNote(`Server exposes ${count} tools; ${p.displayName} uses at most ${limit.value}.`, limit.note),
242
+ fix: "Consolidate tools, or split the server so users can enable only what they need.",
243
+ },
244
+ ];
245
+ });
246
+ },
247
+ }),
248
+ defineCheck({
249
+ id: "TOOL_DESCRIPTION_MISSING",
250
+ area: "tools",
251
+ description: "Every tool has a non-empty description",
252
+ appliesTo: hasTools,
253
+ run: (s) => items(s, "tools")
254
+ .filter((t) => typeof t.description !== "string" || t.description.trim() === "")
255
+ .map((t) => ({
256
+ checkId: "TOOL_DESCRIPTION_MISSING",
257
+ severity: "error",
258
+ subject: toolName(t),
259
+ message: t.description === null
260
+ ? "description is null. The spec allows omitting it, not null; the TypeScript SDK's result schema rejects the whole tools/list response, so SDK-based clients see no tools at all."
261
+ : "Tool has no description, so the model has to guess when to use it.",
262
+ evidence: { description: t.description ?? "(absent)" },
263
+ fix: "Describe what the tool does and when to use it.",
264
+ })),
265
+ }),
266
+ defineCheck({
267
+ id: "TOOL_DESCRIPTION_SHORT",
268
+ area: "tools",
269
+ description: `Tool descriptions are at least ${SHORT_DESCRIPTION} characters`,
270
+ appliesTo: hasTools,
271
+ run: (s) => items(s, "tools")
272
+ .filter((t) => typeof t.description === "string" && t.description.trim() !== "")
273
+ .filter((t) => t.description.trim().length < SHORT_DESCRIPTION)
274
+ .map((t) => ({
275
+ checkId: "TOOL_DESCRIPTION_SHORT",
276
+ severity: "info",
277
+ subject: toolName(t),
278
+ message: `Description ${JSON.stringify(t.description)} is very short; models pick tools from descriptions.`,
279
+ fix: "Say what the tool does, what it returns, and when to prefer it over similar tools.",
280
+ })),
281
+ }),
282
+ defineCheck({
283
+ id: "TOOL_DESCRIPTION_TRUNCATED",
284
+ area: "tools",
285
+ description: "Tool descriptions and server instructions fit each client's length limit",
286
+ appliesTo: connected,
287
+ run: (s, { profiles }) => profiles.flatMap((p) => {
288
+ const limit = p.limits.maxDescriptionLength;
289
+ if (!limit)
290
+ return [];
291
+ const texts = items(s, "tools")
292
+ .filter((t) => typeof t.description === "string")
293
+ .map((t) => [toolName(t), t.description]);
294
+ if (s.initialize?.instructions)
295
+ texts.push(["(server instructions)", s.initialize.instructions]);
296
+ return texts
297
+ .filter(([, text]) => text.length > limit.value)
298
+ .map(([subject, text]) => ({
299
+ checkId: "TOOL_DESCRIPTION_TRUNCATED",
300
+ severity: "warn",
301
+ subject,
302
+ client: p.id,
303
+ source: limit.source,
304
+ message: `${text.length} characters; ${p.displayName} truncates after ${limit.value}, so the end is never seen by the model.`,
305
+ fix: "Put the most important guidance first and move reference material into a resource or the tool result.",
306
+ }));
307
+ }),
308
+ }),
309
+ defineCheck({
310
+ id: "TOOL_STRUCTURED_OUTPUT_HANDLING",
311
+ area: "tools",
312
+ description: "Notes how each client passes structured tool output to the model",
313
+ appliesTo: (s) => connected(s) && items(s, "tools").some((t) => isObject(t.outputSchema)),
314
+ run: (s, { profiles }) => {
315
+ const tools = items(s, "tools").filter((t) => isObject(t.outputSchema)).map(toolName);
316
+ return profiles.flatMap((p) => {
317
+ const rule = p.limits.structuredContent;
318
+ if (!rule || rule.value === "alongsideText")
319
+ return [];
320
+ return [
321
+ {
322
+ checkId: "TOOL_STRUCTURED_OUTPUT_HANDLING",
323
+ severity: "info",
324
+ subject: tools.join(", "),
325
+ client: p.id,
326
+ source: rule.source,
327
+ message: rule.value === "replacesText"
328
+ ? `${p.displayName} sends the model JSON of structuredContent instead of the text content, so anything only in the text is lost.`
329
+ : rule.value === "textOnly"
330
+ ? `${p.displayName} only ever sends the model the text content; structuredContent never reaches it.`
331
+ : `${p.displayName} sends the model only the text content (structuredContent is used only when content is empty).`,
332
+ fix: rule.value === "replacesText"
333
+ ? "Put everything the model needs into structuredContent."
334
+ : "Keep the text content complete; don't rely on structuredContent alone.",
335
+ },
336
+ ];
337
+ });
338
+ },
339
+ }),
340
+ defineCheck({
341
+ id: "TOOL_ANNOTATIONS_CONFLICT",
342
+ area: "tools",
343
+ description: "Tool annotations are consistent with each other and with the tool's name",
344
+ appliesTo: hasTools,
345
+ run: (s) => items(s, "tools").flatMap((t) => {
346
+ const a = annotations(t);
347
+ if (a.readOnlyHint !== true)
348
+ return [];
349
+ if (a.destructiveHint === true || a.idempotentHint === false) {
350
+ return [
351
+ {
352
+ checkId: "TOOL_ANNOTATIONS_CONFLICT",
353
+ severity: "warn",
354
+ subject: toolName(t),
355
+ message: "readOnlyHint is true but destructiveHint/idempotentHint describe a writing tool; clients may skip confirmation prompts.",
356
+ evidence: { annotations: t.annotations },
357
+ fix: "Set readOnlyHint: false for tools that modify anything.",
358
+ },
359
+ ];
360
+ }
361
+ if (typeof t.name === "string" && nameIntent(t.name) === "write") {
362
+ return [
363
+ {
364
+ checkId: "TOOL_ANNOTATIONS_CONFLICT",
365
+ severity: "warn",
366
+ subject: t.name,
367
+ message: `"${t.name}" sounds like it changes something ("${leadingVerb(t.name)}") but declares readOnlyHint: true, so clients may run it without asking.`,
368
+ evidence: { annotations: t.annotations },
369
+ fix: "If the tool modifies state, set readOnlyHint: false (and destructiveHint as appropriate).",
370
+ },
371
+ ];
372
+ }
373
+ return [];
374
+ }),
375
+ }),
376
+ defineCheck({
377
+ id: "TOOL_TITLE_MISSING",
378
+ area: "tools",
379
+ description: "Tools have a human-readable title",
380
+ appliesTo: hasTools,
381
+ run: (s) => {
382
+ const untitled = items(s, "tools").filter((t) => !str(t.title) && !str(annotations(t).title));
383
+ if (untitled.length === 0)
384
+ return [];
385
+ return [
386
+ {
387
+ checkId: "TOOL_TITLE_MISSING",
388
+ severity: "info",
389
+ subject: untitled.map(toolName).slice(0, 10).join(", ") + (untitled.length > 10 ? ", …" : ""),
390
+ message: `${untitled.length} tool(s) have no title, so clients such as VS Code show the raw name; Anthropic's connector directory requires a title on every tool.`,
391
+ evidence: { tools: untitled.map(toolName) },
392
+ fix: 'Add title: "Get weather" (or annotations.title) to each tool.',
393
+ },
394
+ ];
395
+ },
396
+ }),
397
+ defineCheck({
398
+ id: "TOOL_ANNOTATIONS_MISSING",
399
+ area: "tools",
400
+ description: "Read-only tools declare readOnlyHint",
401
+ appliesTo: hasTools,
402
+ run: (s, { profiles }) => {
403
+ const tools = items(s, "tools");
404
+ const skipping = profiles.filter((p) => p.limits.readOnlySkipsApproval?.value === true).map((p) => p.displayName);
405
+ const reads = tools.filter((t) => typeof t.name === "string" && nameIntent(t.name) === "read" && annotations(t).readOnlyHint === undefined);
406
+ if (reads.length === 0)
407
+ return [];
408
+ const none = tools.every((t) => !isObject(t.annotations));
409
+ return [
410
+ {
411
+ checkId: "TOOL_ANNOTATIONS_MISSING",
412
+ severity: "info",
413
+ subject: reads.map(toolName).join(", "),
414
+ message: `${reads.length} tool(s) look read-only but don't declare readOnlyHint${none ? " (the server sets no annotations at all)" : ""}. Without it the spec tells clients to assume they may be destructive${skipping.length ? `; ${skipping.join(", ")} ask for confirmation on every call to them` : ", so users get needless confirmations"}.`,
415
+ evidence: { tools: reads.map(toolName) },
416
+ fix: "Add annotations: { readOnlyHint: true } to read-only tools, and destructiveHint: false to writes that only add data.",
417
+ },
418
+ ];
419
+ },
420
+ }),
421
+ ];
422
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/checks/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const transportChecks: import("./types.js").Check[];
2
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/checks/transport.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,eAAe,8BAwH3B,CAAC"}
@@ -0,0 +1,123 @@
1
+ import { modernOnly } from "./protocol.js";
2
+ import { connected, isHttp, isStdio } from "./util.js";
3
+ import { defineCheck } from "./types.js";
4
+ const SLOW_STARTUP_MS = 5000;
5
+ const SLOW_LIST_MS = 3000;
6
+ function authRequired(s) {
7
+ const status = s.http?.unauthenticated.status;
8
+ return !s.connect.ok && (status === 401 || status === 403);
9
+ }
10
+ export const transportChecks = [
11
+ defineCheck({
12
+ id: "TRANSPORT_CONNECT_FAILED",
13
+ area: "transport",
14
+ description: "The server starts and answers initialize",
15
+ appliesTo: (s) => !authRequired(s) && !modernOnly(s),
16
+ run: (s) => s.connect.ok
17
+ ? []
18
+ : [
19
+ {
20
+ checkId: "TRANSPORT_CONNECT_FAILED",
21
+ severity: "error",
22
+ message: `Could not connect: ${s.connect.error ?? "unknown error"}`,
23
+ evidence: { stderrTail: s.io.stderrTail.slice(-10) },
24
+ fix: "Check the command, working directory and required environment variables (--env).",
25
+ },
26
+ ],
27
+ }),
28
+ defineCheck({
29
+ id: "TRANSPORT_AUTH_REQUIRED",
30
+ area: "transport",
31
+ description: "Notes when an HTTP server needs credentials before initialize",
32
+ appliesTo: isHttp,
33
+ run: (s) => authRequired(s)
34
+ ? [
35
+ {
36
+ checkId: "TRANSPORT_AUTH_REQUIRED",
37
+ severity: "info",
38
+ message: `Server requires authorization (HTTP ${s.http.unauthenticated.status}); only auth discovery was checked.`,
39
+ fix: "Pass --header 'Authorization: Bearer <token>' to also check tools, resources and prompts.",
40
+ },
41
+ ]
42
+ : [],
43
+ }),
44
+ defineCheck({
45
+ id: "TRANSPORT_STDOUT_POLLUTION",
46
+ area: "transport",
47
+ description: "stdout carries only JSON-RPC messages",
48
+ appliesTo: isStdio,
49
+ run: (s) => {
50
+ const lines = s.io.stdoutNonJsonLines;
51
+ if (lines.length === 0)
52
+ return [];
53
+ // A protocol message glued to log output (no newline between them) is lost entirely.
54
+ const corrupted = lines.filter((l) => l.includes('"jsonrpc"'));
55
+ const count = `${lines.length}${lines.length >= 50 ? "+" : ""}`;
56
+ return [
57
+ {
58
+ checkId: "TRANSPORT_STDOUT_POLLUTION",
59
+ severity: corrupted.length > 0 ? "error" : "warn",
60
+ message: corrupted.length > 0
61
+ ? `Log output on stdout corrupted ${corrupted.length} JSON-RPC message(s), e.g. ${JSON.stringify(corrupted[0])}; clients drop them and the request hangs.`
62
+ : `Server wrote ${count} non-JSON-RPC line(s) to stdout, e.g. ${JSON.stringify(lines[0])}. MCP SDK clients drop these lines (the v1 TypeScript SDK reports each as an error), and any log write without a trailing newline corrupts the next message.`,
63
+ evidence: { lines: (corrupted.length > 0 ? corrupted : lines).slice(0, 5) },
64
+ affects: ["stdio"],
65
+ fix: "Send logs to stderr (console.error / logging to sys.stderr). stdout is reserved for protocol messages.",
66
+ },
67
+ ];
68
+ },
69
+ }),
70
+ defineCheck({
71
+ id: "TRANSPORT_SLOW_STARTUP",
72
+ area: "transport",
73
+ description: `initialize answers within ${SLOW_STARTUP_MS / 1000}s of launch`,
74
+ appliesTo: connected,
75
+ run: (s) => (s.connect.startupMs ?? 0) > SLOW_STARTUP_MS
76
+ ? [
77
+ {
78
+ checkId: "TRANSPORT_SLOW_STARTUP",
79
+ severity: "warn",
80
+ message: `initialize took ${s.connect.startupMs}ms; some clients time out on slow startup.`,
81
+ evidence: { startupMs: s.connect.startupMs },
82
+ fix: "Defer expensive setup (network, model loading) until after initialize. If launched via npx/uvx, first-run installs count too.",
83
+ },
84
+ ]
85
+ : [],
86
+ }),
87
+ defineCheck({
88
+ id: "TRANSPORT_SLOW_LIST",
89
+ area: "transport",
90
+ description: `list requests answer within ${SLOW_LIST_MS / 1000}s`,
91
+ appliesTo: connected,
92
+ run: (s) => Object.entries(s.lists)
93
+ .filter(([, list]) => list && list.durationMs > SLOW_LIST_MS)
94
+ .map(([kind, list]) => ({
95
+ checkId: "TRANSPORT_SLOW_LIST",
96
+ severity: "warn",
97
+ subject: kind,
98
+ message: `${kind} listing took ${list.durationMs}ms.`,
99
+ evidence: { durationMs: list.durationMs, pages: list.pages },
100
+ fix: "Build list responses from static metadata; don't call upstream APIs while listing.",
101
+ })),
102
+ }),
103
+ defineCheck({
104
+ id: "TRANSPORT_STDERR_ERRORS",
105
+ area: "transport",
106
+ description: "stderr shows no errors during the session",
107
+ appliesTo: isStdio,
108
+ run: (s) => {
109
+ const errors = s.io.stderrTail.filter((l) => /\b(error|exception|traceback|unhandled)\b/i.test(l));
110
+ if (errors.length === 0 || !s.connect.ok)
111
+ return [];
112
+ return [
113
+ {
114
+ checkId: "TRANSPORT_STDERR_ERRORS",
115
+ severity: "info",
116
+ message: `stderr contained ${errors.length} error-looking line(s), e.g. ${JSON.stringify(errors[0])}`,
117
+ evidence: { lines: errors.slice(0, 5) },
118
+ },
119
+ ];
120
+ },
121
+ }),
122
+ ];
123
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/checks/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { ClientFeature, ClientProfile } from "../profiles/types.js";
2
+ import type { ServerSnapshot } from "../snapshot.js";
3
+ export type Severity = "error" | "warn" | "info";
4
+ export type CheckArea = "transport" | "protocol" | "tools" | "schema" | "discovery" | "resources" | "ui" | "auth" | "calls" | "sdk";
5
+ export interface Finding {
6
+ checkId: string;
7
+ severity: Severity;
8
+ message: string;
9
+ /** Tool/resource/prompt name or URL the finding is about. */
10
+ subject?: string;
11
+ evidence?: Record<string, unknown>;
12
+ fix?: string;
13
+ /**
14
+ * Client features that make this finding matter. A client known not to
15
+ * support any of them gets INFO instead of FAIL/WARN. Absent = all clients.
16
+ */
17
+ affects?: ClientFeature[];
18
+ /** Set when the finding only applies to one client (limit checks). */
19
+ client?: string;
20
+ /** Profile source backing a client-specific finding. */
21
+ source?: string;
22
+ }
23
+ export interface CheckContext {
24
+ profiles: ClientProfile[];
25
+ }
26
+ export interface Check {
27
+ id: string;
28
+ area: CheckArea;
29
+ /** One line, shown by --list-checks. */
30
+ description: string;
31
+ /** False → the check is reported as SKIP (e.g. auth checks on stdio). */
32
+ appliesTo: (snapshot: ServerSnapshot) => boolean;
33
+ run: (snapshot: ServerSnapshot, ctx: CheckContext) => Finding[];
34
+ }
35
+ /** Helper so check modules can define checks with less boilerplate. */
36
+ export declare function defineCheck(check: Check): Check;
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/checks/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjD,MAAM,MAAM,SAAS,GACjB,WAAW,GACX,UAAU,GACV,OAAO,GACP,QAAQ,GACR,WAAW,GACX,WAAW,GACX,IAAI,GACJ,MAAM,GACN,OAAO,GACP,KAAK,CAAC;AAEV,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,OAAO,CAAC,EAAE,aAAa,EAAE,CAAC;IAC1B,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,SAAS,CAAC;IAChB,wCAAwC;IACxC,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,SAAS,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,OAAO,CAAC;IACjD,GAAG,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,EAAE,YAAY,KAAK,OAAO,EAAE,CAAC;CACjE;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C"}
@@ -0,0 +1,5 @@
1
+ /** Helper so check modules can define checks with less boilerplate. */
2
+ export function defineCheck(check) {
3
+ return check;
4
+ }
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/checks/types.ts"],"names":[],"mappings":"AAkDA,uEAAuE;AACvE,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,OAAO,KAAK,CAAC;AACf,CAAC"}