@yawlabs/mcp-compliance 0.1.2 → 0.2.1

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.
@@ -1,126 +1,135 @@
1
1
  import {
2
2
  TEST_DEFINITIONS,
3
3
  runComplianceSuite
4
- } from "../chunk-OOJ4PMF7.js";
4
+ } from "../chunk-SP24UFRC.js";
5
5
 
6
6
  // src/mcp/server.ts
7
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
8
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
- import { z } from "zod";
10
9
  import { createRequire } from "module";
11
- var require2 = createRequire(import.meta.url);
12
- var { version } = require2("../../package.json");
13
- var server = new McpServer({
14
- name: "mcp-compliance",
15
- version
16
- });
17
- server.tool(
18
- "mcp_compliance_test",
19
- "Run the full MCP compliance test suite against a server URL. Returns grade (A-F), score, and detailed results for all 24 tests.",
20
- {
21
- url: z.string().url().describe("The MCP server URL to test (must be HTTP or HTTPS)")
22
- },
23
- async ({ url }) => {
24
- try {
25
- const report = await runComplianceSuite(url);
26
- const summary = [
27
- `Grade: ${report.grade} (${report.score}%)`,
28
- `Overall: ${report.overall}`,
29
- `Tests: ${report.summary.passed}/${report.summary.total} passed (${report.summary.requiredPassed}/${report.summary.required} required)`,
30
- "",
31
- ...report.tests.map(
32
- (t) => `${t.passed ? "PASS" : "FAIL"} ${t.name}${t.required ? " (required)" : ""} \u2014 ${t.details}`
33
- )
34
- ];
35
- if (report.serverInfo.name) {
36
- summary.unshift(`Server: ${report.serverInfo.name} v${report.serverInfo.version || "?"}`);
37
- }
38
- return {
39
- content: [
40
- { type: "text", text: summary.join("\n") },
41
- { type: "text", text: `
10
+
11
+ // src/mcp/tools.ts
12
+ import { z } from "zod";
13
+ function registerTools(server2) {
14
+ server2.tool(
15
+ "mcp_compliance_test",
16
+ "Run the full MCP compliance test suite against a server URL. Returns grade (A-F), score, and detailed results for all 43 tests covering transport, lifecycle, tools, resources, prompts, errors, and schema validation.",
17
+ {
18
+ url: z.string().url().describe("The MCP server URL to test (must be HTTP or HTTPS)")
19
+ },
20
+ async ({ url }) => {
21
+ try {
22
+ const report = await runComplianceSuite(url);
23
+ const summary = [
24
+ `Grade: ${report.grade} (${report.score}%)`,
25
+ `Overall: ${report.overall}`,
26
+ `Tests: ${report.summary.passed}/${report.summary.total} passed (${report.summary.requiredPassed}/${report.summary.required} required)`,
27
+ "",
28
+ ...report.tests.map(
29
+ (t) => `${t.passed ? "PASS" : "FAIL"} ${t.name}${t.required ? " (required)" : ""} \u2014 ${t.details}`
30
+ )
31
+ ];
32
+ if (report.serverInfo.name) {
33
+ summary.unshift(`Server: ${report.serverInfo.name} v${report.serverInfo.version || "?"}`);
34
+ }
35
+ if (report.warnings.length > 0) {
36
+ summary.push("", `Warnings (${report.warnings.length}):`);
37
+ for (const w of report.warnings) {
38
+ summary.push(` - ${w}`);
39
+ }
40
+ }
41
+ return {
42
+ content: [
43
+ { type: "text", text: summary.join("\n") },
44
+ { type: "text", text: `
42
45
 
43
46
  Full report:
44
47
  ${JSON.stringify(report, null, 2)}` }
45
- ]
46
- };
47
- } catch (err) {
48
- return {
49
- content: [{ type: "text", text: `Error running compliance test: ${err.message}` }],
50
- isError: true
51
- };
48
+ ]
49
+ };
50
+ } catch (err) {
51
+ return {
52
+ content: [{ type: "text", text: `Error running compliance test: ${err.message}` }],
53
+ isError: true
54
+ };
55
+ }
56
+ }
57
+ );
58
+ server2.tool(
59
+ "mcp_compliance_badge",
60
+ "Get the badge markdown embed code for an MCP server. Runs the compliance test suite first to determine the grade.",
61
+ {
62
+ url: z.string().url().describe("The MCP server URL to test")
63
+ },
64
+ async ({ url }) => {
65
+ try {
66
+ const report = await runComplianceSuite(url);
67
+ const badge = report.badge;
68
+ return {
69
+ content: [{
70
+ type: "text",
71
+ text: [
72
+ `Grade: ${report.grade} (${report.score}%)`,
73
+ "",
74
+ "Markdown:",
75
+ badge.markdown,
76
+ "",
77
+ "HTML:",
78
+ badge.html
79
+ ].join("\n")
80
+ }]
81
+ };
82
+ } catch (err) {
83
+ return {
84
+ content: [{ type: "text", text: `Error: ${err.message}` }],
85
+ isError: true
86
+ };
87
+ }
52
88
  }
53
- }
54
- );
55
- server.tool(
56
- "mcp_compliance_badge",
57
- "Get the badge markdown embed code for an MCP server. Runs the compliance test suite first to determine the grade.",
58
- {
59
- url: z.string().url().describe("The MCP server URL to test")
60
- },
61
- async ({ url }) => {
62
- try {
63
- const report = await runComplianceSuite(url);
64
- const badge = report.badge;
89
+ );
90
+ server2.tool(
91
+ "mcp_compliance_explain",
92
+ "Explain what a specific compliance test ID checks and why it matters.",
93
+ {
94
+ testId: z.string().describe('The test ID to explain (e.g., "transport-post", "lifecycle-init", "tools-schema")')
95
+ },
96
+ async ({ testId }) => {
97
+ const def = TEST_DEFINITIONS.find((t) => t.id === testId);
98
+ if (!def) {
99
+ return {
100
+ content: [{
101
+ type: "text",
102
+ text: `Unknown test ID: "${testId}"
103
+
104
+ Valid test IDs:
105
+ ${TEST_DEFINITIONS.map((t) => t.id).join(", ")}`
106
+ }],
107
+ isError: true
108
+ };
109
+ }
65
110
  return {
66
111
  content: [{
67
112
  type: "text",
68
113
  text: [
69
- `Grade: ${report.grade} (${report.score}%)`,
114
+ `Test: ${def.id}`,
115
+ `Name: ${def.name}`,
116
+ `Category: ${def.category}`,
117
+ `Required: ${def.required ? "Yes" : "No"}`,
118
+ `Spec reference: https://modelcontextprotocol.io/specification/2025-11-25/${def.specRef}`,
70
119
  "",
71
- "Markdown:",
72
- badge.markdown,
73
- "",
74
- "HTML:",
75
- badge.html
120
+ def.description
76
121
  ].join("\n")
77
122
  }]
78
123
  };
79
- } catch (err) {
80
- return {
81
- content: [{ type: "text", text: `Error: ${err.message}` }],
82
- isError: true
83
- };
84
124
  }
85
- }
86
- );
87
- server.tool(
88
- "mcp_compliance_explain",
89
- "Explain what a specific compliance test ID checks and why it matters.",
90
- {
91
- testId: z.string().describe('The test ID to explain (e.g., "transport-post", "lifecycle-init", "tools-schema")')
92
- },
93
- async ({ testId }) => {
94
- const def = TEST_DEFINITIONS.find((t) => t.id === testId);
95
- if (!def) {
96
- const ids = TEST_DEFINITIONS.map((t) => t.id).join(", ");
97
- return {
98
- content: [{
99
- type: "text",
100
- text: `Unknown test ID: "${testId}"
125
+ );
126
+ }
101
127
 
102
- Valid test IDs:
103
- ${ids}`
104
- }],
105
- isError: true
106
- };
107
- }
108
- return {
109
- content: [{
110
- type: "text",
111
- text: [
112
- `Test: ${def.id}`,
113
- `Name: ${def.name}`,
114
- `Category: ${def.category}`,
115
- `Required: ${def.required ? "Yes" : "No"}`,
116
- `Spec reference: https://modelcontextprotocol.io/specification/2025-11-25/${def.specRef}`,
117
- "",
118
- def.description
119
- ].join("\n")
120
- }]
121
- };
122
- }
123
- );
128
+ // src/mcp/server.ts
129
+ var require2 = createRequire(import.meta.url);
130
+ var { version } = require2("../../package.json");
131
+ var server = new McpServer({ name: "mcp-compliance", version });
132
+ registerTools(server);
124
133
  async function main() {
125
134
  const transport = new StdioServerTransport();
126
135
  await server.connect(transport);
package/dist/runner.d.ts CHANGED
@@ -13,6 +13,7 @@ type Grade = 'A' | 'B' | 'C' | 'D' | 'F';
13
13
  type Overall = 'pass' | 'partial' | 'fail';
14
14
  interface ComplianceReport {
15
15
  specVersion: string;
16
+ toolVersion: string;
16
17
  url: string;
17
18
  timestamp: string;
18
19
  score: number;
@@ -30,6 +31,7 @@ interface ComplianceReport {
30
31
  total: number;
31
32
  }>;
32
33
  tests: TestResult[];
34
+ warnings: string[];
33
35
  serverInfo: {
34
36
  protocolVersion: string | null;
35
37
  name: string | null;
@@ -39,7 +41,9 @@ interface ComplianceReport {
39
41
  toolCount: number;
40
42
  toolNames: string[];
41
43
  resourceCount: number;
44
+ resourceNames: string[];
42
45
  promptCount: number;
46
+ promptNames: string[];
43
47
  badge: {
44
48
  imageUrl: string;
45
49
  reportUrl: string;
@@ -55,7 +59,7 @@ interface TestDefinition {
55
59
  specRef: string;
56
60
  description: string;
57
61
  }
58
- /** All 24 test IDs with descriptions for the explain command */
62
+ /** All 43 test IDs with descriptions for the explain command */
59
63
  declare const TEST_DEFINITIONS: TestDefinition[];
60
64
 
61
65
  declare function computeGrade(score: number): Grade;
@@ -92,6 +96,14 @@ interface RunOptions {
92
96
  onProgress?: (testId: string, passed: boolean, details: string) => void;
93
97
  /** Extra headers to include on all requests */
94
98
  headers?: Record<string, string>;
99
+ /** Request timeout in milliseconds (default: 15000) */
100
+ timeout?: number;
101
+ /** Number of retries for failed tests (default: 0) */
102
+ retries?: number;
103
+ /** Only run tests matching these category names or test IDs */
104
+ only?: string[];
105
+ /** Skip tests matching these category names or test IDs */
106
+ skip?: string[];
95
107
  }
96
108
  /**
97
109
  * Run the full MCP compliance test suite against a URL.
package/dist/runner.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  computeScore,
5
5
  generateBadge,
6
6
  runComplianceSuite
7
- } from "./chunk-OOJ4PMF7.js";
7
+ } from "./chunk-SP24UFRC.js";
8
8
  export {
9
9
  TEST_DEFINITIONS,
10
10
  computeGrade,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/mcp-compliance",
3
- "version": "0.1.2",
3
+ "version": "0.2.1",
4
4
  "description": "CLI tool and MCP server that tests MCP servers for spec compliance",
5
5
  "license": "MIT",
6
6
  "author": "Yaw Labs (https://yaw.sh)",
@@ -28,7 +28,7 @@
28
28
  "prepublishOnly": "npm run build"
29
29
  },
30
30
  "dependencies": {
31
- "@modelcontextprotocol/sdk": "^1.12.1",
31
+ "@modelcontextprotocol/sdk": "^1.29.0",
32
32
  "chalk": "^5.4.1",
33
33
  "commander": "^13.1.0",
34
34
  "undici": "^7.8.0",