@openwop/openwop-conformance 1.133.0 → 1.134.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openwop/openwop-conformance",
3
- "version": "1.133.0",
3
+ "version": "1.134.0",
4
4
  "description": "Production-ready black-box conformance suite for OpenWOP v1.0 compliant servers.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "_comment": "Provenance of this vendored schemas/ copy. See conformance/README.md \u00a7\"Resolving the contract\". Compare against the stamp in your installed @openwop/openwop-conformance to detect a stale hand-copied contract.",
3
- "suiteVersion": "1.133.0",
4
- "corpusCommit": "01d2c45b0cc72ac953bc3c996f9bc3004d3ec297"
3
+ "suiteVersion": "1.134.0",
4
+ "corpusCommit": "fbb82fa8ea94c25358a63fda98bd49fdb528693a"
5
5
  }
package/src/lib/driver.ts CHANGED
@@ -35,7 +35,9 @@ class OpenWOPDriver {
35
35
  init: OpenWOPRequestInit = {},
36
36
  ): Promise<OpenWOPResponse> {
37
37
  const env = loadEnv();
38
- const url = `${env.baseUrl}${path}`;
38
+ // An absolute URL is used as-is (a host may advertise its MCP server mount or
39
+ // an A2A endpoint on another origin); a path is joined to the base URL.
40
+ const url = /^https?:\/\//i.test(path) ? path : `${env.baseUrl}${path}`;
39
41
 
40
42
  const headers: Record<string, string> = {
41
43
  Accept: 'application/json',
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Where a host mounts its MCP server (RFC 0153 §B / `mcp-integration.md`
3
+ * §"MCP server composition").
4
+ *
5
+ * The reference boots mount it at the sample-seam path
6
+ * `/v1/host/sample/mcp`, and until suite 1.134.0 every server-side MCP
7
+ * scenario hard-coded that path. The v1.0 discovery baseline has always let a
8
+ * host SAY where its mount is — `capabilities.mcp.serverUrls: string[]`
9
+ * (`mcp-discoverability.test.ts`) — and the first deployed host to advertise
10
+ * `mcp-2026-07-28` mounted at `/v1/host/openwop-app/mcp`, advertised exactly
11
+ * that, and watched ten `server/discover` legs 404 against the sample path and
12
+ * return early (S25, openwop-app H38, 2026-08-17). So: read the advert first,
13
+ * fall back to the sample path, and never treat "the mount answered 404" as a
14
+ * pass — that is `seamAbsent` (the host advertised a server mount it does not
15
+ * serve where it said).
16
+ */
17
+ import { driver } from './driver.js';
18
+ import { capabilityFamily } from './discovery-capabilities.js';
19
+
20
+ export const SAMPLE_MCP_MOUNT = '/v1/host/sample/mcp';
21
+
22
+ interface McpAdvert {
23
+ readonly supported?: boolean;
24
+ readonly serverUrls?: unknown;
25
+ readonly serverMount?: { readonly supported?: boolean };
26
+ }
27
+
28
+ /**
29
+ * The MCP server mount to POST JSON-RPC to: `capabilities.mcp.serverUrls[0]`
30
+ * when the host advertises one (a path is joined to the base URL by the driver;
31
+ * an absolute URL is used as-is), else the sample-seam path.
32
+ */
33
+ export async function mcpServerMount(): Promise<string> {
34
+ const disco = await driver.get('/.well-known/openwop');
35
+ const mcp = capabilityFamily<McpAdvert>(disco.json, 'mcp');
36
+ const urls = Array.isArray(mcp?.serverUrls) ? (mcp?.serverUrls as unknown[]) : [];
37
+ const first = urls.find((u): u is string => typeof u === 'string' && u.length > 0);
38
+ return first ?? SAMPLE_MCP_MOUNT;
39
+ }
@@ -25,6 +25,8 @@
25
25
 
26
26
  import { describe, it, expect, beforeAll, afterAll } from 'vitest';
27
27
  import { driver } from '../lib/driver.js';
28
+ import { seamAbsent } from '../lib/soft-skip.js';
29
+ import { mcpServerMount } from '../lib/mcp-mount.js';
28
30
  import { behaviorGate } from '../lib/behavior-gate.js';
29
31
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
30
32
  import { McpFakeServer, MCP_ERR } from '../lib/mcp-fake-server.js';
@@ -170,7 +172,7 @@ async function claimsCurrent(): Promise<boolean> {
170
172
  }
171
173
  async function hostRpc(method: string, params: Record<string, unknown>, headers: Record<string, string>) {
172
174
  // The reference host mounts its MCP server at /v1/host/sample/mcp (mcp-server-* scenarios).
173
- const res = await driver.post('/v1/host/sample/mcp', { jsonrpc: '2.0', id: 1, method, params }, { headers });
175
+ const res = await driver.post(await mcpServerMount(), { jsonrpc: '2.0', id: 1, method, params }, { headers });
174
176
  return { status: res.status, body: res.json as { result?: Record<string, unknown>; error?: { code: number; data?: Record<string, unknown> } } };
175
177
  }
176
178
 
@@ -179,7 +181,7 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §B — host as MCP ser
179
181
  if (!behaviorGate(PROFILE, await claimsCurrent())) return;
180
182
  const caps = (await mcp())!;
181
183
  const r = await hostRpc('server/discover', { _meta: { [META_V]: '2026-07-28', [META_C]: {} } }, { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'server/discover' });
182
- if (r.status === 404 || r.status === 403) return; // mount not wired at the sample path — the mcp-server-* legs cover that gap
184
+ if (r.status === 404 || r.status === 403) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${r.status} RFC 0153 §B is unobservable at the path the host itself advertised`);
183
185
  expect(r.status, driver.describe('mcp-integration.md §B', 'server/discover is a server MUST under 2026-07-28')).toBe(200);
184
186
  expect(r.body.result?.['resultType']).toBe('complete');
185
187
  expect([...((r.body.result?.['supportedVersions'] as string[] | undefined) ?? [])].sort(), driver.describe('mcp-integration.md §B', 'server/discover.supportedVersions MUST equal capabilities.mcp.protocolVersions — two documents, one fact')).toEqual([...(caps.protocolVersions ?? [])].sort());
@@ -196,7 +198,7 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §B — host as MCP ser
196
198
  // answered -32022 — the leg was testing an unstated precedence
197
199
  // (mcp-integration.md §B: agreement is checked before selection).
198
200
  const mismatch = await hostRpc('tools/list', { _meta: { [META_V]: '2025-06-18', [META_C]: {} } }, { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'tools/list' });
199
- if (mismatch.status === 404 || mismatch.status === 403) return;
201
+ if (mismatch.status === 404 || mismatch.status === 403) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${mismatch.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
200
202
  expect(mismatch.status, driver.describe('mcp-integration.md §B', 'header ≠ body MUST be refused 400 (HeaderMismatchError -32020) — fail closed')).toBe(400);
201
203
  expect(mismatch.body.error?.code).toBe(MCP_ERR.HEADER_MISMATCH);
202
204
  const unsupported = await hostRpc('tools/list', { _meta: { [META_V]: '1999-01-01', [META_C]: {} } }, { 'MCP-Protocol-Version': '1999-01-01', 'Mcp-Method': 'tools/list' });
@@ -22,6 +22,8 @@
22
22
 
23
23
  import { describe, it, expect } from 'vitest';
24
24
  import { driver } from '../lib/driver.js';
25
+ import { seamAbsent } from '../lib/soft-skip.js';
26
+ import { mcpServerMount } from '../lib/mcp-mount.js';
25
27
  import { behaviorGate } from '../lib/behavior-gate.js';
26
28
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
27
29
 
@@ -38,7 +40,7 @@ async function claimsCurrent(): Promise<boolean> {
38
40
  async function listAs(bearer?: string) {
39
41
  const headers: Record<string, string> = { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'tools/list' };
40
42
  if (bearer) headers['authorization'] = `Bearer ${bearer}`;
41
- const res = await driver.post('/v1/host/sample/mcp', { jsonrpc: '2.0', id: 1, method: 'tools/list', params: { _meta: { [META_V]: '2026-07-28', [META_C]: {} } } }, { headers });
43
+ const res = await driver.post(await mcpServerMount(), { jsonrpc: '2.0', id: 1, method: 'tools/list', params: { _meta: { [META_V]: '2026-07-28', [META_C]: {} } } }, { headers });
42
44
  return { status: res.status, body: res.json as { result?: { tools?: unknown[]; cacheScope?: string; ttlMs?: number } } };
43
45
  }
44
46
 
@@ -46,7 +48,7 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §D — mcp-cache-tenan
46
48
  it('a per-caller list is cacheScope private; a public list is byte-identical across callers', async () => {
47
49
  if (!behaviorGate(PROFILE, await claimsCurrent())) return;
48
50
  const mine = await listAs();
49
- if (mine.status === 404 || mine.status === 403) return;
51
+ if (mine.status === 404 || mine.status === 403) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${mine.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
50
52
  expect(['public', 'private'], driver.describe('mcp-integration.md §D', 'cacheScope MUST be present on tools/list')).toContain(mine.body.result?.cacheScope);
51
53
  const other = process.env.OPENWOP_TEST_SECONDARY_API_KEY;
52
54
  if (!other) {
@@ -18,6 +18,8 @@
18
18
 
19
19
  import { describe, it, expect } from 'vitest';
20
20
  import { driver } from '../lib/driver.js';
21
+ import { seamAbsent } from '../lib/soft-skip.js';
22
+ import { mcpServerMount } from '../lib/mcp-mount.js';
21
23
  import { behaviorGate } from '../lib/behavior-gate.js';
22
24
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
23
25
 
@@ -38,10 +40,10 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §E — mcp-current-aut
38
40
  const { mcp, anon } = await disco();
39
41
  const claims = mcp?.supported === true && (mcp.profiles ?? []).includes(PROFILE) && mcp.serverMount?.supported === true;
40
42
  if (!behaviorGate(PROFILE, claims)) return;
41
- const authed = await driver.post('/v1/host/sample/mcp', REQ, { headers: HDR });
42
- if (authed.status === 404 || authed.status === 403) return; // mount not at the sample path
43
+ const authed = await driver.post(await mcpServerMount(), REQ, { headers: HDR });
44
+ if (authed.status === 404 || authed.status === 403) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${authed.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
43
45
  expect(authed.status, driver.describe('mcp-integration.md §E', 'the authenticated call MUST succeed at the same path, so a refusal below is not a wrong path')).toBe(200);
44
- const anonymous = await driver.post('/v1/host/sample/mcp', REQ, { headers: HDR, authenticated: false });
46
+ const anonymous = await driver.post(await mcpServerMount(), REQ, { headers: HDR, authenticated: false });
45
47
  if (anon?.supported === true) {
46
48
  // Anonymous is permitted only through the RFC 0132 surface; a 200 here is that surface answering.
47
49
  expect([200, 401, 403]).toContain(anonymous.status);
@@ -23,6 +23,7 @@
23
23
  import { describe, it, expect } from 'vitest';
24
24
  import { softSkip, seamAbsent } from '../lib/soft-skip.js';
25
25
  import { driver } from '../lib/driver.js';
26
+ import { mcpServerMount } from '../lib/mcp-mount.js';
26
27
  import { behaviorGate } from '../lib/behavior-gate.js';
27
28
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
28
29
  import { getMcpFakeServer } from '../lib/mcp-fake-server.js';
@@ -66,7 +67,7 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §D — mcp-extension-o
66
67
  const caps = await mcp();
67
68
  const claims = caps?.supported === true && (caps.profiles ?? []).includes('mcp-2026-07-28') && caps.serverMount?.supported === true;
68
69
  if (!behaviorGate('mcp-2026-07-28', claims)) return;
69
- const res = await driver.post('/v1/host/sample/mcp', {
70
+ const res = await driver.post(await mcpServerMount(), {
70
71
  jsonrpc: '2.0', id: 1, method: 'tools/list',
71
72
  params: { _meta: { [META_V]: '2026-07-28', [META_C]: { extensions: { 'io.example/authority': { admin: true } } }, 'io.example/authority': { grantScopes: ['*'] } } },
72
73
  }, { headers: { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'tools/list' } });
@@ -33,6 +33,7 @@
33
33
  import { describe, it, expect } from 'vitest';
34
34
  import { softSkip, seamAbsent } from '../lib/soft-skip.js';
35
35
  import { driver } from '../lib/driver.js';
36
+ import { mcpServerMount } from '../lib/mcp-mount.js';
36
37
  import { behaviorGate } from '../lib/behavior-gate.js';
37
38
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
38
39
  import { getMcpFakeServer } from '../lib/mcp-fake-server.js';
@@ -120,7 +121,7 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §C — mcp-mrtr-roundt
120
121
  // not seam absence and not a host finding — fail loudly at the source.
121
122
  expect(reg.status, driver.describe('host-sample-test-seams.md §"sample workflows"', `the registration fixture MUST be accepted; a 4xx means the fixture this leg posts is malformed (suite defect): ${JSON.stringify(reg.json).slice(0, 200)}`)).toBeLessThan(400);
122
123
  const hdr = { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'tools/call', 'Mcp-Name': TOOL };
123
- const first = await driver.post('/v1/host/sample/mcp', { jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: TOOL, arguments: {}, _meta: { [META_V]: '2026-07-28', [META_C]: { elicitation: {} } } } }, { headers: hdr });
124
+ const first = await driver.post(await mcpServerMount(), { jsonrpc: '2.0', id: 1, method: 'tools/call', params: { name: TOOL, arguments: {}, _meta: { [META_V]: '2026-07-28', [META_C]: { elicitation: {} } } } }, { headers: hdr });
124
125
  if (first.status === 404) return seamAbsent('host advertises an MCP server mount but /v1/host/sample/mcp answered 404');
125
126
  const r1 = first.json as { result?: { resultType?: string; inputRequests?: Record<string, { method?: string }>; requestState?: string }; error?: { code: number } };
126
127
  expect(r1.error, driver.describe('mcp-integration.md §C.2', `tools/call MUST NOT error: ${JSON.stringify(r1.error)}`)).toBeUndefined();
@@ -129,11 +130,11 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §C — mcp-mrtr-roundt
129
130
  expect(key, driver.describe('mcp-integration.md §C.2', 'inputRequests MUST carry the elicitation')).toBeDefined();
130
131
  expect(r1.result?.inputRequests?.[key!]?.method).toBe('elicitation/create');
131
132
  expect(typeof r1.result?.requestState, driver.describe('mcp-integration.md §C.2', 'requestState MUST be present (opaque, integrity-protected, bound to principal/TTL/request/runId/interrupt token)')).toBe('string');
132
- const retry = await driver.post('/v1/host/sample/mcp', { jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: TOOL, arguments: {}, requestState: r1.result!.requestState, inputResponses: { [key!]: { action: 'accept', content: { name: 'Ada' } } }, _meta: { [META_V]: '2026-07-28', [META_C]: { elicitation: {} } } } }, { headers: hdr });
133
+ const retry = await driver.post(await mcpServerMount(), { jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: TOOL, arguments: {}, requestState: r1.result!.requestState, inputResponses: { [key!]: { action: 'accept', content: { name: 'Ada' } } }, _meta: { [META_V]: '2026-07-28', [META_C]: { elicitation: {} } } } }, { headers: hdr });
133
134
  const r2 = retry.json as { result?: { resultType?: string }; error?: { code: number } };
134
135
  expect(r2.error).toBeUndefined();
135
136
  expect(['complete', 'input_required'], driver.describe('mcp-integration.md §C.2', 'the retry MUST resolve the interrupt (complete) or ask for the next pending input')).toContain(r2.result?.resultType);
136
- const forged = await driver.post('/v1/host/sample/mcp', { jsonrpc: '2.0', id: 3, method: 'tools/call', params: { name: TOOL, arguments: {}, requestState: 'forged', inputResponses: { [key!]: { action: 'accept', content: { name: 'Eve' } } }, _meta: { [META_V]: '2026-07-28', [META_C]: { elicitation: {} } } } }, { headers: hdr });
137
+ const forged = await driver.post(await mcpServerMount(), { jsonrpc: '2.0', id: 3, method: 'tools/call', params: { name: TOOL, arguments: {}, requestState: 'forged', inputResponses: { [key!]: { action: 'accept', content: { name: 'Eve' } } }, _meta: { [META_V]: '2026-07-28', [META_C]: { elicitation: {} } } } }, { headers: hdr });
137
138
  const r3 = forged.json as { result?: { resultType?: string }; error?: { code: number } };
138
139
  expect(r3.error !== undefined || forged.status >= 400, driver.describe('mcp-integration.md §C.2', 'a requestState that fails integrity verification MUST be refused (upstream: attacker-controlled input)')).toBe(true);
139
140
  });
@@ -13,6 +13,8 @@
13
13
 
14
14
  import { describe, it, expect } from 'vitest';
15
15
  import { driver } from '../lib/driver.js';
16
+ import { seamAbsent } from '../lib/soft-skip.js';
17
+ import { mcpServerMount } from '../lib/mcp-mount.js';
16
18
 
17
19
  interface DiscoveryDoc {
18
20
  capabilities?: Record<string, unknown>;
@@ -31,7 +33,7 @@ async function rpc(method: string, params?: Record<string, unknown>) {
31
33
  const id = Math.floor(Math.random() * 1e6);
32
34
  const req: Record<string, unknown> = { jsonrpc: '2.0', id, method };
33
35
  if (params !== undefined) req.params = params;
34
- const res = await driver.post('/v1/host/sample/mcp', req);
36
+ const res = await driver.post(await mcpServerMount(), req);
35
37
  return { status: res.status, body: res.json as { result?: unknown; error?: { code: number; message: string } } };
36
38
  }
37
39
 
@@ -71,7 +73,7 @@ describe('mcp-server-elicitation-bridge: behavioral (RFC 0020 §A point 3)', ()
71
73
  required: ['name'],
72
74
  },
73
75
  });
74
- if (r.status === 404) return;
76
+ if (r.status === 404) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${r.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
75
77
  expect(r.status, 'JSON-RPC envelope MUST 200').toBe(200);
76
78
  const dispatched = !!r.body.result || (!!r.body.error && r.body.error.code !== -32601);
77
79
  expect(
@@ -8,6 +8,8 @@
8
8
 
9
9
  import { describe, it, expect } from 'vitest';
10
10
  import { driver } from '../lib/driver.js';
11
+ import { seamAbsent } from '../lib/soft-skip.js';
12
+ import { mcpServerMount } from '../lib/mcp-mount.js';
11
13
 
12
14
  interface DiscoveryDoc {
13
15
  capabilities?: Record<string, unknown>;
@@ -26,7 +28,7 @@ async function rpc(method: string, params?: Record<string, unknown>) {
26
28
  const id = Math.floor(Math.random() * 1e6);
27
29
  const req: Record<string, unknown> = { jsonrpc: '2.0', id, method };
28
30
  if (params !== undefined) req.params = params;
29
- const res = await driver.post('/v1/host/sample/mcp', req);
31
+ const res = await driver.post(await mcpServerMount(), req);
30
32
  return { status: res.status, body: res.json as { result?: unknown; error?: { code: number; message: string } } };
31
33
  }
32
34
 
@@ -65,7 +67,7 @@ describe('mcp-server-prompt-roundtrip: behavioral (RFC 0020)', () => {
65
67
  if (!(await registerPromptWorkflow())) return;
66
68
 
67
69
  const list = await rpc('prompts/list');
68
- if (list.status === 404) return;
70
+ if (list.status === 404) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${list.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
69
71
  const prompts = (list.body.result as { prompts?: Array<{ name: string }> } | undefined)?.prompts ?? [];
70
72
  expect(
71
73
  prompts.find((p) => p.name === PROMPT_NAME),
@@ -10,6 +10,8 @@
10
10
 
11
11
  import { describe, it, expect } from 'vitest';
12
12
  import { driver } from '../lib/driver.js';
13
+ import { seamAbsent } from '../lib/soft-skip.js';
14
+ import { mcpServerMount } from '../lib/mcp-mount.js';
13
15
 
14
16
  interface DiscoveryDoc {
15
17
  capabilities?: Record<string, unknown>;
@@ -28,7 +30,7 @@ async function rpc(method: string, params?: Record<string, unknown>) {
28
30
  const id = Math.floor(Math.random() * 1e6);
29
31
  const req: Record<string, unknown> = { jsonrpc: '2.0', id, method };
30
32
  if (params !== undefined) req.params = params;
31
- const res = await driver.post('/v1/host/sample/mcp', req);
33
+ const res = await driver.post(await mcpServerMount(), req);
32
34
  return { status: res.status, body: res.json as { result?: unknown; error?: { code: number; message: string } } };
33
35
  }
34
36
 
@@ -67,7 +69,7 @@ describe('mcp-server-resource-roundtrip: behavioral (RFC 0020)', () => {
67
69
  if (!(await registerResourceWorkflow())) return;
68
70
 
69
71
  const list = await rpc('resources/list');
70
- if (list.status === 404) return;
72
+ if (list.status === 404) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${list.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
71
73
  const resources = (list.body.result as { resources?: Array<{ uri: string }> } | undefined)?.resources ?? [];
72
74
  expect(
73
75
  resources.find((r) => r.uri === RESOURCE_URI),
@@ -16,6 +16,8 @@
16
16
 
17
17
  import { describe, it, expect } from 'vitest';
18
18
  import { driver } from '../lib/driver.js';
19
+ import { seamAbsent } from '../lib/soft-skip.js';
20
+ import { mcpServerMount } from '../lib/mcp-mount.js';
19
21
 
20
22
  interface DiscoveryDoc {
21
23
  capabilities?: Record<string, unknown>;
@@ -34,7 +36,7 @@ async function rpc(method: string, params?: Record<string, unknown>) {
34
36
  const id = Math.floor(Math.random() * 1e6);
35
37
  const req: Record<string, unknown> = { jsonrpc: '2.0', id, method };
36
38
  if (params !== undefined) req.params = params;
37
- const res = await driver.post('/v1/host/sample/mcp', req);
39
+ const res = await driver.post(await mcpServerMount(), req);
38
40
  return { status: res.status, body: res.json as { result?: unknown; error?: { code: number; message: string } } };
39
41
  }
40
42
 
@@ -70,7 +72,7 @@ describe('mcp-server-sampling-bridge: behavioral (RFC 0020 §A point 3)', () =>
70
72
  messages: [{ role: 'user', content: { type: 'text', text: 'ping' } }],
71
73
  maxTokens: 16,
72
74
  });
73
- if (r.status === 404) return;
75
+ if (r.status === 404) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${r.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
74
76
  expect(r.status, 'JSON-RPC envelope MUST 200').toBe(200);
75
77
  const dispatched = !!r.body.result || (!!r.body.error && r.body.error.code !== -32601);
76
78
  expect(
@@ -14,6 +14,8 @@
14
14
 
15
15
  import { describe, it, expect } from 'vitest';
16
16
  import { driver } from '../lib/driver.js';
17
+ import { seamAbsent } from '../lib/soft-skip.js';
18
+ import { mcpServerMount } from '../lib/mcp-mount.js';
17
19
 
18
20
  interface DiscoveryDoc {
19
21
  capabilities?: Record<string, unknown>;
@@ -32,7 +34,7 @@ async function rpc(method: string, params?: Record<string, unknown>): Promise<{
32
34
  const id = Math.floor(Math.random() * 1e6);
33
35
  const req: Record<string, unknown> = { jsonrpc: '2.0', id, method };
34
36
  if (params !== undefined) req.params = params;
35
- const res = await driver.post('/v1/host/sample/mcp', req);
37
+ const res = await driver.post(await mcpServerMount(), req);
36
38
  return { status: res.status, body: res.json as { result?: unknown; error?: { code: number; message: string } } };
37
39
  }
38
40
 
@@ -83,7 +85,7 @@ describe('mcp-server-tool-roundtrip: behavioral (RFC 0020 §A points 1-2)', () =
83
85
  if (!registered) return; // host doesn't expose workflow registration
84
86
 
85
87
  const list = await rpc('tools/list');
86
- if (list.status === 404) return; // host doesn't expose the seam
88
+ if (list.status === 404) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${list.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
87
89
  expect(list.status, 'tools/list MUST 200').toBe(200);
88
90
  const tools = (list.body.result as { tools?: Array<{ name: string }> } | undefined)?.tools ?? [];
89
91
  const found = tools.find((t) => t.name === TEST_TOOL_NAME);
@@ -12,6 +12,8 @@
12
12
 
13
13
  import { describe, it, expect } from 'vitest';
14
14
  import { driver } from '../lib/driver.js';
15
+ import { seamAbsent } from '../lib/soft-skip.js';
16
+ import { mcpServerMount } from '../lib/mcp-mount.js';
15
17
 
16
18
  interface DiscoveryDoc {
17
19
  capabilities?: Record<string, unknown>;
@@ -30,7 +32,7 @@ async function rpc(method: string, params?: Record<string, unknown>) {
30
32
  const id = Math.floor(Math.random() * 1e6);
31
33
  const req: Record<string, unknown> = { jsonrpc: '2.0', id, method };
32
34
  if (params !== undefined) req.params = params;
33
- const res = await driver.post('/v1/host/sample/mcp', req);
35
+ const res = await driver.post(await mcpServerMount(), req);
34
36
  return { status: res.status, body: res.json as { result?: unknown; error?: { code: number; message: string; data?: unknown } } };
35
37
  }
36
38
 
@@ -77,7 +79,7 @@ describe('mcp-server-untrusted-args: behavioral (RFC 0020 §D)', () => {
77
79
  name: TEST_TOOL_NAME,
78
80
  arguments: { wrongField: 'no' },
79
81
  });
80
- if (r.status === 404) return;
82
+ if (r.status === 404) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${r.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
81
83
  expect(r.status, 'JSON-RPC envelope MUST 200').toBe(200);
82
84
  expect(
83
85
  r.body.error?.code,
@@ -96,7 +98,7 @@ describe('mcp-server-untrusted-args: behavioral (RFC 0020 §D)', () => {
96
98
  name: TEST_TOOL_NAME,
97
99
  arguments: { text: 'hello' },
98
100
  });
99
- if (r.status === 404) return;
101
+ if (r.status === 404) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${r.status} — RFC 0153 §B is unobservable at the path the host itself advertised`);
100
102
  expect(r.status).toBe(200);
101
103
  if (r.body.error) {
102
104
  expect(r.body.error.code, 'valid args MUST NOT trigger -32602').not.toBe(-32602);
@@ -20,9 +20,10 @@
20
20
 
21
21
  import { describe, it, expect } from 'vitest';
22
22
  import { driver } from '../lib/driver.js';
23
+ import { mcpServerMount } from '../lib/mcp-mount.js';
23
24
  import { behaviorGate } from '../lib/behavior-gate.js';
24
25
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
25
- import { softSkip } from '../lib/soft-skip.js';
26
+ import { softSkip, seamAbsent } from '../lib/soft-skip.js';
26
27
 
27
28
  const PROFILE = 'mcp-2026-07-28';
28
29
  const META_V = 'io.modelcontextprotocol/protocolVersion';
@@ -37,7 +38,7 @@ async function claimsCurrent(): Promise<boolean> {
37
38
  }
38
39
  async function list() {
39
40
  const res = await driver.post(
40
- '/v1/host/sample/mcp',
41
+ await mcpServerMount(),
41
42
  { jsonrpc: '2.0', id: 1, method: 'tools/list', params: { _meta: { [META_V]: '2026-07-28', [META_C]: {}, [META_I]: { name: 'openwop-conformance', version: 'suite' } } } },
42
43
  { headers: { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'tools/list' } },
43
44
  );
@@ -49,12 +50,12 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §B — mcp-header-body
49
50
  if (!behaviorGate(PROFILE, await claimsCurrent())) return;
50
51
  const meta = { [META_V]: '2026-07-28', [META_C]: {}, [META_I]: { name: 'openwop-conformance', version: 'suite' } };
51
52
  // (a) Mcp-Method header disagrees with the JSON-RPC method
52
- const m = await driver.post('/v1/host/sample/mcp', { jsonrpc: '2.0', id: 1, method: 'tools/list', params: { _meta: meta } }, { headers: { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'resources/list' } });
53
+ const m = await driver.post(await mcpServerMount(), { jsonrpc: '2.0', id: 1, method: 'tools/list', params: { _meta: meta } }, { headers: { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'resources/list' } });
53
54
  if (m.status === 404 || m.status === 403) return softSkip('blocked', `MCP server mount /v1/host/sample/mcp answered ${m.status}`);
54
55
  expect(m.status, driver.describe('mcp-integration.md §B', 'Mcp-Method MUST equal the body method; disagreement MUST be refused 400 (mcp-header-body-consistent)')).toBe(400);
55
56
  expect((m.json as { error?: { code?: number } }).error?.code, driver.describe('mcp-integration.md §B', 'the refusal is HeaderMismatchError -32020')).toBe(-32020);
56
57
  // (b) Mcp-Name header disagrees with params.name on tools/call
57
- const n = await driver.post('/v1/host/sample/mcp', { jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: 'echo', arguments: {}, _meta: meta } }, { headers: { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'tools/call', 'Mcp-Name': 'not-echo' } });
58
+ const n = await driver.post(await mcpServerMount(), { jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: 'echo', arguments: {}, _meta: meta } }, { headers: { 'MCP-Protocol-Version': '2026-07-28', 'Mcp-Method': 'tools/call', 'Mcp-Name': 'not-echo' } });
58
59
  expect(n.status, driver.describe('mcp-integration.md §B', 'Mcp-Name MUST equal params.name; disagreement MUST be refused 400 (mcp-header-body-consistent)')).toBe(400);
59
60
  expect((n.json as { error?: { code?: number } }).error?.code, driver.describe('mcp-integration.md §B', 'the refusal is HeaderMismatchError -32020')).toBe(-32020);
60
61
  });
