@modelprofile.com/mcp-crossharness 5.0.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/.smartconfig.json +34 -0
- package/cli.js +4 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.connection.codex.d.ts +66 -0
- package/dist_ts/classes.connection.codex.js +941 -0
- package/dist_ts/classes.connection.opencode.d.ts +34 -0
- package/dist_ts/classes.connection.opencode.js +365 -0
- package/dist_ts/classes.connectionregistry.d.ts +32 -0
- package/dist_ts/classes.connectionregistry.js +246 -0
- package/dist_ts/classes.dispatchregistry.d.ts +39 -0
- package/dist_ts/classes.dispatchregistry.js +177 -0
- package/dist_ts/classes.mcpserver.d.ts +21 -0
- package/dist_ts/classes.mcpserver.js +276 -0
- package/dist_ts/helpers.d.ts +4 -0
- package/dist_ts/helpers.js +17 -0
- package/dist_ts/index.d.ts +5 -0
- package/dist_ts/index.js +9 -0
- package/dist_ts/interfaces.d.ts +57 -0
- package/dist_ts/interfaces.js +2 -0
- package/dist_ts/plugins.d.ts +17 -0
- package/dist_ts/plugins.js +14 -0
- package/license.md +21 -0
- package/package.json +51 -0
- package/readme.hints.md +52 -0
- package/readme.md +204 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.connection.codex.ts +1120 -0
- package/ts/classes.connection.opencode.ts +443 -0
- package/ts/classes.connectionregistry.ts +309 -0
- package/ts/classes.dispatchregistry.ts +216 -0
- package/ts/classes.mcpserver.ts +363 -0
- package/ts/helpers.ts +20 -0
- package/ts/index.ts +10 -0
- package/ts/interfaces.ts +71 -0
- package/ts/plugins.ts +30 -0
package/readme.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# @modelprofile.com/mcp-crossharness
|
|
2
|
+
|
|
3
|
+
Connection-first MCP server for interacting with AI coding harness sessions through their explicit web-server APIs.
|
|
4
|
+
|
|
5
|
+
## Issue Reporting and Security
|
|
6
|
+
|
|
7
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
8
|
+
|
|
9
|
+
## Transport Contract
|
|
10
|
+
|
|
11
|
+
Crossharness only talks to explicitly connected harness web servers:
|
|
12
|
+
|
|
13
|
+
| Harness | Server transport | Support |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| OpenCode | `http://` or `https://` | list, read, send, health |
|
|
16
|
+
| Codex | `ws://` or `wss://` app-server | list, read, send, health |
|
|
17
|
+
| Claude Code | none | rejected at connection time |
|
|
18
|
+
|
|
19
|
+
There is no local session-store access, CLI invocation, process spawn, server discovery, auto-start, restart, or fallback. If a connection or request fails, the operation fails.
|
|
20
|
+
|
|
21
|
+
Claude Code 2.1.219 does not expose a URL-addressable session server. Its CLI and Agent SDK are local process/library interfaces, so it cannot participate in this server-only contract yet.
|
|
22
|
+
|
|
23
|
+
## Connection Flow
|
|
24
|
+
|
|
25
|
+
Harness operations start with `connect_harness`:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
connect_harness {
|
|
29
|
+
harness: "opencode",
|
|
30
|
+
serverUrl: "http://127.0.0.1:4096",
|
|
31
|
+
directory: "/absolute/path/on/server"
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The result contains an opaque `connectionId`. Connection-scoped calls must reference it:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
list_connections {}
|
|
39
|
+
list_chats { connectionId: "c-...", limit: 10 }
|
|
40
|
+
read_chat { connectionId: "c-...", chatId: "ses_..." }
|
|
41
|
+
send_message { connectionId: "c-...", chatId: "ses_...", message: "..." }
|
|
42
|
+
send_message_async { connectionId: "c-...", chatId: "ses_...", message: "..." }
|
|
43
|
+
check_reply { connectionId: "c-...", dispatchId: "d-..." }
|
|
44
|
+
connection_status { connectionId: "c-..." }
|
|
45
|
+
disconnect_harness { connectionId: "c-..." }
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Connections and asynchronous dispatches live in the MCP process and do not survive a restart.
|
|
49
|
+
|
|
50
|
+
If `disconnect_harness` cannot close the connection, it returns an error and retains that
|
|
51
|
+
connection ID for a retry. Calling `disconnect_harness` again with the same ID retries cleanup.
|
|
52
|
+
|
|
53
|
+
`send_message` defaults to a 300-second timeout and `send_message_async` to 900 seconds; both accept 1-3,600 seconds. `check_reply.waitSeconds` accepts 0-60 seconds. The send timeout covers connection-scoped validation, queueing, and the harness request. Codex timeout recovery can then take up to 3 seconds for interrupt acknowledgment and 3 seconds for terminal completion.
|
|
54
|
+
|
|
55
|
+
Canceling a foreground `send_message` aborts its OpenCode request or safely interrupts its correlated Codex turn. Canceling `check_reply` stops only that wait. A `send_message_async` dispatch remains independent after its `dispatchId` is returned.
|
|
56
|
+
|
|
57
|
+
The in-memory dispatch registry retains at most 100 records. Settled records expire after two hours and may be evicted earlier to admit new work; if all 100 records are active, a new asynchronous send is rejected before delivery starts.
|
|
58
|
+
|
|
59
|
+
## Trusted Origins
|
|
60
|
+
|
|
61
|
+
Agents must not be allowed to send harness credentials to arbitrary URLs. Configure exact approved origins before starting Crossharness:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
export CROSSHARNESS_ALLOWED_SERVER_URLS="http://127.0.0.1:4096/,ws://127.0.0.1:4500/"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`connect_harness` rejects origins not in this comma-separated allowlist. URLs containing user info, query parameters, fragments, or non-root paths are also rejected. HTTP redirects are never followed. At most one connection may bind a given harness, origin, and directory in one MCP process; the registry accepts up to 32 connections.
|
|
68
|
+
|
|
69
|
+
The standalone MCP server reads credentials from the harnesses' fixed environment variables. They are never accepted as tool arguments or printed:
|
|
70
|
+
|
|
71
|
+
- OpenCode: required `OPENCODE_SERVER_PASSWORD` and optional `OPENCODE_SERVER_USERNAME`
|
|
72
|
+
- Codex: `CODEX_REMOTE_TOKEN`
|
|
73
|
+
|
|
74
|
+
For remote servers, use TLS: `https://` for OpenCode and `wss://` for Codex.
|
|
75
|
+
|
|
76
|
+
## OpenCode
|
|
77
|
+
|
|
78
|
+
Start an OpenCode server on a fixed URL:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
OPENCODE_SERVER_PASSWORD="..." opencode serve --hostname 127.0.0.1 --port 4096
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Crossharness uses only the official HTTP API:
|
|
85
|
+
|
|
86
|
+
- `GET /global/health`
|
|
87
|
+
- `GET /session`
|
|
88
|
+
- `GET /session/:id`
|
|
89
|
+
- `GET /session/:id/message`
|
|
90
|
+
- `POST /session/:id/message`
|
|
91
|
+
|
|
92
|
+
The connection directory is sent as a server-side query filter and verified against every selected session. Concurrent sends are passed directly to OpenCode; OpenCode owns session queuing. Crossharness does not intercept permissions and does not issue session-wide aborts. If a local HTTP wait times out, the server may still have queued or started the turn; Crossharness reports that uncertainty and never retries.
|
|
93
|
+
|
|
94
|
+
## Codex
|
|
95
|
+
|
|
96
|
+
Start a Codex app-server on an explicit WebSocket URL:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
codex app-server --listen ws://127.0.0.1:4500
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For remote listeners, configure Codex WebSocket authentication and use `wss://`. Crossharness sends `CODEX_REMOTE_TOKEN` as a bearer token.
|
|
103
|
+
|
|
104
|
+
Each connection owns one initialized WebSocket and uses the official app-server JSON-RPC protocol:
|
|
105
|
+
|
|
106
|
+
- `initialize` followed by `initialized`
|
|
107
|
+
- `thread/list` with the connection directory as `cwd`
|
|
108
|
+
- `thread/read` with `includeTurns`
|
|
109
|
+
- `thread/resume`
|
|
110
|
+
- `turn/start` and correlated turn/item notifications
|
|
111
|
+
- `turn/interrupt` for a timed-out correlated turn
|
|
112
|
+
|
|
113
|
+
Turns on different threads may run concurrently. Sends to the same thread are sequenced so notification identity remains unambiguous. Each connection permits at most 100 queued or active sends, with at most 10 for one thread; a queued send can time out before delivery. Approval and elicitation requests are conservatively declined; unsupported server requests receive a JSON-RPC method-not-supported error instead of hanging.
|
|
114
|
+
|
|
115
|
+
If a Codex turn times out, Crossharness keeps the same-thread queue locked until `turn/interrupt` is acknowledged and `turn/completed` confirms terminal state. If the turn cannot be correlated, interruption is not acknowledged, or terminal state is not reported, the WebSocket connection is closed rather than risk overlapping turns or retrying an uncertain send.
|
|
116
|
+
|
|
117
|
+
## Package Migration
|
|
118
|
+
|
|
119
|
+
The package and executable were renamed for consistent `mcp-*` naming:
|
|
120
|
+
|
|
121
|
+
| Previous | Replacement |
|
|
122
|
+
| --- | --- |
|
|
123
|
+
| `@modelprofile.com/crossharness-mcp` | `@modelprofile.com/mcp-crossharness` |
|
|
124
|
+
| `crossharness-mcp` | `mcp-crossharness` |
|
|
125
|
+
|
|
126
|
+
The previous package remains installable after deprecation, and existing lockfiles continue to resolve it. Update package references and MCP client commands explicitly; npm deprecation does not redirect imports or executables.
|
|
127
|
+
|
|
128
|
+
## Install
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
pnpm add -g @modelprofile.com/mcp-crossharness
|
|
132
|
+
|
|
133
|
+
# library use
|
|
134
|
+
pnpm add @modelprofile.com/mcp-crossharness
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Requires Node.js 24 or newer.
|
|
138
|
+
|
|
139
|
+
Register the `mcp-crossharness` binary as a stdio MCP server in your client.
|
|
140
|
+
|
|
141
|
+
## Library API
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import {
|
|
145
|
+
ConnectionRegistry,
|
|
146
|
+
DispatchRegistry,
|
|
147
|
+
CrossHarnessMcpServer,
|
|
148
|
+
} from '@modelprofile.com/mcp-crossharness';
|
|
149
|
+
|
|
150
|
+
const connections = new ConnectionRegistry({
|
|
151
|
+
allowedServerUrls: ['http://127.0.0.1:4096/'],
|
|
152
|
+
openCodeCredentials: {
|
|
153
|
+
serverUrl: 'http://127.0.0.1:4096/',
|
|
154
|
+
username: 'opencode',
|
|
155
|
+
password: controllerOwnedPassword,
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
const connection = await connections.connect(
|
|
160
|
+
'opencode',
|
|
161
|
+
'http://127.0.0.1:4096/',
|
|
162
|
+
'/absolute/path/on/server',
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const chats = await connections.get(connection.connectionId).listChats(10);
|
|
166
|
+
await connections.disconnect(connection.connectionId);
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Connection closure is fail-closed and retryable. `disconnect()` retains ownership when a close
|
|
170
|
+
fails, and another call with the same connection ID retries it. Overlapping close requests share
|
|
171
|
+
the active close attempt. `closeAll()` permanently closes the registry to new connections, waits
|
|
172
|
+
for every current close attempt, and retains failed connections for a later `closeAll()` retry. A
|
|
173
|
+
single failure is rethrown directly; multiple failures are reported as an `AggregateError`.
|
|
174
|
+
|
|
175
|
+
`openCodeCredentials` is intended for an embedding application that owns the
|
|
176
|
+
OpenCode server credential. The registry validates and copies it during
|
|
177
|
+
construction. An injected password bypasses the environment credentials; an
|
|
178
|
+
omitted username uses the protocol default `opencode`. Injected credentials are
|
|
179
|
+
bound to their exact `serverUrl`, never included in connection metadata, and
|
|
180
|
+
redacted from OpenCode HTTP response errors. Plain HTTP injection is accepted
|
|
181
|
+
only for loopback hosts; use HTTPS for remote OpenCode servers. The standalone
|
|
182
|
+
MCP server continues to read its credentials from fixed environment variables;
|
|
183
|
+
credentials are never accepted as tool arguments.
|
|
184
|
+
|
|
185
|
+
## License and Legal Information
|
|
186
|
+
|
|
187
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the repository license file.
|
|
188
|
+
|
|
189
|
+
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
190
|
+
|
|
191
|
+
### Trademarks
|
|
192
|
+
|
|
193
|
+
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
|
194
|
+
|
|
195
|
+
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
|
196
|
+
|
|
197
|
+
### Company Information
|
|
198
|
+
|
|
199
|
+
Task Venture Capital GmbH<br>
|
|
200
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
201
|
+
|
|
202
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
203
|
+
|
|
204
|
+
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
|
+
*/
|
|
4
|
+
export const commitinfo = {
|
|
5
|
+
name: '@modelprofile.com/mcp-crossharness',
|
|
6
|
+
version: '5.0.0',
|
|
7
|
+
description: 'Connection-first MCP server for explicit OpenCode HTTP and Codex WebSocket session servers'
|
|
8
|
+
}
|