@modelprofile.com/mcp-crossharness 5.3.0 → 5.5.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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@modelprofile.com/mcp-crossharness',
6
- version: '5.3.0',
6
+ version: '5.5.0',
7
7
  description: 'Connection-first MCP server for explicit OpenCode HTTP and Codex WebSocket session servers'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxvQ0FBb0M7SUFDMUMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDRGQUE0RjtDQUMxRyxDQUFBIn0=
@@ -12,6 +12,9 @@ export type TCodexAppServerTransport = {
12
12
  type: 'websocket';
13
13
  url: string;
14
14
  token?: string;
15
+ } | {
16
+ type: 'unix';
17
+ socketPath: string;
15
18
  } | {
16
19
  type: 'stdio';
17
20
  readable: plugins.stream.Readable;
@@ -43,6 +43,11 @@ export class CodexAppServerClient {
43
43
  throw new Error('Codex app-server requires an explicit ws/wss URL without credentials or fragment');
44
44
  }
45
45
  }
46
+ if (options.transport.type === 'unix' && (typeof options.transport.socketPath !== 'string'
47
+ || !options.transport.socketPath.startsWith('/')
48
+ || options.transport.socketPath.includes('\0')
49
+ || Buffer.byteLength(options.transport.socketPath, 'utf8') > 4096))
50
+ throw new Error('Codex app-server requires an absolute Unix socket path of at most 4096 bytes');
46
51
  }
