@botbotgo/agent-harness 0.0.165 → 0.0.167

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
@@ -28,7 +28,7 @@
28
28
 
29
29
  <p align="center">
30
30
  <a href="https://botbotgo.github.io/agent-harness/development/">Developer docs</a>
31
- (multi-page static docs in <code>docs/development/</code>)
31
+ (<code>docs/development/</code>, English / 中文)
32
32
  </p>
33
33
 
34
34
  <p align="center">
@@ -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
@@ -28,7 +28,7 @@
28
28
 
29
29
  <p align="center">
30
30
  <a href="https://botbotgo.github.io/agent-harness/development/">开发文档</a>
31
- (多页面静态文档位于 <code>docs/development/</code>)
31
+ (多页面静态文档位于 <code>docs/development/</code>,支持 English / 中文)
32
32
  </p>
33
33
 
34
34
  <p align="center">
@@ -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.164";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.166";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.164";
1
+ export const AGENT_HARNESS_VERSION = "0.0.166";
@@ -49,7 +49,7 @@ export async function runLocalToolInvocationLoop({ binding, request, primaryTool
49
49
  throw new Error(`Tool ${toolCall.name} is not configured for this agent.`);
50
50
  }
51
51
  const compiledTool = toolCatalog.get(toolCall.name) ?? toolCatalog.get(resolvedToolName);
52
- const normalizedArgs = normalizeToolArgsForSchema(toolCall.args, activeExecutable.schema);
52
+ const normalizedArgs = normalizeToolArgsForSchema(toolCall.args, activeExecutable.schema, toolCall.rawArgsInput);
53
53
  const toolResult = await activeExecutable.invoke(normalizedArgs);
54
54
  const memoryCandidates = compiledTool ? extractMemoryCandidatesFromToolOutput(compiledTool, toolResult) : [];
55
55
  executedToolResults.push({
@@ -1,7 +1,8 @@
1
1
  export declare function stringifyToolOutput(output: unknown): string;
2
- export declare function normalizeToolArgsForSchema(args: Record<string, unknown>, schema: unknown): Record<string, unknown>;
2
+ export declare function normalizeToolArgsForSchema(args: Record<string, unknown>, schema: unknown, rawArgsInput?: unknown): Record<string, unknown>;
3
3
  export declare function extractToolCallsFromResult(result: unknown): Array<{
4
4
  id?: string;
5
5
  name: string;
6
6
  args: Record<string, unknown>;
7
+ rawArgsInput?: unknown;
7
8
  }>;
@@ -14,7 +14,29 @@ export function stringifyToolOutput(output) {
14
14
  return `${String(output)}`;
15
15
  }
16
16
  }
17
- export function normalizeToolArgsForSchema(args, schema) {
17
+ function mapSingleFieldScalarArg(args, expectedKey, rawArgsInput) {
18
+ if (expectedKey in args) {
19
+ return args;
20
+ }
21
+ if (typeof rawArgsInput === "string") {
22
+ const trimmed = rawArgsInput.trim();
23
+ if (trimmed.length === 0) {
24
+ return args;
25
+ }
26
+ return {
27
+ ...args,
28
+ [expectedKey]: trimmed,
29
+ };
30
+ }
31
+ if (typeof rawArgsInput === "number" || typeof rawArgsInput === "boolean") {
32
+ return {
33
+ ...args,
34
+ [expectedKey]: rawArgsInput,
35
+ };
36
+ }
37
+ return args;
38
+ }
39
+ export function normalizeToolArgsForSchema(args, schema, rawArgsInput) {
18
40
  const schemaDef = isObject(schema) ? schema._def : undefined;
19
41
  const shape = schemaDef
20
42
  ? isRecord(schemaDef.shape)
@@ -34,19 +56,23 @@ export function normalizeToolArgsForSchema(args, schema) {
34
56
  if (expectedKey in args) {
35
57
  return args;
36
58
  }
59
+ const scalarMappedArgs = mapSingleFieldScalarArg(args, expectedKey, rawArgsInput);
60
+ if (expectedKey in scalarMappedArgs) {
61
+ return scalarMappedArgs;
62
+ }
37
63
  const aliasesByExpected = {
38
64
  city: ["location", "locality", "place"],
39
65
  location: ["city", "city_name"],
40
66
  query: ["question", "prompt", "text", "request"],
41
67
  };
42
68
  const aliases = aliasesByExpected[expectedKey] ?? [];
43
- const aliasKey = aliases.find((candidate) => candidate in args);
44
- if (!aliasKey || !(aliasKey in args)) {
45
- return args;
69
+ const aliasKey = aliases.find((candidate) => candidate in scalarMappedArgs);
70
+ if (!aliasKey || !(aliasKey in scalarMappedArgs)) {
71
+ return scalarMappedArgs;
46
72
  }
47
73
  return {
48
- ...args,
49
- [expectedKey]: args[aliasKey],
74
+ ...scalarMappedArgs,
75
+ [expectedKey]: scalarMappedArgs[aliasKey],
50
76
  };
51
77
  }
52
78
  export function extractToolCallsFromResult(result) {
@@ -75,12 +101,13 @@ export function extractToolCallsFromResult(result) {
75
101
  if (!name) {
76
102
  return null;
77
103
  }
78
- const rawArgs = salvageToolArgs(toolCall.args ?? functionPayload?.arguments) ?? {};
104
+ const rawArgsInput = toolCall.args ?? functionPayload?.arguments;
105
+ const rawArgs = salvageToolArgs(rawArgsInput) ?? {};
79
106
  if (!isObject(rawArgs)) {
80
107
  return null;
81
108
  }
82
109
  const id = typeof toolCall.id === "string" ? toolCall.id : undefined;
83
- return { id, name, args: rawArgs };
110
+ return { id, name, args: rawArgs, rawArgsInput };
84
111
  })
85
112
  .filter((item) => item !== null);
86
113
  }
@@ -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,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.165",
3
+ "version": "0.0.167",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",