@botbotgo/agent-harness 0.0.166 → 0.0.168

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
@@ -903,6 +903,8 @@ Primary exports:
903
903
  - `serveAcpHttp`
904
904
  - `serveAcpStdio`
905
905
  - `serveAgUiHttp`
906
+ - `createRuntimeMcpServer`
907
+ - `serveRuntimeMcpOverStdio`
906
908
  - `createToolMcpServer`
907
909
  - `serveToolsOverStdio`
908
910
  - `stop`
@@ -925,5 +927,6 @@ ACP transport notes:
925
927
  - `serveAcpStdio(runtime)` exposes newline-delimited JSON-RPC over stdio for local IDE, CLI, or subprocess clients.
926
928
  - `serveAcpHttp(runtime)` exposes JSON-RPC over HTTP plus SSE runtime events so remote operator surfaces can connect without importing the runtime in-process.
927
929
  - `serveAgUiHttp(runtime)` exposes a minimal AG-UI-compatible HTTP SSE bridge that projects `run + output.delta + final result` onto `RUN_STARTED`, `TEXT_MESSAGE_*`, and `RUN_FINISHED` events for UI clients.
930
+ - `createRuntimeMcpServer(runtime)` and `serveRuntimeMcpOverStdio(runtime)` expose the persisted runtime control surface itself as MCP tools, including sessions, requests, approvals, artifacts, events, and package export helpers.
928
931
  - `exportRunPackage(...)` and `exportSessionPackage(...)` package stable runtime records, transcript, approvals, events, and artifacts for operator tooling without reaching into persistence internals.
929
932
  - `runtime/default.governance.remoteMcp` can now deny or allow specific MCP servers, raise approval requirements by transport, and stamp transport-based risk tiers into runtime governance bundles.
package/README.zh.md CHANGED
@@ -862,6 +862,8 @@ spec:
862
862
  - `serveAcpHttp`
863
863
  - `serveAcpStdio`
864
864
  - `serveAgUiHttp`
865
+ - `createRuntimeMcpServer`
866
+ - `serveRuntimeMcpOverStdio`
865
867
  - `createToolMcpServer`
866
868
  - `serveToolsOverStdio`
867
869
  - `stop`
@@ -884,5 +886,6 @@ ACP transport 说明:
884
886
  - `serveAcpStdio(runtime)` 提供基于 stdio 的 newline-delimited JSON-RPC,适合本地 IDE、CLI 或子进程客户端。
885
887
  - `serveAcpHttp(runtime)` 提供基于 HTTP 的 JSON-RPC 与 SSE runtime events,适合远程 operator surface 或独立控制面接入。
886
888
  - `serveAgUiHttp(runtime)` 提供最小可用的 AG-UI HTTP SSE bridge,把现有 `run + output.delta + final result` 投影成 `RUN_STARTED`、`TEXT_MESSAGE_*` 与 `RUN_FINISHED` 事件,便于 UI 客户端直接接入。
889
+ - `createRuntimeMcpServer(runtime)` 与 `serveRuntimeMcpOverStdio(runtime)` 会把持久化 runtime 控制面本身暴露成 MCP tools,包括 sessions、requests、approvals、artifacts、events 与 package export helpers。
887
890
  - `exportRunPackage(...)` 与 `exportSessionPackage(...)` 可把稳定 runtime 记录、transcript、approvals、events 和 artifacts 打包给 operator tooling,而不必直接访问 persistence 内部实现。
888
891
  - `runtime/default.governance.remoteMcp` 现在可以按 MCP server 或 transport 做 allow/deny、审批升级,并把 transport 风险等级写进 runtime governance bundles。