47
52
  async connect() {
48
53
  if (this.started || this.state === 'closed')
@@ -50,12 +55,17 @@ export class CodexAppServerClient {
50
55
  this.started = true;
51
56
  try {
52
57
  const transport = this.options.transport;
53
- if (transport.type === 'websocket') {
54
- const socket = new plugins.WsWebSocket(transport.url, {
58
+ if (transport.type !== 'stdio') {
59
+ const socket = new plugins.WsWebSocket(transport.type === 'websocket' ? transport.url : 'ws://localhost/', {
55
60
  perMessageDeflate: false,
56
61
  followRedirects: false,
57
62
  maxPayload: this.maxMessageBytes,
58
- headers: transport.token ? { authorization: `Bearer ${transport.token}` } : {},
63
+ headers: transport.type === 'websocket' && transport.token
64
+ ? { authorization: `Bearer ${transport.token}` } : {},
65
+ ...(transport.type === 'unix' ? {
66
+ // Keep the path out of URL parsing: valid socket names may contain :, # or %.
67
+ createConnection: () => plugins.net.createConnection({ path: transport.socketPath }),
68
+ } : {}),
59
69
  });
60
70
  this.socket = socket;
61
71
  socket.on('message', (data) => this.receive(data.toString()));
@@ -160,7 +170,7 @@ export class CodexAppServerClient {
160
170
  this.finishServerRequest(id);
161
171
  this.inputBuffer = Buffer.alloc(0);
162
172
  const transport = this.options.transport;
163
- if (transport.type === 'websocket') {
173
+ if (transport.type !== 'stdio') {
164
174
  if (this.socket && this.socket.readyState !== plugins.WsWebSocket.CLOSED)
165
175
  this.socket.terminate();
166
176
  }
@@ -201,7 +211,7 @@ export class CodexAppServerClient {
201
211
  const payload = JSON.stringify(frameArg);
202
212
  const payloadBytes = Buffer.byteLength(payload, 'utf8');
203
213
  const transport = this.options.transport;
204
- const buffered = transport.type === 'websocket'
214
+ const buffered = transport.type !== 'stdio'
205
215
  ? this.socket?.bufferedAmount ?? 0 : transport.writable.writableLength;
206
216
  if (this.state === 'closed')
207
217
  throw new Error('Codex server connection is closed');
@@ -210,7 +220,7 @@ export class CodexAppServerClient {
210
220
  this.close(error.message);
211
221
  throw error;
212
222
  }
213
- if (transport.type === 'websocket') {
223
+ if (transport.type !== 'stdio') {
214
224
  if (!this.socket || this.socket.readyState !== plugins.WsWebSocket.OPEN) {
215
225
  throw new Error('Codex server WebSocket is not open');
216
226
  }
@@ -301,4 +311,4 @@ export class CodexAppServerClient {
301
311
  return new CodexAppServerRequestError(signalArg.reason instanceof Error ? signalArg.reason.message : 'operation cancelled', dispatchedArg, undefined, { cause: signalArg.reason });
302
312
  }
303
313
  }
304
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jb2RleGFwcHNlcnZlcmNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuY29kZXhhcHBzZXJ2ZXJjbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUEwQ3hDLG9GQUFvRjtBQUNwRixNQUFNLE9BQU8sMEJBQTJCLFNBQVEsS0FBSztJQUdqQztJQUNBO0lBSGxCLFlBQ0UsVUFBa0IsRUFDRixVQUFtQixFQUNuQixJQUFhLEVBQzdCLFVBQXlCO1FBRXpCLEtBQUssQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFKZCxlQUFVLEdBQVYsVUFBVSxDQUFTO1FBQ25CLFNBQUksR0FBSixJQUFJLENBQVM7UUFJN0IsSUFBSSxDQUFDLElBQUksR0FBRyw0QkFBNEIsQ0FBQztJQUMzQyxDQUFDO0NBQ0Y7QUFFRCxzR0FBc0c7QUFDdEcsTUFBTSxPQUFPLG9CQUFvQjtJQVlGO0lBWHRCLEtBQUssR0FBMEMsWUFBWSxDQUFDO0lBQzVELGFBQWEsQ0FBVTtJQUN0QixNQUFNLENBQTRDO0lBQ2xELE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDaEIsY0FBYyxHQUFHLENBQUMsQ0FBQztJQUNWLGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFBMkIsQ0FBQztJQUNyRCxjQUFjLEdBQUcsSUFBSSxHQUFHLEVBQTZDLENBQUM7SUFDdEUsZUFBZSxDQUFTO0lBQ2pDLFdBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JCLGdCQUFnQixHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBRXBELFlBQTZCLE9BQXFDO1FBQXJDLFlBQU8sR0FBUCxPQUFPLENBQThCO1FBQ2hFLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxDQUFDLGVBQWUsSUFB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
314
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jb2RleGFwcHNlcnZlcmNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuY29kZXhhcHBzZXJ2ZXJjbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUEyQ3hDLG9GQUFvRjtBQUNwRixNQUFNLE9BQU8sMEJBQTJCLFNBQVEsS0FBSztJQUdqQztJQUNBO0lBSGxCLFlBQ0UsVUFBa0IsRUFDRixVQUFtQixFQUNuQixJQUFhLEVBQzdCLFVBQXlCO1FBRXpCLEtBQUssQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFKZCxlQUFVLEdBQVYsVUFBVSxDQUFTO1FBQ25CLFNBQUksR0FBSixJQUFJLENBQVM7UUFJN0IsSUFBSSxDQUFDLElBQUksR0FBRyw0QkFBNEIsQ0FBQztJQUMzQyxDQUFDO0NBQ0Y7QUFFRCxzR0FBc0c7QUFDdEcsTUFBTSxPQUFPLG9CQUFvQjtJQVlGO0lBWHRCLEtBQUssR0FBMEMsWUFBWSxDQUFDO0lBQzVELGFBQWEsQ0FBVTtJQUN0QixNQUFNLENBQTRDO0lBQ2xELE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDaEIsY0FBYyxHQUFHLENBQUMsQ0FBQztJQUNWLGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFBMkIsQ0FBQztJQUNyRCxjQUFjLEdBQUcsSUFBSSxHQUFHLEVBQTZDLENBQUM7SUFDdEUsZUFBZSxDQUFTO0lBQ2pDLFdBQVcsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JCLGdCQUFnQixHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBRXBELFlBQTZCLE9BQXFDO1FBQXJDLFlBQU8sR0FBUCxPQUFPLENBQThCO1FBQ2hFLElBQUksQ0FBQyxlQUFlLEdBQUcsT0FBTyxDQUFDLGVBQWUsSUFB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
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Codex's `--listen unix://PATH` contract since Codex 0.156.0 (codex-rs/app-server-transport,
3
+ * `protected_socket_path`): the socket is bound in the fixed per-user directory
4
+ * `<realpath /tmp>/codex-daemon-<euid>` under the SHA-256 of PATH with its parent canonicalised,
5
+ * and PATH itself is only a symlink to it. Earlier releases bound PATH directly; that layout is
6
+ * not this contract and is refused like any other foreign entry.
7
+ */
8
+ export interface ICodexUnixSocketOptions {
9
+ /**
10
+ * Codex's per-user socket directory. Defaults to `<realpath /tmp>/codex-daemon-<euid>`, which
11
+ * Codex derives without HOME, TMPDIR or CODEX_HOME; override it only for fixtures.
12
+ */
13
+ daemonDirectory?: string;
14
+ }
15
+ /** `absent`: nothing exists at the path. `published`: Codex's own alias to a private socket. */
16
+ export type TCodexUnixSocketPublication = 'absent' | 'published';
17
+ /** Where Codex binds the socket it publishes at `socketPathArg`. The parent directory must exist. */
18
+ export declare const codexUnixSocketTarget: (socketPathArg: string, optionsArg?: ICodexUnixSocketOptions) => Promise<string>;
19
+ /**
20
+ * Reports whether Codex has published an app-server socket at `socketPathArg`. Anything present
21
+ * must be exactly Codex's own same-user link to its target, in a parent other users cannot
22
+ * rewrite (Codex's own startup condition), pointing at a same-user socket in a 0700 same-user
23
+ * directory; every other entry throws instead of being connected to.
24
+ */
25
+ export declare const observeCodexUnixSocket: (socketPathArg: string, optionsArg?: ICodexUnixSocketOptions) => Promise<TCodexUnixSocketPublication>;
@@ -0,0 +1,94 @@
1
+ import * as plugins from './plugins.js';
2
+ import * as helpers from './helpers.js';
3
+ const assertNormalizedAbsolute = (pathArg, messageArg) => {
4
+ if (typeof pathArg !== 'string' || !plugins.path.isAbsolute(pathArg) || pathArg.includes('\0')
5
+ || plugins.path.normalize(pathArg) !== pathArg) {
6
+ throw new Error(messageArg);
7
+ }
8
+ };
9
+ /**
10
+ * Codex splits PATH into parent and file name with Rust's `Path`, which drops `.` components and
11
+ * has no file name for `..`; a normalized path without a trailing separator splits identically here.
12
+ */
13
+ const assertSocketPath = (socketPathArg) => {
14
+ const message = 'Codex Unix socket path must be a normalized absolute file path';
15
+ assertNormalizedAbsolute(socketPathArg, message);
16
+ if (socketPathArg.endsWith(plugins.path.sep))
17
+ throw new Error(message);
18
+ };
19
+ /** Codex keys its directory and checks every entry by the effective uid, so this module does too. */
20
+ const effectiveUserId = () => {
21
+ const euid = process.geteuid?.();
22
+ if (euid === undefined)
23
+ throw new Error('Codex Unix socket inspection requires a POSIX effective user id');
24
+ return euid;
25
+ };
26
+ /** A malformed root is a caller error, so it throws whatever exists at the socket path. */
27
+ const assertOptions = (optionsArg) => {
28
+ if (optionsArg.daemonDirectory !== undefined) {
29
+ assertNormalizedAbsolute(optionsArg.daemonDirectory, 'Codex daemon socket directory must be a normalized absolute path');
30
+ }
31
+ };
32
+ const daemonDirectoryFor = async (optionsArg, euidArg) => {
33
+ if (optionsArg.daemonDirectory !== undefined)
34
+ return optionsArg.daemonDirectory;
35
+ return plugins.path.join(await plugins.fs.promises.realpath('/tmp'), `codex-daemon-${euidArg}`);
36
+ };
37
+ const isMissing = (errorArg) => helpers.isRecord(errorArg) && errorArg.code === 'ENOENT';
38
+ /** Where Codex binds the socket it publishes at `socketPathArg`. The parent directory must exist. */
39
+ export const codexUnixSocketTarget = async (socketPathArg, optionsArg = {}) => {
40
+ assertSocketPath(socketPathArg);
41
+ assertOptions(optionsArg);
42
+ const euid = effectiveUserId();
43
+ const directory = await daemonDirectoryFor(optionsArg, euid);
44
+ const canonical = plugins.path.join(await plugins.fs.promises.realpath(plugins.path.dirname(socketPathArg)), plugins.path.basename(socketPathArg));
45
+ return plugins.path.join(directory, plugins.crypto.createHash('sha256').update(canonical).digest('hex'));
46
+ };
47
+ /**
48
+ * Reports whether Codex has published an app-server socket at `socketPathArg`. Anything present
49
+ * must be exactly Codex's own same-user link to its target, in a parent other users cannot
50
+ * rewrite (Codex's own startup condition), pointing at a same-user socket in a 0700 same-user
51
+ * directory; every other entry throws instead of being connected to.
52
+ */
53
+ export const observeCodexUnixSocket = async (socketPathArg, optionsArg = {}) => {
54
+ assertSocketPath(socketPathArg);
55
+ assertOptions(optionsArg);
56
+ const euid = effectiveUserId();
57
+ let alias;
58
+ try {
59
+ alias = await plugins.fs.promises.lstat(socketPathArg);
60
+ }
61
+ catch (error) {
62
+ if (isMissing(error))
63
+ return 'absent';
64
+ throw error;
65
+ }
66
+ const target = await codexUnixSocketTarget(socketPathArg, optionsArg);
67
+ if (!alias.isSymbolicLink() || alias.uid !== euid || await plugins.fs.promises.readlink(socketPathArg) !== target) {
68
+ throw new Error('Codex Unix socket path is not the alias Codex publishes');
69
+ }
70
+ const parent = await plugins.fs.promises.stat(plugins.path.dirname(socketPathArg));
71
+ if (!parent.isDirectory() || (parent.uid !== 0 && parent.uid !== euid)
72
+ || ((parent.mode & 0o022) !== 0 && (parent.mode & 0o1000) === 0)) {
73
+ throw new Error('Codex Unix socket parent directory lets other users replace its entries');
74
+ }
75
+ let directory;
76
+ let socket;
77
+ try {
78
+ directory = await plugins.fs.promises.lstat(plugins.path.dirname(target));
79
+ socket = await plugins.fs.promises.lstat(target);
80
+ }
81
+ catch (error) {
82
+ if (isMissing(error))
83
+ throw new Error('Codex Unix socket alias has no socket behind it');
84
+ throw error;
85
+ }
86
+ if (!directory.isDirectory() || directory.uid !== euid || (directory.mode & 0o777) !== 0o700) {
87
+ throw new Error('Codex Unix socket directory is not private to the current user');
88
+ }
89
+ if (!socket.isSocket() || socket.uid !== euid) {
90
+ throw new Error('Codex Unix socket is not a socket owned by the current user');
91
+ }
92
+ return 'published';
93
+ };
94
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb25zLmNvZGV4dW5peHNvY2tldC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2Z1bmN0aW9ucy5jb2RleHVuaXhzb2NrZXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFvQnhDLE1BQU0sd0JBQXdCLEdBQUcsQ0FBQyxPQUFlLEVBQUUsVUFBa0IsRUFBUSxFQUFFO0lBQzdFLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7V0FDekYsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDakQsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM5QixDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBRUY7OztHQUdHO0FBQ0gsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLGFBQXFCLEVBQVEsRUFBRTtJQUN2RCxNQUFNLE9BQU8sR0FBRyxnRUFBZ0UsQ0FBQztJQUNqRix3QkFBd0IsQ0FBQyxhQUFhLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDakQsSUFBSSxhQUFhLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUN6RSxDQUFDLENBQUM7QUFFRixxR0FBcUc7QUFDckcsTUFBTSxlQUFlLEdBQUcsR0FBVyxFQUFFO0lBQ25DLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO0lBQ2pDLElBQUksSUFBSSxLQUFLLFNBQVM7UUFBRSxNQUFNLElBQUksS0FB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
@@ -1,5 +1,6 @@
1
1
  export * from './interfaces.js';
2
2
  export * from './classes.codexappserverclient.js';
3
+ export * from './functions.codexunixsocket.js';
3
4
  export * from './classes.connectionregistry.js';
4
5
  export * from './classes.dispatchregistry.js';
5
6
  export * from './classes.mcptoolregistrar.js';
package/dist_ts/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './interfaces.js';
2
2
  export * from './classes.codexappserverclient.js';
3
+ export * from './functions.codexunixsocket.js';
3
4
  export * from './classes.connectionregistry.js';
4
5
  export * from './classes.dispatchregistry.js';
5
6
  export * from './classes.mcptoolregistrar.js';
@@ -8,4 +9,4 @@ import { CrossHarnessMcpServer } from './classes.mcpserver.js';
8
9
  export const runCli = async () => {
9
10
  await new CrossHarnessMcpServer().start();
10
11
  };
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsbUNBQW1DLENBQUM7QUFDbEQsY0FBYyxpQ0FBaUMsQ0FBQztBQUNoRCxjQUFjLCtCQUErQixDQUFDO0FBQzlDLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyx3QkFBd0IsQ0FBQztBQUV2QyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUUvRCxNQUFNLENBQUMsTUFBTSxNQUFNLEdBQUcsS0FBSyxJQUFtQixFQUFFO0lBQzlDLE1BQU0sSUFBSSxxQkFBcUIsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQzVDLENBQUMsQ0FBQyJ9
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsbUNBQW1DLENBQUM7QUFDbEQsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLGlDQUFpQyxDQUFDO0FBQ2hELGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYywrQkFBK0IsQ0FBQztBQUM5QyxjQUFjLHdCQUF3QixDQUFDO0FBRXZDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRS9ELE1BQU0sQ0FBQyxNQUFNLE1BQU0sR0FBRyxLQUFLLElBQW1CLEVBQUU7SUFDOUMsTUFBTSxJQUFJLHFCQUFxQixFQUFFLENBQUMsS0FBSyxFQUFFLENBQUM7QUFDNUMsQ0FBQyxDQUFDIn0=
@@ -1,8 +1,11 @@
1
1
  import * as crypto from 'node:crypto';
2
+ import * as fs from 'node:fs';
2
3
  import * as http from 'node:http';
4
+ import * as net from 'node:net';
5
+ import * as path from 'node:path';
3
6
  import * as stream from 'node:stream';
4
7
  import type { AddressInfo } from 'node:net';
5
- export { crypto, http, stream };
8
+ export { crypto, fs, http, net, path, stream };
6
9
  export type { AddressInfo };
7
10
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
11
  import type { RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
@@ -1,8 +1,11 @@
1
1
  // Node native modules
2
2
  import * as crypto from 'node:crypto';
3
+ import * as fs from 'node:fs';
3
4
  import * as http from 'node:http';
5
+ import * as net from 'node:net';
6
+ import * as path from 'node:path';
4
7
  import * as stream from 'node:stream';
5
- export { crypto, http, stream };
8
+ export { crypto, fs, http, net, path, stream };
6
9
  // Third-party modules
7
10
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
11
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
@@ -11,4 +14,4 @@ import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
11
14
  import { WebSocket as WsWebSocket, WebSocketServer } from 'ws';
12
15
  import { z } from 'zod';
13
16
  export { InMemoryTransport, McpClient, McpServer, StdioServerTransport, WebSocketServer, WsWebSocket, z, };
14
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsc0JBQXNCO0FBQ3RCLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBR3RDLE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBR2hDLHNCQUFzQjtBQUN0QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFFcEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFDakYsT0FBTyxFQUFFLE1BQU0sSUFBSSxTQUFTLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUNoRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUUxRSxPQUFPLEVBQUUsU0FBUyxJQUFJLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFFL0QsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4QixPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxTQUFTLEVBQ1Qsb0JBQW9CLEVBQ3BCLGVBQWUsRUFDZixXQUFXLEVBQ1gsQ0FBQyxHQUNGLENBQUMifQ==
17
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsc0JBQXNCO0FBQ3RCLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBR3RDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBRy9DLHNCQUFzQjtBQUN0QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFFcEUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkNBQTJDLENBQUM7QUFDakYsT0FBTyxFQUFFLE1BQU0sSUFBSSxTQUFTLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUNoRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUUxRSxPQUFPLEVBQUUsU0FBUyxJQUFJLFdBQVcsRUFBRSxlQUFlLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFFL0QsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4QixPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxTQUFTLEVBQ1Qsb0JBQW9CLEVBQ3BCLGVBQWUsRUFDZixXQUFXLEVBQ1gsQ0FBQyxHQUNGLENBQUMifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelprofile.com/mcp-crossharness",
3
- "version": "5.3.0",
3
+ "version": "5.5.0",
4
4
  "private": false,
5
5
  "description": "Connection-first MCP server for explicit OpenCode HTTP and Codex WebSocket session servers",
6
6
  "main": "dist_ts/index.js",
@@ -23,10 +23,10 @@
23
23
  "mcp-crossharness": "./cli.js"
24
24
  },
25
25
  "devDependencies": {
26
- "@git.zone/tsbuild": "^4.4.2",
27
- "@git.zone/tsrun": "^2.0.6",
28
- "@git.zone/tstest": "^4.0.0",
29
- "@types/node": "^26.4.1",
26
+ "@git.zone/tsbuild": "^5.0.0",
27
+ "@git.zone/tsrun": "^3.0.0",
28
+ "@git.zone/tstest": "^6.2.1",
29
+ "@types/node": "^26.6.1",
30
30
  "@types/ws": "^8.18.1"
31
31
  },
32
32
  "dependencies": {
package/readme.md CHANGED
@@ -143,7 +143,7 @@ Register the `mcp-crossharness` binary as a stdio MCP server in your client.
143
143
  ### Native Codex app-server client
144
144
 
145
145
  `CodexAppServerClient` exposes the underlying app-server protocol independently of the MCP
146
- chat tools. It accepts an explicit WebSocket endpoint or caller-owned JSONL stdio streams;
146
+ chat tools. It accepts an explicit WebSocket endpoint, a Unix socket, or caller-owned JSONL stdio streams;
147
147
  it never discovers or spawns a server. The embedding application owns process lifecycle,
148
148
  session authorization, history projection, and human approval policy.
149
149
 
@@ -166,6 +166,14 @@ client.close();
166
166
  ```
167
167
 
168
168
  For WebSocket transport use `{ type: 'websocket', url: approvedServerUrl, token: bearerToken }`.
169
+
170
+ To join an existing local Codex daemon, use
171
+ `{ type: 'unix', socketPath: absoluteSocketPath }`. This performs a WebSocket handshake
172
+ over the exact Unix socket, with the same deadlines, message limits and request lifecycle
173
+ as the network transport. The client does not discover, start, restart or stop the daemon;
174
+ closing it closes only its own connection. Socket paths remain filesystem paths, including
175
+ spaces and URL punctuation. Callers choose a trusted socket and own discovery and process
176
+ policy. Codex's `app-server proxy` forwards raw socket bytes; its stdio is not JSONL.
169
177
  The caller must authorize the destination before supplying credentials. The client follows no
170
178
  redirects and reads no credential environment variables. MCP tools retain their existing
171
179
  allowlist and credential policy.
@@ -189,6 +197,56 @@ client never grants or automatically declines a permission. `close()` ends the s
189
197
  stdio streams but never kills a subprocess. The existing MCP Codex adapter delegates to
190
198
  this client and retains its conservative automatic rejection policy.
191
199
 
200
+ ### Codex Unix socket alias
201
+
202
+ Since Codex 0.156.0, `codex app-server --listen unix://PATH` does not bind PATH. Codex binds
203
+ the socket in its fixed per-user directory, `<realpath /tmp>/codex-daemon-<euid>` (mode 0700),
204
+ under the SHA-256 of PATH with its parent directory canonicalised, and publishes PATH as a
205
+ symlink to it. Its shared local daemon socket, `$CODEX_HOME/app-server-control/app-server-control.sock`,
206
+ is published the same way. The unix transport connects through that link like any other
207
+ path; these two functions let a caller check, before connecting, that the entry really is
208
+ Codex's own:
209
+
210
+ ```typescript
211
+ import { CodexAppServerClient, codexUnixSocketTarget, observeCodexUnixSocket } from '@modelprofile.com/mcp-crossharness';
212
+
213
+ const target = await codexUnixSocketTarget(socketPath); // where Codex binds PATH
214
+ if (await observeCodexUnixSocket(socketPath) === 'published') {
215
+ const client = new CodexAppServerClient({
216
+ transport: { type: 'unix', socketPath },
217
+ clientInfo: { name: 'my-app', title: 'My App', version: '1.0.0' },
218
+ });
219
+ await client.connect();
220
+ }
221
+ ```
222
+
223
+ `observeCodexUnixSocket(socketPath)` returns `'absent'` when nothing exists at the path and
224
+ `'published'` only when the path is a link owned by the effective user whose text is exactly
225
+ the derived target, in a parent directory other users cannot rewrite (owned by the user or
226
+ root, and not group- or world-writable unless sticky, which is Codex's own startup condition),
227
+ pointing at a socket owned by the effective user in a directory owned by that user with mode
228
+ 0700. Every other entry throws, and nothing is created, removed or connected to. Ownership is
229
+ compared with the effective uid because Codex keys the directory by and checks against it.
230
+ A socket bound directly at the path, as Codex 0.155 and earlier did, is not this contract
231
+ and is refused like any other foreign entry.
232
+
233
+ Both functions take an optional `{ daemonDirectory }` that replaces the per-user directory for
234
+ fixtures; `codexUnixSocketTarget` needs the socket's parent directory to exist. They throw
235
+ plain `Error`s with these exact messages:
236
+
237
+ | Message | Cause |
238
+ | --- | --- |
239
+ | `Codex Unix socket path must be a normalized absolute file path` | relative, non-normalized, trailing-separator or NUL-containing path |
240
+ | `Codex daemon socket directory must be a normalized absolute path` | invalid `daemonDirectory` |
241
+ | `Codex Unix socket inspection requires a POSIX effective user id` | no `process.geteuid` (Windows) |
242
+ | `Codex Unix socket path is not the alias Codex publishes` | a regular file, a direct socket, another user's link, or a link to any other target |
243
+ | `Codex Unix socket parent directory lets other users replace its entries` | the path's parent is not safe for a published alias |
244
+ | `Codex Unix socket alias has no socket behind it` | Codex's own link whose target is gone (a stale publication) |
245
+ | `Codex Unix socket directory is not private to the current user` | the per-user directory is not the user's own 0700 directory |
246
+ | `Codex Unix socket is not a socket owned by the current user` | the target is not a socket, or is another user's |
247
+
248
+ Filesystem errors other than a missing path propagate unchanged.
249
+
192
250
  ### Composable tool registration
193
251
 
194
252
  `CrossHarnessMcpToolRegistrar` registers the same nine Crossharness tools used by the standalone
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@modelprofile.com/mcp-crossharness',
6
- version: '5.3.0',
6
+ version: '5.5.0',
7
7
  description: 'Connection-first MCP server for explicit OpenCode HTTP and Codex WebSocket session servers'
8
8
  }
@@ -15,6 +15,7 @@ export interface ICodexAppServerRequest extends ICodexAppServerNotification {
15
15
 
16
16
  export type TCodexAppServerTransport =
17
17
  | { type: 'websocket'; url: string; token?: string }
18
+ | { type: 'unix'; socketPath: string }
18
19
  | { type: 'stdio'; readable: plugins.stream.Readable; writable: plugins.stream.Writable };
19
20
 
20
21
  export interface ICodexAppServerClientOptions {
@@ -85,6 +86,12 @@ export class CodexAppServerClient {
85
86
  throw new Error('Codex app-server requires an explicit ws/wss URL without credentials or fragment');
86
87
  }
87
88
  }
89
+ if (options.transport.type === 'unix' && (
90
+ typeof options.transport.socketPath !== 'string'
91
+ || !options.transport.socketPath.startsWith('/')
92
+ || options.transport.socketPath.includes('\0')
93
+ || Buffer.byteLength(options.transport.socketPath, 'utf8') > 4096
94
+ )) throw new Error('Codex app-server requires an absolute Unix socket path of at most 4096 bytes');
88
95
  }
89
96
 
90
97
  public async connect(): Promise<void> {
@@ -92,12 +99,17 @@ export class CodexAppServerClient {
92
99
  this.started = true;
93
100
  try {
94
101
  const transport = this.options.transport;
95
- if (transport.type === 'websocket') {
96
- const socket = new plugins.WsWebSocket(transport.url, {
102
+ if (transport.type !== 'stdio') {
103
+ const socket = new plugins.WsWebSocket(transport.type === 'websocket' ? transport.url : 'ws://localhost/', {
97
104
  perMessageDeflate: false,
98
105
  followRedirects: false,
99
106
  maxPayload: this.maxMessageBytes,
100
- headers: transport.token ? { authorization: `Bearer ${transport.token}` } : {},
107
+ headers: transport.type === 'websocket' && transport.token
108
+ ? { authorization: `Bearer ${transport.token}` } : {},
109
+ ...(transport.type === 'unix' ? {
110
+ // Keep the path out of URL parsing: valid socket names may contain :, # or %.
111
+ createConnection: () => plugins.net.createConnection({ path: transport.socketPath }),
112
+ } : {}),
101
113
  });
102
114
  this.socket = socket;
103
115
  socket.on('message', (data) => this.receive(data.toString()));
@@ -211,7 +223,7 @@ export class CodexAppServerClient {
211
223
  for (const id of this.serverRequests.keys()) this.finishServerRequest(id);
212
224
  this.inputBuffer = Buffer.alloc(0);
213
225
  const transport = this.options.transport;
214
- if (transport.type === 'websocket') {
226
+ if (transport.type !== 'stdio') {
215
227
  if (this.socket && this.socket.readyState !== plugins.WsWebSocket.CLOSED) this.socket.terminate();
216
228
  } else {
217
229
  transport.readable.off('data', this.handleData);
@@ -250,7 +262,7 @@ export class CodexAppServerClient {
250
262
  const payload = JSON.stringify(frameArg);
251
263
  const payloadBytes = Buffer.byteLength(payload, 'utf8');
252
264
  const transport = this.options.transport;
253
- const buffered = transport.type === 'websocket'
265
+ const buffered = transport.type !== 'stdio'
254
266
  ? this.socket?.bufferedAmount ?? 0 : transport.writable.writableLength;
255
267
  if (this.state === 'closed') throw new Error('Codex server connection is closed');
256
268
  if (buffered + payloadBytes + 1 > this.maxBufferedBytes) {
@@ -258,7 +270,7 @@ export class CodexAppServerClient {
258
270
  this.close(error.message);
259
271
  throw error;
260
272
  }
261
- if (transport.type === 'websocket') {
273
+ if (transport.type !== 'stdio') {
262
274
  if (!this.socket || this.socket.readyState !== plugins.WsWebSocket.OPEN) {
263
275
  throw new Error('Codex server WebSocket is not open');
264
276
  }
@@ -0,0 +1,119 @@
1
+ import * as plugins from './plugins.js';
2
+ import * as helpers from './helpers.js';
3
+
4
+ /**
5
+ * Codex's `--listen unix://PATH` contract since Codex 0.156.0 (codex-rs/app-server-transport,
6
+ * `protected_socket_path`): the socket is bound in the fixed per-user directory
7
+ * `<realpath /tmp>/codex-daemon-<euid>` under the SHA-256 of PATH with its parent canonicalised,
8
+ * and PATH itself is only a symlink to it. Earlier releases bound PATH directly; that layout is
9
+ * not this contract and is refused like any other foreign entry.
10
+ */
11
+ export interface ICodexUnixSocketOptions {
12
+ /**
13
+ * Codex's per-user socket directory. Defaults to `<realpath /tmp>/codex-daemon-<euid>`, which
14
+ * Codex derives without HOME, TMPDIR or CODEX_HOME; override it only for fixtures.
15
+ */
16
+ daemonDirectory?: string;
17
+ }
18
+
19
+ /** `absent`: nothing exists at the path. `published`: Codex's own alias to a private socket. */
20
+ export type TCodexUnixSocketPublication = 'absent' | 'published';
21
+
22
+ const assertNormalizedAbsolute = (pathArg: string, messageArg: string): void => {
23
+ if (typeof pathArg !== 'string' || !plugins.path.isAbsolute(pathArg) || pathArg.includes('\0')
24
+ || plugins.path.normalize(pathArg) !== pathArg) {
25
+ throw new Error(messageArg);
26
+ }
27
+ };
28
+
29
+ /**
30
+ * Codex splits PATH into parent and file name with Rust's `Path`, which drops `.` components and
31
+ * has no file name for `..`; a normalized path without a trailing separator splits identically here.
32
+ */
33
+ const assertSocketPath = (socketPathArg: string): void => {
34
+ const message = 'Codex Unix socket path must be a normalized absolute file path';
35
+ assertNormalizedAbsolute(socketPathArg, message);
36
+ if (socketPathArg.endsWith(plugins.path.sep)) throw new Error(message);
37
+ };
38
+
39
+ /** Codex keys its directory and checks every entry by the effective uid, so this module does too. */
40
+ const effectiveUserId = (): number => {
41
+ const euid = process.geteuid?.();
42
+ if (euid === undefined) throw new Error('Codex Unix socket inspection requires a POSIX effective user id');
43
+ return euid;
44
+ };
45
+
46
+ /** A malformed root is a caller error, so it throws whatever exists at the socket path. */
47
+ const assertOptions = (optionsArg: ICodexUnixSocketOptions): void => {
48
+ if (optionsArg.daemonDirectory !== undefined) {
49
+ assertNormalizedAbsolute(optionsArg.daemonDirectory, 'Codex daemon socket directory must be a normalized absolute path');
50
+ }
51
+ };
52
+
53
+ const daemonDirectoryFor = async (optionsArg: ICodexUnixSocketOptions, euidArg: number): Promise<string> => {
54
+ if (optionsArg.daemonDirectory !== undefined) return optionsArg.daemonDirectory;
55
+ return plugins.path.join(await plugins.fs.promises.realpath('/tmp'), `codex-daemon-${euidArg}`);
56
+ };
57
+
58
+ const isMissing = (errorArg: unknown): boolean => helpers.isRecord(errorArg) && errorArg.code === 'ENOENT';
59
+
60
+ /** Where Codex binds the socket it publishes at `socketPathArg`. The parent directory must exist. */
61
+ export const codexUnixSocketTarget = async (
62
+ socketPathArg: string,
63
+ optionsArg: ICodexUnixSocketOptions = {},
64
+ ): Promise<string> => {
65
+ assertSocketPath(socketPathArg);
66
+ assertOptions(optionsArg);
67
+ const euid = effectiveUserId();
68
+ const directory = await daemonDirectoryFor(optionsArg, euid);
69
+ const canonical = plugins.path.join(await plugins.fs.promises.realpath(plugins.path.dirname(socketPathArg)),
70
+ plugins.path.basename(socketPathArg));
71
+ return plugins.path.join(directory, plugins.crypto.createHash('sha256').update(canonical).digest('hex'));
72
+ };
73
+
74
+ /**
75
+ * Reports whether Codex has published an app-server socket at `socketPathArg`. Anything present
76
+ * must be exactly Codex's own same-user link to its target, in a parent other users cannot
77
+ * rewrite (Codex's own startup condition), pointing at a same-user socket in a 0700 same-user
78
+ * directory; every other entry throws instead of being connected to.
79
+ */
80
+ export const observeCodexUnixSocket = async (
81
+ socketPathArg: string,
82
+ optionsArg: ICodexUnixSocketOptions = {},
83
+ ): Promise<TCodexUnixSocketPublication> => {
84
+ assertSocketPath(socketPathArg);
85
+ assertOptions(optionsArg);
86
+ const euid = effectiveUserId();
87
+ let alias: plugins.fs.Stats;
88
+ try {
89
+ alias = await plugins.fs.promises.lstat(socketPathArg);
90
+ } catch (error) {
91
+ if (isMissing(error)) return 'absent';
92
+ throw error;
93
+ }
94
+ const target = await codexUnixSocketTarget(socketPathArg, optionsArg);
95
+ if (!alias.isSymbolicLink() || alias.uid !== euid || await plugins.fs.promises.readlink(socketPathArg) !== target) {
96
+ throw new Error('Codex Unix socket path is not the alias Codex publishes');
97
+ }
98
+ const parent = await plugins.fs.promises.stat(plugins.path.dirname(socketPathArg));
99
+ if (!parent.isDirectory() || (parent.uid !== 0 && parent.uid !== euid)
100
+ || ((parent.mode & 0o022) !== 0 && (parent.mode & 0o1000) === 0)) {
101
+ throw new Error('Codex Unix socket parent directory lets other users replace its entries');
102
+ }
103
+ let directory: plugins.fs.Stats;
104
+ let socket: plugins.fs.Stats;
105
+ try {
106
+ directory = await plugins.fs.promises.lstat(plugins.path.dirname(target));
107
+ socket = await plugins.fs.promises.lstat(target);
108
+ } catch (error) {
109
+ if (isMissing(error)) throw new Error('Codex Unix socket alias has no socket behind it');
110
+ throw error;
111
+ }
112
+ if (!directory.isDirectory() || directory.uid !== euid || (directory.mode & 0o777) !== 0o700) {
113
+ throw new Error('Codex Unix socket directory is not private to the current user');
114
+ }
115
+ if (!socket.isSocket() || socket.uid !== euid) {
116
+ throw new Error('Codex Unix socket is not a socket owned by the current user');
117
+ }
118
+ return 'published';
119
+ };
package/ts/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './interfaces.js';
2
2
  export * from './classes.codexappserverclient.js';
3
+ export * from './functions.codexunixsocket.js';
3
4
  export * from './classes.connectionregistry.js';
4
5
  export * from './classes.dispatchregistry.js';
5
6
  export * from './classes.mcptoolregistrar.js';
package/ts/plugins.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  // Node native modules
2
2
  import * as crypto from 'node:crypto';
3
+ import * as fs from 'node:fs';
3
4
  import * as http from 'node:http';
5
+ import * as net from 'node:net';
6
+ import * as path from 'node:path';
4
7
  import * as stream from 'node:stream';
5
8
  import type { AddressInfo } from 'node:net';
6
9
 
7
- export { crypto, http, stream };
10
+ export { crypto, fs, http, net, path, stream };
8
11
  export type { AddressInfo };
9
12
 
10
13
  // Third-party modules
package/readme.hints.md DELETED
@@ -1,52 +0,0 @@
1
- # readme.hints.md
2
-
3
- Implementation findings for mcp-crossharness.
4
-
5
- ## Server-only architecture
6
-
7
- - Every harness operation after connection setup is scoped to an opaque connection established from an explicit server origin and remote absolute directory; `list_connections` remains global.
8
- - Duplicate harness/origin/directory bindings are rejected and each registry is capped at 32 connections.
9
- - `CROSSHARNESS_ALLOWED_SERVER_URLS` is an exact-origin allowlist. Credentials are fixed environment variables, never tool inputs.
10
- - URLs reject user info, query strings, fragments, and non-root paths. OpenCode fetch calls use `redirect: 'error'`.
11
- - No production source reads harness stores, invokes harness CLIs, starts or stops processes, or discovers endpoints.
12
-
13
- ## OpenCode server API
14
-
15
- Verified against OpenCode 1.18.13 docs, source, and generated SDK.
16
-
17
- - Health: `GET /global/health`.
18
- - Session list: `GET /session?directory=...&scope=project&roots=true&limit=...`.
19
- - Session ownership: `GET /session/:id?directory=...`, then verify returned `directory` exactly.
20
- - Transcript: `GET /session/:id/message?directory=...&limit=...`.
21
- - Send: `POST /session/:id/message?directory=...` with a generated `messageID` and text part.
22
- - OpenCode owns queuing. Crossharness intentionally does not serialize HTTP sends, subscribe to permission events, or issue session-wide aborts.
23
- - Aborting a fetch does not prove that a queued/running server turn stopped, so timeout errors state the ambiguity and no retry occurs.
24
- - Successful JSON response bodies are capped at 16 MiB; error bodies are capped at 64 KiB and only the first 2,000 characters are surfaced.
25
-
26
- ## Codex app-server API
27
-
28
- Verified against Codex 0.146.0 using `codex app-server generate-ts` and official app-server documentation.
29
-
30
- - Explicit transports are `ws://` and `wss://`; one initialized WebSocket is owned per Crossharness connection.
31
- - Flow: `initialize` -> `initialized`; `thread/list`; `thread/read`; `thread/resume`; `turn/start`; correlated notifications; optional `turn/interrupt` on timeout.
32
- - `thread/list` supports exact `cwd` filtering. `thread/read` results are still verified against the connection directory before reading or sending.
33
- - Request responses are correlated by JSON-RPC id. Turn events are correlated by `threadId` and `turnId`; events can arrive before `turn/start` resolves, so one unbound turn per thread may claim the early id.
34
- - Sends to one thread are sequenced; different threads remain concurrent.
35
- - Codex send queues are bounded globally and per thread, outbound WebSocket buffering is capped at 4 MiB, and a send's timeout includes time spent waiting in the same-thread queue.
36
- - Turn output is bounded by text size and delta count, including empty streaming deltas.
37
- - Foreground MCP cancellation aborts the operation-scoped OpenCode request or safely interrupts the correlated Codex turn; asynchronous dispatches remain independent after acceptance.
38
- - A timed-out send keeps its thread queue locked until `turn/interrupt` is acknowledged and `turn/completed` reports terminal state. Missing turn correlation or incomplete interruption closes the connection fail-closed.
39
- - Socket close rejects all pending requests and turns. Disconnect removes the connection before closing so no new work can enter.
40
- - Stdio EOF closes the MCP transport and every active or handshaking connection.
41
- - Server requests are never ignored: command/file approvals decline, tool input returns empty answers, MCP elicitation declines, permission-profile requests grant no extra permissions for the turn, legacy approvals abort, and unknown requests receive `-32601`.
42
-
43
- ## Claude Code
44
-
45
- Claude Code 2.1.219 and the current Agent SDK expose local CLI/library interfaces, not a URL-addressable session server. `connect_harness` rejects `claudecode` until such a server exists.
46
-
47
- ## Testing
48
-
49
- - HTTP fixtures cover required Basic auth, allowlisting, redirect rejection, directory ownership, concurrent OpenCode sends, and disconnect state.
50
- - WebSocket fixtures cover initialization, list/read/send, interleaved turns, bounded deltas and send buffering, safe server-request responses, timeout interruption, directory ownership, and disconnect failure propagation.
51
- - Registry fixtures cover pending-connect shutdown and bounded dispatch admission before send invocation.
52
- - Timeout fixtures cover OpenCode validation, Codex same-thread queueing, interruption completion, malformed terminal events, and stdio EOF cleanup.