@yawlabs/mcp-compliance 0.14.3 → 0.14.4

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.
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  Built and maintained by [Yaw Labs](https://yaw.sh).
11
11
 
12
- [![Add to Yaw MCP](https://yaw.sh/yaw-mcp-button.svg)](yaw://install?name=mcp-compliance&command=npx&args=-y%2C%40yawlabs%2Fmcp-compliance&description=Test%20any%20MCP%20server%20against%20the%20spec%20-%2088-test%20suite%20with%20letter-grade%20scoring&source=https%3A%2F%2Fgithub.com%2FYawLabs%2Fmcp-compliance)
12
+ [![Add to Yaw MCP](https://yaw.sh/yaw-mcp-button.svg)](https://yaw.sh/mcp/install?name=mcp-compliance&command=npx&args=-y%2C%40yawlabs%2Fmcp-compliance&description=Test%20any%20MCP%20server%20against%20the%20spec%20-%2088-test%20suite%20with%20letter-grade%20scoring&source=https%3A%2F%2Fgithub.com%2FYawLabs%2Fmcp-compliance)
13
13
 
14
14
  One click adds this to your local Yaw MCP config so it's available in every Yaw Terminal session. Or install manually below.
15
15
 
@@ -127,10 +127,17 @@ function createHttpTransport(opts) {
127
127
  }
128
128
  return out;
129
129
  }
130
- async function doRawRequest(method, body, extraHeaders, timeout) {
130
+ async function doRawRequest(method, body, extraHeaders, timeout, omitUserHeaders) {
131
+ const base = sessionHeaders();
132
+ if (omitUserHeaders && omitUserHeaders.length > 0) {
133
+ const drop = new Set(omitUserHeaders.map((h) => h.toLowerCase()));
134
+ for (const key of Object.keys(base)) {
135
+ if (drop.has(key.toLowerCase())) delete base[key];
136
+ }
137
+ }
131
138
  const headers = {
132
139
  Accept: "application/json, text/event-stream",
133
- ...sessionHeaders(),
140
+ ...base,
134
141
  ...extraHeaders
135
142
  };
136
143
  if (body !== void 0 && !("Content-Type" in headers) && !("content-type" in headers)) {
@@ -155,7 +162,7 @@ function createHttpTransport(opts) {
155
162
  async request(method, params, nextId, init) {
156
163
  const id = nextId();
157
164
  const body = JSON.stringify({ jsonrpc: "2.0", id, method, params: params ?? {} });
158
- const raw = await doRawRequest("POST", body, init.headers ?? {}, init.timeout);
165
+ const raw = await doRawRequest("POST", body, init.headers ?? {}, init.timeout, init.omitUserHeaders);
159
166
  const contentType = (raw.headers["content-type"] || "").toLowerCase();
160
167
  let parsed;
161
168
  if (contentType.includes("text/event-stream")) {
@@ -185,7 +192,7 @@ function createHttpTransport(opts) {
185
192
  },
186
193
  async notify(method, params, init) {
187
194
  const body = JSON.stringify({ jsonrpc: "2.0", method, ...params ? { params } : {} });
188
- const raw = await doRawRequest("POST", body, init.headers ?? {}, init.timeout);
195
+ const raw = await doRawRequest("POST", body, init.headers ?? {}, init.timeout, init.omitUserHeaders);
189
196
  return { statusCode: raw.statusCode, headers: raw.headers };
190
197
  },
191
198
  async close() {
@@ -1451,10 +1458,11 @@ async function runComplianceSuite(target, options = {}) {
1451
1458
  const retries = options.retries || 0;
1452
1459
  let sessionId = null;
1453
1460
  let negotiatedProtocolVersion = null;
1454
- async function mcpRequest(_backendUrl, method, params, idCounter, extraHeaders, timeoutMs) {
1461
+ async function mcpRequest(_backendUrl, method, params, idCounter, extraHeaders, timeoutMs, omitUserHeaders) {
1455
1462
  const res = await transport.request(method, params, idCounter, {
1456
1463
  timeout: timeoutMs,
1457
- headers: extraHeaders
1464
+ headers: extraHeaders,
1465
+ omitUserHeaders
1458
1466
  });
1459
1467
  return {
1460
1468
  statusCode: res.statusCode ?? 200,
@@ -3168,7 +3176,9 @@ async function runComplianceSuite(target, options = {}) {
3168
3176
  const noAuthHeaders = {};
3169
3177
  if (sessionId) noAuthHeaders["mcp-session-id"] = sessionId;
3170
3178
  try {
3171
- const res = await mcpRequest(backendUrl, "ping", void 0, nextId, noAuthHeaders, timeout);
3179
+ const res = await mcpRequest(backendUrl, "ping", void 0, nextId, noAuthHeaders, timeout, [
3180
+ "authorization"
3181
+ ]);
3172
3182
  if (res.statusCode === 401 || res.statusCode === 403) {
3173
3183
  return { passed: true, details: `HTTP ${res.statusCode} (unauthenticated request rejected)` };
3174
3184
  }
@@ -3191,7 +3201,9 @@ async function runComplianceSuite(target, options = {}) {
3191
3201
  const noAuthHeaders = {};
3192
3202
  if (sessionId) noAuthHeaders["mcp-session-id"] = sessionId;
3193
3203
  try {
3194
- const res = await mcpRequest(backendUrl, "ping", void 0, nextId, noAuthHeaders, timeout);
3204
+ const res = await mcpRequest(backendUrl, "ping", void 0, nextId, noAuthHeaders, timeout, [
3205
+ "authorization"
3206
+ ]);
3195
3207
  if (res.statusCode === 401) {
3196
3208
  const wwwAuth = res.headers["www-authenticate"];
3197
3209
  if (wwwAuth) {
@@ -3226,7 +3238,9 @@ async function runComplianceSuite(target, options = {}) {
3226
3238
  };
3227
3239
  if (sessionId) malformedHeaders["mcp-session-id"] = sessionId;
3228
3240
  try {
3229
- const res = await mcpRequest(backendUrl, "ping", void 0, nextId, malformedHeaders, timeout);
3241
+ const res = await mcpRequest(backendUrl, "ping", void 0, nextId, malformedHeaders, timeout, [
3242
+ "authorization"
3243
+ ]);
3230
3244
  if (res.statusCode === 401 || res.statusCode === 403) {
3231
3245
  return { passed: true, details: `HTTP ${res.statusCode} (malformed auth rejected)` };
3232
3246
  }
@@ -3316,7 +3330,9 @@ async function runComplianceSuite(target, options = {}) {
3316
3330
  "mcp-session-id": sessionId
3317
3331
  };
3318
3332
  try {
3319
- const res = await mcpRequest(backendUrl, "ping", void 0, nextId, sessionOnlyHeaders, timeout);
3333
+ const res = await mcpRequest(backendUrl, "ping", void 0, nextId, sessionOnlyHeaders, timeout, [
3334
+ "authorization"
3335
+ ]);
3320
3336
  if (res.statusCode === 401 || res.statusCode === 403) {
3321
3337
  return { passed: true, details: `HTTP ${res.statusCode} (session ID alone not sufficient for auth)` };
3322
3338
  }
package/dist/index.js CHANGED
@@ -117,10 +117,17 @@ function createHttpTransport(opts) {
117
117
  }
118
118
  return out;
119
119
  }
120
- async function doRawRequest(method, body, extraHeaders, timeout) {
120
+ async function doRawRequest(method, body, extraHeaders, timeout, omitUserHeaders) {
121
+ const base = sessionHeaders();
122
+ if (omitUserHeaders && omitUserHeaders.length > 0) {
123
+ const drop = new Set(omitUserHeaders.map((h) => h.toLowerCase()));
124
+ for (const key of Object.keys(base)) {
125
+ if (drop.has(key.toLowerCase())) delete base[key];
126
+ }
127
+ }
121
128
  const headers = {
122
129
  Accept: "application/json, text/event-stream",
123
- ...sessionHeaders(),
130
+ ...base,
124
131
  ...extraHeaders
125
132
  };
126
133
  if (body !== void 0 && !("Content-Type" in headers) && !("content-type" in headers)) {
@@ -145,7 +152,7 @@ function createHttpTransport(opts) {
145
152
  async request(method, params, nextId, init) {
146
153
  const id = nextId();
147
154
  const body = JSON.stringify({ jsonrpc: "2.0", id, method, params: params ?? {} });
148
- const raw = await doRawRequest("POST", body, init.headers ?? {}, init.timeout);
155
+ const raw = await doRawRequest("POST", body, init.headers ?? {}, init.timeout, init.omitUserHeaders);
149
156
  const contentType = (raw.headers["content-type"] || "").toLowerCase();
150
157
  let parsed;
151
158
  if (contentType.includes("text/event-stream")) {
@@ -175,7 +182,7 @@ function createHttpTransport(opts) {
175
182
  },
176
183
  async notify(method, params, init) {
177
184
  const body = JSON.stringify({ jsonrpc: "2.0", method, ...params ? { params } : {} });
178
- const raw = await doRawRequest("POST", body, init.headers ?? {}, init.timeout);
185
+ const raw = await doRawRequest("POST", body, init.headers ?? {}, init.timeout, init.omitUserHeaders);
179
186
  return { statusCode: raw.statusCode, headers: raw.headers };
180
187
  },
181
188
  async close() {
@@ -1808,10 +1815,11 @@ async function runComplianceSuite(target, options = {}) {
1808
1815
  const retries = options.retries || 0;
1809
1816
  let sessionId = null;
1810
1817
  let negotiatedProtocolVersion = null;
1811
- async function mcpRequest(_backendUrl, method, params, idCounter, extraHeaders, timeoutMs) {
1818
+ async function mcpRequest(_backendUrl, method, params, idCounter, extraHeaders, timeoutMs, omitUserHeaders) {
1812
1819
  const res = await transport.request(method, params, idCounter, {
1813
1820
  timeout: timeoutMs,
1814
- headers: extraHeaders
1821
+ headers: extraHeaders,
1822
+ omitUserHeaders
1815
1823
  });
1816
1824
  return {
1817
1825
  statusCode: res.statusCode ?? 200,
@@ -3525,7 +3533,9 @@ async function runComplianceSuite(target, options = {}) {
3525
3533
  const noAuthHeaders = {};
3526
3534
  if (sessionId) noAuthHeaders["mcp-session-id"] = sessionId;
3527
3535
  try {
3528
- const res = await mcpRequest(backendUrl, "ping", void 0, nextId, noAuthHeaders, timeout);
3536
+ const res = await mcpRequest(backendUrl, "ping", void 0, nextId, noAuthHeaders, timeout, [
3537
+ "authorization"
3538
+ ]);
3529
3539
  if (res.statusCode === 401 || res.statusCode === 403) {
3530
3540
  return { passed: true, details: `HTTP ${res.statusCode} (unauthenticated request rejected)` };
3531
3541
  }
@@ -3548,7 +3558,9 @@ async function runComplianceSuite(target, options = {}) {
3548
3558
  const noAuthHeaders = {};
3549
3559
  if (sessionId) noAuthHeaders["mcp-session-id"] = sessionId;
3550
3560
  try {
3551
- const res = await mcpRequest(backendUrl, "ping", void 0, nextId, noAuthHeaders, timeout);
3561
+ const res = await mcpRequest(backendUrl, "ping", void 0, nextId, noAuthHeaders, timeout, [
3562
+ "authorization"
3563
+ ]);
3552
3564
  if (res.statusCode === 401) {
3553
3565
  const wwwAuth = res.headers["www-authenticate"];
3554
3566
  if (wwwAuth) {
@@ -3583,7 +3595,9 @@ async function runComplianceSuite(target, options = {}) {
3583
3595
  };
3584
3596
  if (sessionId) malformedHeaders["mcp-session-id"] = sessionId;
3585
3597
  try {
3586
- const res = await mcpRequest(backendUrl, "ping", void 0, nextId, malformedHeaders, timeout);
3598
+ const res = await mcpRequest(backendUrl, "ping", void 0, nextId, malformedHeaders, timeout, [
3599
+ "authorization"
3600
+ ]);
3587
3601
  if (res.statusCode === 401 || res.statusCode === 403) {
3588
3602
  return { passed: true, details: `HTTP ${res.statusCode} (malformed auth rejected)` };
3589
3603
  }
@@ -3673,7 +3687,9 @@ async function runComplianceSuite(target, options = {}) {
3673
3687
  "mcp-session-id": sessionId
3674
3688
  };
3675
3689
  try {
3676
- const res = await mcpRequest(backendUrl, "ping", void 0, nextId, sessionOnlyHeaders, timeout);
3690
+ const res = await mcpRequest(backendUrl, "ping", void 0, nextId, sessionOnlyHeaders, timeout, [
3691
+ "authorization"
3692
+ ]);
3677
3693
  if (res.statusCode === 401 || res.statusCode === 403) {
3678
3694
  return { passed: true, details: `HTTP ${res.statusCode} (session ID alone not sufficient for auth)` };
3679
3695
  }
@@ -2,7 +2,7 @@ import {
2
2
  SPEC_BASE,
3
3
  TEST_DEFINITIONS,
4
4
  runComplianceSuite
5
- } from "../chunk-6PF56RRO.js";
5
+ } from "../chunk-2CXRMEZ3.js";
6
6
 
7
7
  // src/mcp/server.ts
8
8
  import { existsSync, readFileSync, realpathSync } from "fs";
package/dist/runner.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  previewTests,
11
11
  runComplianceSuite,
12
12
  urlHash
13
- } from "./chunk-6PF56RRO.js";
13
+ } from "./chunk-2CXRMEZ3.js";
14
14
  export {
15
15
  SPEC_BASE,
16
16
  SPEC_VERSION,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/mcp-compliance",
3
- "version": "0.14.3",
3
+ "version": "0.14.4",
4
4
  "mcpName": "io.github.YawLabs/mcp-compliance",
5
5
  "description": "CLI tool and MCP server that tests MCP servers for spec compliance",
6
6
  "license": "MIT",
@@ -20,7 +20,7 @@
20
20
  "main": "./dist/runner.js",
21
21
  "types": "./dist/runner.d.ts",
22
22
  "bin": {
23
- "mcp-compliance": "./dist/index.js"
23
+ "mcp-compliance": "dist/index.js"
24
24
  },
25
25
  "files": [
26
26
  "dist",