mcp-integration-harness 0.1.0 → 0.2.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/README.md CHANGED
@@ -44,6 +44,15 @@ Four things are additionally untouched by any in-process test: `src/index.ts`,
44
44
  elicitation across a **process boundary**. This spawns the built artifact, so
45
45
  all four are on the path.
46
46
 
47
+ On framing, be precise about what that buys. Anything the transport reports out
48
+ of band — a line that parses as JSON but is not a JSON-RPC message, an era
49
+ mismatch, an unknown message id — fails the run and names the tool it happened
50
+ on. A line that is not JSON **at all** is swallowed inside the SDK's read
51
+ buffer, below any hook a client can install; if it also lacks a trailing
52
+ newline it corrupts the next real message, which surfaces as a request timeout
53
+ with a hint pointing at stdout. Owning stdout outright would need a transport of
54
+ our own, and that is not what this is yet.
55
+
47
56
  ## `expectEveryToolExercised`
48
57
 
49
58
  The part worth copying even if you write the rest yourself.
@@ -82,9 +91,16 @@ production". Hosts are compared numerically via
82
91
  `[::ffff:127.0.0.1]` and `localhost.` count and `127.example.com` — a hostname
83
92
  anybody can register — does not.
84
93
 
85
- `startServer` is the same idea as a property: the child gets `PATH` and the
86
- variables you passed. Nothing is inherited, so nothing can be inherited by
87
- accident.
94
+ `startServer` is the same idea as a property: the child gets `PATH`, a `HOME`
95
+ pointing at a temporary directory, and the variables you passed. Nothing else is
96
+ inherited, so nothing else can be inherited by accident.
97
+
98
+ That needs enforcing rather than merely not asking for it. `StdioClientTransport`
99
+ merges `getDefaultEnvironment()` _underneath_ whatever it is handed, which
100
+ carries `HOME`, `LOGNAME`, `SHELL`, `TERM`, `USER` — and on Windows the
101
+ `APPDATA` family — through from the parent. A server, or any dependency of one,
102
+ that reads `~/.netrc`, `~/.npmrc` or a credential file under `os.homedir()`
103
+ would otherwise run your suite as you. Those names are blanked explicitly.
88
104
 
89
105
  ## API
90
106
 
package/dist/harness.d.ts CHANGED
@@ -21,8 +21,17 @@ export interface StartServerOptions {
21
21
  *
22
22
  * Deliberately not merged with `process.env`. A `WIKIJS_URL` left in a shell
23
23
  * is otherwise enough to point an integration run — deletes included — at
24
- * whatever that variable happens to name. Nothing is inherited, so nothing
25
- * can be inherited by accident.
24
+ * whatever that variable happens to name.
25
+ *
26
+ * "Nothing is inherited" needs enforcing rather than merely not asking for
27
+ * it: `StdioClientTransport` merges `getDefaultEnvironment()` under whatever
28
+ * it is given, which carries `HOME`, `LOGNAME`, `SHELL`, `TERM`, `USER` and
29
+ * on Windows the `APPDATA` family through from the parent. A server — or any
30
+ * dependency of one — that reads `~/.netrc`, `~/.npmrc` or a credential file
31
+ * under `os.homedir()` would then run the suite as the developer. Those names
32
+ * are blanked here, and `HOME` points at a temporary directory rather than
33
+ * being empty, because an empty `HOME` breaks tools in a way that reads like
34
+ * a bug in the server.
26
35
  */
27
36
  env: Record<string, string>;
28
37
  /**
@@ -35,8 +44,17 @@ export interface StartServerOptions {
35
44
  timeoutSeconds?: number;
36
45
  }
37
46
  export interface CallOptions {
38
- /** Assert that the call fails. Refusals are behaviour worth pinning too. */
39
- expectError?: boolean;
47
+ /**
48
+ * Assert that the call fails. Refusals are behaviour worth pinning too.
49
+ *
50
+ * `true` only asserts that *something* failed, which is weaker than it looks:
51
+ * a renamed parameter makes the schema reject the call, and a guard test
52
+ * written this way stays green while the guard it names is no longer reached.
53
+ * Pass a string or a `RegExp` to require the reason as well — the returned
54
+ * text has to contain it, or match it — and prefer that wherever the refusal
55
+ * is the point of the test.
56
+ */
57
+ expectError?: boolean | string | RegExp;
40
58
  }