package/dist/api.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { ArtifactListing, CancelOptions, InvocationEnvelope, ListMemoriesIn
2
2
  import { AgentHarnessRuntime } from "./runtime/harness.js";
3
3
  import type { InventoryAgentRecord, InventorySkillRecord } from "./runtime/harness/system/inventory.js";
4
4
  import type { RequirementAssessmentOptions } from "./runtime/harness/system/skill-requirements.js";
5
- import type { ToolMcpServerOptions } from "./mcp.js";
5
+ import type { RuntimeMcpServerOptions, ToolMcpServerOptions } from "./mcp.js";
6
6
  export { AgentHarnessAcpServer, createAcpServer } from "./acp.js";
7
7
  export type { AcpApproval, AcpArtifact, AcpEventNotification, AcpJsonRpcError, AcpJsonRpcRequest, AcpJsonRpcResponse, AcpJsonRpcSuccess, AcpRequestRecord, AcpRunRequestParams, AcpServerCapabilities, AcpSessionRecord, } from "./acp.js";
8
8
  export { AgentHarnessRuntime } from "./runtime/harness.js";
@@ -115,3 +115,5 @@ export declare function cancelRun(runtime: AgentHarnessRuntime, options: CancelO
115
115
  export declare function stop(runtime: AgentHarnessRuntime): Promise<void>;
116
116
  export declare function createToolMcpServer(runtime: AgentHarnessRuntime, options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
117
117
  export declare function serveToolsOverStdio(runtime: AgentHarnessRuntime, options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
118
+ export declare function createRuntimeMcpServer(runtime: AgentHarnessRuntime, options?: RuntimeMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
119
+ export declare function serveRuntimeMcpOverStdio(runtime: AgentHarnessRuntime, options?: RuntimeMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
package/dist/api.js CHANGED
@@ -243,6 +243,12 @@ export async function createToolMcpServer(runtime, options) {
243
243
  export async function serveToolsOverStdio(runtime, options) {
244
244
  return runtime.serveToolsOverStdio(options);
245
245
  }
246
+ export async function createRuntimeMcpServer(runtime, options) {
247
+ return runtime.createRuntimeMcpServer(options);
248
+ }
249
+ export async function serveRuntimeMcpOverStdio(runtime, options) {
250
+ return runtime.serveRuntimeMcpOverStdio(options);
251
+ }
246
252
  function normalizeUserChatMessage(message) {
247
253
  if (message.role !== "user") {
248
254
  throw new Error("normalizeUserChatInput only accepts user-role chat messages.");
package/dist/cli.d.ts CHANGED
@@ -3,6 +3,7 @@ import { createAgentHarness } from "./api.js";
3
3
  import { serveAgUiOverHttp } from "./protocol/ag-ui/http.js";
4
4
  import { serveAcpOverHttp } from "./protocol/acp/http.js";
5
5
  import { serveAcpOverStdio } from "./protocol/acp/stdio.js";
6
+ import { serveRuntimeMcpOverStdio } from "./mcp.js";
6
7
  type CliIo = {
7
8
  cwd?: string;
8
9
  stdout?: (message: string) => void;
@@ -13,6 +14,7 @@ type CliDeps = {
13
14
  serveAgUiOverHttp?: typeof serveAgUiOverHttp;
14
15
  serveAcpOverHttp?: typeof serveAcpOverHttp;
15
16
  serveAcpOverStdio?: typeof serveAcpOverStdio;
17
+ serveRuntimeMcpOverStdio?: typeof serveRuntimeMcpOverStdio;
16
18
  };
17
19
  export declare function runCli(argv: string[], io?: CliIo, deps?: CliDeps): Promise<number>;
18
20
  export {};
package/dist/cli.js CHANGED
@@ -6,11 +6,13 @@ import { initProject } from "./init-project.js";
6
6
  import { serveAgUiOverHttp } from "./protocol/ag-ui/http.js";
7
7
  import { serveAcpOverHttp } from "./protocol/acp/http.js";
8
8
  import { serveAcpOverStdio } from "./protocol/acp/stdio.js";
9
+ import { serveRuntimeMcpOverStdio } from "./mcp.js";
9
10
  function renderUsage() {
10
11
  return `Usage:
11
12
  agent-harness init <project-name> [--template deep-research|single-agent] [--provider <provider>] [--model <model>] [--with-web-search|--no-web-search]
12
13
  agent-harness acp serve [--workspace <path>] [--transport stdio|http] [--host <hostname>] [--port <port>]
13
14
  agent-harness ag-ui serve [--workspace <path>] [--host <hostname>] [--port <port>]
15
+ agent-harness runtime-mcp serve [--workspace <path>]
14
16
  `;
15
17
  }
16
18
  function isTemplate(value) {
@@ -156,6 +158,7 @@ export async function runCli(argv, io = {}, deps = {}) {
156
158
  const serveAgUi = deps.serveAgUiOverHttp ?? serveAgUiOverHttp;
157
159
  const serveAcpHttp = deps.serveAcpOverHttp ?? serveAcpOverHttp;
158
160
  const serveAcp = deps.serveAcpOverStdio ?? serveAcpOverStdio;
161
+ const serveRuntimeMcp = deps.serveRuntimeMcpOverStdio ?? serveRuntimeMcpOverStdio;
159
162
  if (command === "init") {
160
163
  if (!projectName?.trim()) {
161
164
  stderr(renderUsage());
@@ -253,6 +256,37 @@ export async function runCli(argv, io = {}, deps = {}) {
253
256
  return 1;
254
257
  }
255
258
  }
259
+ if (command === "runtime-mcp") {
260
+ const [subcommand, ...subcommandArgs] = [projectName, ...rest];
261
+ if (subcommand !== "serve") {
262
+ stderr(renderUsage());
263
+ return 1;
264
+ }
265
+ const parsed = parseHttpServeOptions(subcommandArgs);
266
+ if (parsed.error) {
267
+ stderr(`${parsed.error}\n`);
268
+ stderr(renderUsage());
269
+ return 1;
270
+ }
271
+ try {
272
+ const runtime = await createHarness(path.resolve(cwd, parsed.workspaceRoot ?? "."));
273
+ const workspacePath = path.resolve(cwd, parsed.workspaceRoot ?? ".");
274
+ stderr(`Serving runtime MCP over stdio from ${workspacePath}\n`);
275
+ const server = await serveRuntimeMcp(runtime);
276
+ await new Promise((resolve, reject) => {
277
+ process.stdin.on("end", resolve);
278
+ process.stdin.on("error", reject);
279
+ });
280
+ await server.close();
281
+ await runtime.stop();
282
+ return 0;
283
+ }
284
+ catch (error) {
285
+ const message = error instanceof Error ? error.message : String(error);
286
+ stderr(`${message}\n`);
287
+ return 1;
288
+ }
289
+ }
256
290
  stderr(renderUsage());
257
291
  return 1;
258
292
  }
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- export { AgentHarnessAcpServer, AgentHarnessRuntime, buildFlowGraph, cancelRun, createAgentHarness, createAcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, exportRunPackage, exportSessionPackage, replayEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, listRunEvents, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveAcpHttp, serveAcpStdio, serveAgUiHttp, serveToolsOverStdio, subscribe, stop, updateMemory, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid, } from "./api.js";
1
+ export { AgentHarnessAcpServer, AgentHarnessRuntime, buildFlowGraph, cancelRun, createAgentHarness, createAcpServer, createRuntimeMcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, exportRunPackage, exportSessionPackage, replayEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, listRunEvents, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveAcpHttp, serveAcpStdio, serveAgUiHttp, serveRuntimeMcpOverStdio, serveToolsOverStdio, subscribe, stop, updateMemory, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid, } from "./api.js";
2
2
  export type { AcpApproval, AcpArtifact, AcpEventNotification, AcpJsonRpcError, AcpJsonRpcRequest, AcpJsonRpcResponse, AcpJsonRpcSuccess, AcpRequestRecord, AcpRunRequestParams, AcpServerCapabilities, AcpSessionRecord, } from "./acp.js";
3
3
  export type { ListMemoriesInput, ListMemoriesResult, MemoryDecision, MemoryKind, MemoryRecord, MemoryScope, MemorizeInput, MemorizeResult, NormalizeUserChatInputOptions, RecallInput, RecallResult, RemoveMemoryInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, UpdateMemoryInput, UserChatInput, UserChatMessage, } from "./api.js";
4
4
  export type { BuildFlowGraphInput, FlowEdge, FlowEdgeKind, FlowGraph, FlowGraphMermaidOptions, FlowGraphSequenceMermaidOptions, FlowGroup, FlowGroupKind, FlowNode, FlowNodeKind, FlowNodeLayer, FlowNodeStatus, } from "./flow/index.js";
5
5
  export type { AcpHttpServer, AcpHttpServerOptions, AcpStdioServer, AcpStdioServerOptions, AgUiEvent, AgUiHttpServer, AgUiHttpServerOptions, AgUiRunAgentInput, } from "./api.js";
6
- export type { ToolMcpServerOptions } from "./mcp.js";
6
+ export type { RuntimeMcpServerOptions, ToolMcpServerOptions } from "./mcp.js";
7
7
  export { tool } from "./tools.js";
8
8
  export type { UpstreamTimelineProjection, UpstreamTimelineReducer } from "./upstream-events.js";
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { AgentHarnessAcpServer, AgentHarnessRuntime, buildFlowGraph, cancelRun, createAgentHarness, createAcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, exportRunPackage, exportSessionPackage, replayEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, listRunEvents, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveAcpHttp, serveAcpStdio, serveAgUiHttp, serveToolsOverStdio, subscribe, stop, updateMemory, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid, } from "./api.js";
1
+ export { AgentHarnessAcpServer, AgentHarnessRuntime, buildFlowGraph, cancelRun, createAgentHarness, createAcpServer, createRuntimeMcpServer, createUpstreamTimelineReducer, createToolMcpServer, deleteSession, describeInventory, exportEvaluationBundle, exportRunPackage, exportSessionPackage, replayEvaluationBundle, getArtifact, getAgent, getApproval, getRequest, getHealth, listMemories, listRunEvents, getSession, listAgentSkills, listArtifacts, listApprovals, listRequests, listSessions, memorize, normalizeUserChatInput, recall, removeMemory, resolveApproval, run, serveAcpHttp, serveAcpStdio, serveAgUiHttp, serveRuntimeMcpOverStdio, serveToolsOverStdio, subscribe, stop, updateMemory, exportFlowGraphToMermaid, exportFlowGraphToSequenceMermaid, } from "./api.js";
2
2
  export { tool } from "./tools.js";
package/dist/mcp.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import type { CompiledTool, ParsedToolObject } from "./contracts/types.js";
2
+ import type { ApprovalRecord, ArtifactListing, CompiledTool, HarnessEvent, ParsedToolObject, RunResult, RunState, RunSummary, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, ThreadRecord, ThreadSummary } from "./contracts/types.js";
3
3
  export type ToolMcpServerOptions = {
4
4
  agentId: string;
5
5
  serverInfo?: {
@@ -13,5 +13,44 @@ export type ToolMcpServerTool = {
13
13
  resolvedTool: unknown;
14
14
  sourceTool?: ParsedToolObject;
15
15
  };
16
+ export type RuntimeMcpServerOptions = {
17
+ serverInfo?: {
18
+ name?: string;
19
+ version?: string;
20
+ };
21
+ };
22
+ type RuntimeMcpRuntime = {
23
+ listThreads: (filter?: {
24
+ agentId?: string;
25
+ }) => Promise<ThreadSummary[]>;
26
+ getThread: (threadId: string) => Promise<ThreadRecord | null>;
27
+ listRuns: (filter?: {
28
+ agentId?: string;
29
+ threadId?: string;
30
+ state?: RunState;
31
+ }) => Promise<RunSummary[]>;
32
+ getRun: (runId: string) => Promise<RunSummary | null>;
33
+ listApprovals: (filter?: {
34
+ status?: ApprovalRecord["status"];
35
+ threadId?: string;
36
+ runId?: string;
37
+ }) => Promise<ApprovalRecord[]>;
38
+ getApproval: (approvalId: string) => Promise<ApprovalRecord | null>;
39
+ resume: (options: {
40
+ approvalId?: string;
41
+ threadId?: string;
42
+ runId?: string;
43
+ decision?: "approve" | "edit" | "reject";
44
+ editedInput?: Record<string, unknown>;
45
+ }) => Promise<RunResult>;
46
+ listArtifacts: (threadId: string, runId: string) => Promise<ArtifactListing>;
47
+ readArtifact: (threadId: string, runId: string, artifactPath: string) => Promise<unknown>;
48
+ listRunEvents: (threadId: string, runId: string) => Promise<HarnessEvent[]>;
49
+ exportRunPackage: (input: RuntimeRunPackageInput) => Promise<RuntimeRunPackage>;
50
+ exportSessionPackage: (input: RuntimeSessionPackageInput) => Promise<RuntimeSessionPackage>;
51
+ };
16
52
  export declare function createToolMcpServerFromTools(tools: ToolMcpServerTool[], options: ToolMcpServerOptions): Promise<McpServer>;
17
53
  export declare function serveToolsOverStdioFromHarness(tools: ToolMcpServerTool[], options: ToolMcpServerOptions): Promise<McpServer>;
54
+ export declare function createRuntimeMcpServer(runtime: RuntimeMcpRuntime, options?: RuntimeMcpServerOptions): Promise<McpServer>;
55
+ export declare function serveRuntimeMcpOverStdio(runtime: RuntimeMcpRuntime, options?: RuntimeMcpServerOptions): Promise<McpServer>;
56
+ export {};
package/dist/mcp.js CHANGED
@@ -110,3 +110,144 @@ export async function serveToolsOverStdioFromHarness(tools, options) {
110
110
  await server.connect(new StdioServerTransport());
111
111
  return server;
112
112
  }
113
+ export async function createRuntimeMcpServer(runtime, options = {}) {
114
+ const server = new McpServer({
115
+ name: options.serverInfo?.name ?? "agent-harness-runtime",
116
+ version: options.serverInfo?.version ?? AGENT_HARNESS_VERSION,
117
+ });
118
+ server.tool("list_sessions", "List persisted runtime sessions.", {
119
+ agentId: z.string().optional(),
120
+ }, async (input) => ({
121
+ content: [{
122
+ type: "text",
123
+ text: renderToolOutput(await runtime.listThreads(input.agentId ? { agentId: input.agentId } : undefined)),
124
+ }],
125
+ }));
126
+ server.tool("get_session", "Get one persisted runtime session by id.", {
127
+ sessionId: z.string(),
128
+ }, async (input) => ({
129
+ content: [{
130
+ type: "text",
131
+ text: renderToolOutput(await runtime.getThread(input.sessionId)),
132
+ }],
133
+ }));
134
+ server.tool("list_requests", "List persisted runtime requests.", {
135
+ agentId: z.string().optional(),
136
+ sessionId: z.string().optional(),
137
+ state: z.enum(["queued", "running", "waiting_for_approval", "completed", "failed", "cancelled"]).optional(),
138
+ }, async (input) => ({
139
+ content: [{
140
+ type: "text",
141
+ text: renderToolOutput(await runtime.listRuns({
142
+ ...(input.agentId ? { agentId: input.agentId } : {}),
143
+ ...(input.sessionId ? { threadId: input.sessionId } : {}),
144
+ ...(input.state ? { state: input.state } : {}),
145
+ })),
146
+ }],
147
+ }));
148
+ server.tool("get_request", "Get one persisted runtime request by id.", {
149
+ requestId: z.string(),
150
+ }, async (input) => ({
151
+ content: [{
152
+ type: "text",
153
+ text: renderToolOutput(await runtime.getRun(input.requestId)),
154
+ }],
155
+ }));
156
+ server.tool("list_approvals", "List runtime approvals.", {
157
+ status: z.enum(["pending", "approved", "edited", "rejected", "expired"]).optional(),
158
+ sessionId: z.string().optional(),
159
+ requestId: z.string().optional(),
160
+ }, async (input) => ({
161
+ content: [{
162
+ type: "text",
163
+ text: renderToolOutput(await runtime.listApprovals({
164
+ ...(input.status ? { status: input.status } : {}),
165
+ ...(input.sessionId ? { threadId: input.sessionId } : {}),
166
+ ...(input.requestId ? { runId: input.requestId } : {}),
167
+ })),
168
+ }],
169
+ }));
170
+ server.tool("get_approval", "Get one runtime approval by id.", {
171
+ approvalId: z.string(),
172
+ }, async (input) => ({
173
+ content: [{
174
+ type: "text",
175
+ text: renderToolOutput(await runtime.getApproval(input.approvalId)),
176
+ }],
177
+ }));
178
+ server.tool("resolve_approval", "Resolve one runtime approval.", {
179
+ approvalId: z.string(),
180
+ decision: z.enum(["approve", "edit", "reject"]),
181
+ sessionId: z.string().optional(),
182
+ requestId: z.string().optional(),
183
+ editedInput: z.record(z.string(), z.any()).optional(),
184
+ }, async (input) => ({
185
+ content: [{
186
+ type: "text",
187
+ text: renderToolOutput(await runtime.resume({
188
+ approvalId: input.approvalId,
189
+ decision: input.decision,
190
+ ...(input.sessionId ? { threadId: input.sessionId } : {}),
191
+ ...(input.requestId ? { runId: input.requestId } : {}),
192
+ ...(input.editedInput ? { editedInput: input.editedInput } : {}),
193
+ })),
194
+ }],
195
+ }));
196
+ server.tool("list_artifacts", "List artifacts for one runtime request.", {
197
+ sessionId: z.string(),
198
+ requestId: z.string(),
199
+ }, async (input) => ({
200
+ content: [{
201
+ type: "text",
202
+ text: renderToolOutput(await runtime.listArtifacts(input.sessionId, input.requestId)),
203
+ }],
204
+ }));
205
+ server.tool("read_artifact", "Read one runtime artifact.", {
206
+ sessionId: z.string(),
207
+ requestId: z.string(),
208
+ artifactPath: z.string(),
209
+ }, async (input) => ({
210
+ content: [{
211
+ type: "text",
212
+ text: renderToolOutput(await runtime.readArtifact(input.sessionId, input.requestId, input.artifactPath)),
213
+ }],
214
+ }));
215
+ server.tool("list_run_events", "List persisted runtime events for one request.", {
216
+ sessionId: z.string(),
217
+ requestId: z.string(),
218
+ }, async (input) => ({
219
+ content: [{
220
+ type: "text",
221
+ text: renderToolOutput(await runtime.listRunEvents(input.sessionId, input.requestId)),
222
+ }],
223
+ }));
224
+ server.tool("export_run_package", "Export a stable runtime run package for one request.", {
225
+ sessionId: z.string(),
226
+ requestId: z.string(),
227
+ includeArtifacts: z.boolean().optional(),
228
+ includeArtifactContents: z.boolean().optional(),
229
+ includeRuntimeHealth: z.boolean().optional(),
230
+ }, async (input) => ({
231
+ content: [{
232
+ type: "text",
233
+ text: renderToolOutput(await runtime.exportRunPackage(input)),
234
+ }],
235
+ }));
236
+ server.tool("export_session_package", "Export a stable runtime session package.", {
237
+ sessionId: z.string(),
238
+ includeArtifacts: z.boolean().optional(),
239
+ includeArtifactContents: z.boolean().optional(),
240
+ includeRuntimeHealth: z.boolean().optional(),
241
+ }, async (input) => ({
242
+ content: [{
243
+ type: "text",
244
+ text: renderToolOutput(await runtime.exportSessionPackage(input)),
245
+ }],
246
+ }));
247
+ return server;
248
+ }
249
+ export async function serveRuntimeMcpOverStdio(runtime, options = {}) {
250
+ const server = await createRuntimeMcpServer(runtime, options);
251
+ await server.connect(new StdioServerTransport());
252
+ return server;
253
+ }
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.165";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.167";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.165";
1
+ export const AGENT_HARNESS_VERSION = "0.0.167";
@@ -1,4 +1,4 @@
1
- import { isToolCallParseFailure, sanitizeVisibleText, } from "../../parsing/output-parsing.js";
1
+ import { isToolCallRecoveryFailure, sanitizeVisibleText, } from "../../parsing/output-parsing.js";
2
2
  import { buildInvocationRequest } from "../model/invocation-request.js";
3
3
  import { buildRawModelMessages } from "../model/message-assembly.js";
4
4
  import { projectRuntimeStreamEvent, createStreamEventProjectionState } from "../stream-event-projection.js";
@@ -82,7 +82,7 @@ export async function* streamRuntimeExecution(options) {
82
82
  error.message.includes("does not support tool binding")) {
83
83
  throw error;
84
84
  }
85
- if (!isToolCallParseFailure(error)) {
85
+ if (!isToolCallRecoveryFailure(error)) {
86
86
  throw error;
87
87
  }
88
88
  const retried = await options.invoke(options.applyStrictToolJsonInstruction(options.binding), options.input, options.threadId, options.runtimeOptions.runId ?? options.threadId, undefined, options.history, options.runtimeOptions);
@@ -1,5 +1,5 @@
1
1
  import { setTimeout as sleep } from "node:timers/promises";
2
- import { extractVisibleOutput, isToolCallParseFailure, STRICT_TOOL_JSON_INSTRUCTION } from "../parsing/output-parsing.js";
2
+ import { extractVisibleOutput, isToolCallRecoveryFailure, STRICT_TOOL_JSON_INSTRUCTION } from "../parsing/output-parsing.js";
3
3
  import { readStreamDelta } from "../parsing/stream-event-parsing.js";
4
4
  import { computeRemainingTimeoutMs, isRetryableProviderError, resolveProviderRetryPolicy } from "./resilience.js";
5
5
  import { isDeepAgentBinding, isLangChainBinding, withUpdatedBindingExecutionParams, } from "../support/compiled-binding.js";
@@ -153,7 +153,7 @@ export async function callRuntimeWithToolParseRecovery(input) {
153
153
  return await input.callRuntime(input.binding, input.request);
154
154
  }
155
155
  catch (error) {
156
- if (input.resumePayload !== undefined || !isToolCallParseFailure(error)) {
156
+ if (input.resumePayload !== undefined || !isToolCallRecoveryFailure(error)) {
157
157
  throw error;
158
158
  }
159
159
  return input.callRuntime(applyStrictToolJsonInstruction(input.binding), input.request);
@@ -1,5 +1,5 @@
1
1
  import type { ApprovalRecord, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RunRecord, RunStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRunPackage, RuntimeRunPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, ResumeOptions, RunOptions, RunResult, RunSummary, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, ThreadSummary, ThreadRecord, WorkspaceBundle } from "../contracts/types.js";
2
- import { type ToolMcpServerOptions } from "../mcp.js";
2
+ import { type RuntimeMcpServerOptions, type ToolMcpServerOptions } from "../mcp.js";
3
3
  import { type InventoryAgentRecord, type InventorySkillRecord } from "./harness/system/inventory.js";
4
4
  import type { RequirementAssessmentOptions } from "./harness/system/skill-requirements.js";
5
5
  export declare class AgentHarnessRuntime {
@@ -99,6 +99,8 @@ export declare class AgentHarnessRuntime {
99
99
  deleteThread(threadId: string): Promise<boolean>;
100
100
  createToolMcpServer(options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
101
101
  serveToolsOverStdio(options: ToolMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
102
+ createRuntimeMcpServer(options?: RuntimeMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
103
+ serveRuntimeMcpOverStdio(options?: RuntimeMcpServerOptions): Promise<import("@modelcontextprotocol/sdk/server/mcp.js").McpServer>;
102
104
  routeAgent(input: MessageContent, options?: {
103
105
  threadId?: string;
104
106
  }): Promise<string>;
@@ -22,7 +22,7 @@ import { acquireRunSlot as acquireHarnessRunSlot } from "./harness/run/run-slot-
22
22
  import { dropPendingRunSlot, enqueuePendingRunSlot } from "./harness/run/run-queue.js";
23
23
  import { getDefaultRuntimeEntryAgentId, resolveSelectedAgentId, routeAgentId } from "./harness/run/routing.js";
24
24
  import { resolveStoreFromConfig, resolveVectorStore, } from "./harness/run/resources.js";
25
- import { createToolMcpServerFromTools, serveToolsOverStdioFromHarness } from "../mcp.js";
25
+ import { createRuntimeMcpServer, createToolMcpServerFromTools, serveRuntimeMcpOverStdio, serveToolsOverStdioFromHarness, } from "../mcp.js";
26
26
  import { closeMcpClientsForWorkspace } from "../resource/mcp-tool-support.js";
27
27
  import { getBindingRuntimeExecutionMode, } from "./support/compiled-binding.js";
28
28
  import { bindingSupportsRunningReplay, getWorkspaceBinding, resolveWorkspaceAgentTools, } from "./harness/bindings.js";
@@ -653,6 +653,12 @@ export class AgentHarnessRuntime {
653
653
  const tools = this.resolveToolMcpServerTools(options.agentId);
654
654
  return serveToolsOverStdioFromHarness(tools, options);
655
655
  }
656
+ async createRuntimeMcpServer(options = {}) {
657
+ return createRuntimeMcpServer(this, options);
658
+ }
659
+ async serveRuntimeMcpOverStdio(options = {}) {
660
+ return serveRuntimeMcpOverStdio(this, options);
661
+ }
656
662
  async routeAgent(input, options = {}) {
657
663
  return routeAgentId({
658
664
  workspace: this.workspace,
@@ -10,6 +10,8 @@ export declare function extractOutputContent(value: unknown): unknown;
10
10
  export declare function extractContentBlocks(value: unknown): unknown[];
11
11
  export declare function extractEmptyAssistantMessageFailure(value: unknown): string;
12
12
  export declare function isToolCallParseFailure(error: unknown): boolean;
13
+ export declare function isToolCallValidationFailure(error: unknown): boolean;
14
+ export declare function isToolCallRecoveryFailure(error: unknown): boolean;
13
15
  export declare const STRICT_TOOL_JSON_INSTRUCTION = "When calling tools, return only the tool call itself. The arguments must be a pure JSON object with no explanatory text before or after it.";
14
16
  export declare function wrapResolvedModel<T>(value: T): T;
15
17
  export declare function extractReasoningText(value: unknown): string;
@@ -492,6 +492,28 @@ export function isToolCallParseFailure(error) {
492
492
  return false;
493
493
  return /error parsing tool call:/i.test(error.message);
494
494
  }
495
+ function isStructuredValidationIssue(value) {
496
+ if (typeof value !== "object" || !value || Array.isArray(value)) {
497
+ return false;
498
+ }
499
+ const typed = value;
500
+ return typeof typed.code === "string" && Array.isArray(typed.path) && (typed.message === undefined || typeof typed.message === "string");
501
+ }
502
+ export function isToolCallValidationFailure(error) {
503
+ if (!(error instanceof Error))
504
+ return false;
505
+ const message = error.message.trim();
506
+ if (!message)
507
+ return false;
508
+ const direct = tryParseJson(message);
509
+ if (Array.isArray(direct) && direct.length > 0 && direct.every((issue) => isStructuredValidationIssue(issue) && issue.path.length > 0)) {
510
+ return true;
511
+ }
512
+ return /Invalid input:\s*expected .* received undefined/i.test(message) && /"path"\s*:\s*\[/.test(message);
513
+ }
514
+ export function isToolCallRecoveryFailure(error) {
515
+ return isToolCallParseFailure(error) || isToolCallValidationFailure(error);
516
+ }
495
517
  export const STRICT_TOOL_JSON_INSTRUCTION = "When calling tools, return only the tool call itself. The arguments must be a pure JSON object with no explanatory text before or after it.";
496
518
  function appendStrictToolInstruction(input) {
497
519
  if (Array.isArray(input)) {
@@ -518,7 +540,7 @@ export function wrapResolvedModel(value) {
518
540
  return normalizeAgentMessage(await member.apply(currentTarget, args));
519
541
  }
520
542
  catch (error) {
521
- if (!isToolCallParseFailure(error)) {
543
+ if (!isToolCallRecoveryFailure(error)) {
522
544
  throw error;
523
545
  }
524
546
  const retryArgs = [...args];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.166",
3
+ "version": "0.0.168",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",