@@ -64,7 +65,7 @@ describe.skipIf(!process.env.OPENWOP_BASE_URL)('RFC 0153 §B — mcp-stateless-r
64
65
  it('tools/list succeeds with no initialize and no session; result carries resultType + cache hints; two connections agree', async () => {
65
66
  if (!behaviorGate(PROFILE, await claimsCurrent())) return;
66
67
  const a = await list();
67
- if (a.status === 404 || a.status === 403) return; // mount not at the sample pathcovered by mcp-server-* legs
68
+ if (a.status === 404 || a.status === 403) return seamAbsent(`host advertises an MCP server mount but the mount (capabilities.mcp.serverUrls[0], else /v1/host/sample/mcp) answered ${a.status} RFC 0153 §B is unobservable at the path the host itself advertised`);
68
69
  expect(a.status, driver.describe('mcp-integration.md §B', 'a core request MUST succeed without a prior initialize or a session header')).toBe(200);
69
70
  expect(a.body.error, driver.describe('mcp-integration.md §B', `stateless tools/list MUST NOT error: ${JSON.stringify(a.body.error)}`)).toBeUndefined();
70
71
  expect(a.body.result?.resultType, driver.describe('mcp-integration.md §B', 'every current-revision result carries resultType')).toBe('complete');
@@ -26,6 +26,7 @@
26
26
 
27
27
  import { describe, it, expect } from 'vitest';
28
28
  import { driver } from '../lib/driver.js';
29
+ import { seamAbsent } from '../lib/soft-skip.js';
29
30
  import { behaviorGate } from '../lib/behavior-gate.js';
30
31
  import { capabilityFamily } from '../lib/discovery-capabilities.js';
31
32
  import { getMcpFakeServer } from '../lib/mcp-fake-server.js';
@@ -123,8 +124,7 @@ describe('RFC 0153 §A/§B — MCP revision negotiation', () => {
123
124
  const caps = await mcp();
124
125
  server.reset();
125
126
  const drive = await driver.post('/v1/host/sample/mcp/invoke', { serverUrl: server.endpoint() });
126
- if (drive.status === 404 || drive.status === 403) return;
127
- // Discovery is a promise about behavior. A host that negotiates a revision
127
+ if (drive.status === 404 || drive.status === 403) return seamAbsent(`host advertises mcp version negotiation but the invoke seam /v1/host/sample/mcp/invoke answered ${drive.status} — the host-as-client legs are unobservable (host-sample-test-seams.md)`);
128
128
  // it never advertised has made its own discovery document unreliable, which
129
129
  // is worse than advertising nothing — a consumer that read it made a
130
130
  // decision on a fact that was not true.
@@ -149,7 +149,7 @@ describe('RFC 0153 §A/§B — MCP revision negotiation', () => {
149
149
  serverUrl: server.endpoint(),
150
150
  requestVersion: '1999-01-01',
151
151
  });
152
- if (drive.status === 404 || drive.status === 403) return;
152
+ if (drive.status === 404 || drive.status === 403) return seamAbsent(`host advertises mcp version negotiation but the invoke seam /v1/host/sample/mcp/invoke answered ${drive.status} — the host-as-client legs are unobservable (host-sample-test-seams.md)`);
153
153
  expect(
154
154
  drive.status >= 400,
155
155
  driver.describe('RFCS/0153 §B', 'an unsupported revision MUST fail rather than silently proceed'),