41
59
  export interface ToolResult {
42
60
  content?: {
package/dist/harness.js CHANGED
@@ -1,5 +1,6 @@
1
+ import { tmpdir } from 'node:os';
1
2
  import { Client } from '@modelcontextprotocol/client';
2
- import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';
3
+ import { DEFAULT_INHERITED_ENV_VARS, StdioClientTransport, } from '@modelcontextprotocol/client/stdio';
3
4
  /** Pulls the fallback token out of a refusal. */
4
5
  export function tokenOf(text) {
5
6
  const match = /confirm_token="([0-9a-f]+)"/.exec(text);
@@ -22,6 +23,7 @@ export async function startServer(options) {
22
23
  const prompts = [];
23
24
  const called = new Set();
24
25
  const errors = [];
26
+ const protocolErrors = [];
25
27
  const client = new Client({ name: 'mcp-integration-harness', version: '0.1.0' }, options.elicit === undefined ? {} : { capabilities: { elicitation: {} } });
26
28
  if (options.elicit !== undefined) {
27
29
  const behaviour = options.elicit;
@@ -37,11 +39,33 @@ export async function startServer(options) {
37
39
  return { action: 'accept', content: { confirm: true } };
38
40
  });
39
41
  }
42
+ // Out-of-band protocol failures. The transport reports a line that parses as
43
+ // JSON but is not a JSON-RPC message here — the `console.log(JSON.stringify(x))`
44
+ // that a server picks up from a dependency — and without a listener it is
45
+ // discarded, leaving a suite green while the framing this library exists to
46
+ // exercise is broken. Also catches era mismatches, unknown message ids and
47
+ // dropped inbound requests.
48
+ //
49
+ // The one case this does *not* reach is a line that is not JSON at all:
50
+ // `ReadBuffer.readMessage` swallows the SyntaxError inside the buffer, below
51
+ // any hook a client can install. Such a line without a trailing newline
52
+ // corrupts the next real message instead, which surfaces as a request
53
+ // timeout — see the hint in the failure below.
54
+ client.onerror = (error) => {
55
+ protocolErrors.push(error);
56
+ };
40
57
  const transport = new StdioClientTransport({
41
58
  command: process.execPath,
42
59
  args: [entry],
43
- // PATH only. See the comment on StartServerOptions.env.
44
- env: { PATH: process.env.PATH ?? '', ...options.env },
60
+ // PATH only, and the SDK's inherit list explicitly blanked — it merges
61
+ // getDefaultEnvironment() underneath whatever it is handed. See the comment
62
+ // on StartServerOptions.env.
63
+ env: {
64
+ ...Object.fromEntries(DEFAULT_INHERITED_ENV_VARS.map((name) => [name, ''])),
65
+ HOME: tmpdir(),
66
+ PATH: process.env.PATH ?? '',
67
+ ...options.env,
68
+ },
45
69
  ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
46
70
  stderr: 'pipe',
47
71
  });
@@ -53,7 +77,9 @@ export async function startServer(options) {
53
77
  errors.push(chunk.toString());
54
78
  });
55
79
  try {
56
- await client.connect(transport);
80
+ await client.connect(transport, {
81
+ timeout: (options.timeoutSeconds ?? 30) * 1000,
82
+ });
57
83
  }
58
84
  catch (error) {
59
85
  // A server that dies during the handshake reports "Connection closed" and
@@ -79,18 +105,56 @@ export async function startServer(options) {
79
105
  // since it started.
80
106
  throw new Error(`mcp-integration-harness: calling ${name} failed at the transport.\n` +
81
107
  `${String(error)}\n\nThe server's stderr so far:\n` +
82
- `${errors.join('') || '(nothing)'}`);
108
+ `${errors.join('') || '(nothing)'}\n\n` +
109
+ 'If that stderr is empty and this was a timeout, suspect stdout: a ' +
110
+ 'write there without a trailing newline is prepended to the next ' +
111
+ 'JSON-RPC message, and the reply is discarded inside the read buffer ' +
112
+ 'where no hook can see it. stdout belongs to the transport.');
83
113
  }
114
+ const expectation = callOptions.expectError ?? false;
115
+ const wantFailure = expectation !== false;
84
116
  const failed = result.isError === true;
85
- if (failed !== (callOptions.expectError ?? false)) {
86
- const text = textOf(result);
87
- throw new Error(callOptions.expectError
117
+ const text = textOf(result);
118
+ if (failed !== wantFailure) {
119
+ throw new Error(wantFailure
88
120
  ? `${name} was expected to fail and did not: ${text.slice(0, 500)}`
89
121
  : `${name} failed: ${text.slice(0, 500)}`);
90
122
  }
123
+ // A refusal that does not say why is a refusal that could have come from
124
+ // anywhere — the schema, a 500, a renamed argument. Where the caller named
125
+ // the reason, it has to be the reason.
126
+ if (typeof expectation === 'string' && !text.includes(expectation)) {
127
+ throw new Error(`${name} failed as expected, but not for the stated reason.\n` +
128
+ `Expected the message to contain: ${expectation}\n` +
129
+ `Got: ${text.slice(0, 500)}`);
130
+ }
131
+ if (expectation instanceof RegExp && !expectation.test(text)) {
132
+ throw new Error(`${name} failed as expected, but not for the stated reason.\n` +
133
+ `Expected the message to match: ${String(expectation)}\n` +
134
+ `Got: ${text.slice(0, 500)}`);
135
+ }
136
+ assertFramingIntact(`calling ${name}`);
91
137
  return result;
92
138
  };
93
139
  const call = async (name, args = {}, callOptions = {}) => textOf(await raw(name, args, callOptions));
140
+ /**
141
+ * Fails the run if the transport reported anything out of band.
142
+ *
143
+ * Checked after each call rather than only at the end, so the failure names
144
+ * the tool whose turn produced it instead of the whole suite.
145
+ */
146
+ function assertFramingIntact(during) {
147
+ if (protocolErrors.length === 0)
148
+ return;
149
+ const reported = protocolErrors.map((error) => error.message).join('\n');
150
+ protocolErrors.length = 0;
151
+ throw new Error(`mcp-integration-harness: the server broke the stdio framing while ${during}.\n` +
152
+ `${reported}\n\n` +
153
+ 'Something reached stdout that is not a JSON-RPC message — a stray ' +
154
+ 'console.log in the server or in one of its dependencies is the usual ' +
155
+ 'cause. Route it to stderr.\n\n' +
156
+ `The server's stderr so far:\n${errors.join('') || '(nothing)'}`);
157
+ }
94
158
  return {
95
159
  client,
96
160
  call,
@@ -104,6 +168,7 @@ export async function startServer(options) {
104
168
  },
105
169
  close: async () => {
106
170
  await client.close();
171
+ assertFramingIntact('closing the session');
107
172
  },
108
173
  };
109
174
  }
@@ -1 +1 @@
1
- {"version":3,"file":"harness.js","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"harness.js","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-integration-harness",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Drive an MCP server over real stdio against a real backend, and prove every tool was exercised",
5
5
  "keywords": [
6
6
  "mcp",