@superdurable/dex-agents 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1608 -64
- package/dist/src/agent-built-in-tools.d.ts +81 -0
- package/dist/src/agent-built-in-tools.js +246 -0
- package/dist/src/agent-built-in-tools.js.map +1 -0
- package/dist/src/agent-context-compaction.d.ts +254 -0
- package/dist/src/agent-context-compaction.js +287 -0
- package/dist/src/agent-context-compaction.js.map +1 -0
- package/dist/src/agent-framework-runner.d.ts +456 -16
- package/dist/src/agent-framework-runner.js +4 -3
- package/dist/src/agent-framework-runner.js.map +1 -1
- package/dist/src/agent-plans.d.ts +48 -0
- package/dist/src/agent-plans.js +86 -0
- package/dist/src/agent-plans.js.map +1 -0
- package/dist/src/agent-session-cancellation-steps.d.ts +28 -0
- package/dist/src/agent-session-cancellation-steps.js +154 -0
- package/dist/src/agent-session-cancellation-steps.js.map +1 -0
- package/dist/src/agent-session-codecs.d.ts +65 -4
- package/dist/src/agent-session-codecs.js +343 -8
- package/dist/src/agent-session-codecs.js.map +1 -1
- package/dist/src/agent-session-failure.d.ts +58 -0
- package/dist/src/agent-session-failure.js +126 -0
- package/dist/src/agent-session-failure.js.map +1 -0
- package/dist/src/agent-session-flow-graph-cli.d.ts +2 -0
- package/dist/src/agent-session-flow-graph-cli.js +47 -0
- package/dist/src/agent-session-flow-graph-cli.js.map +1 -0
- package/dist/src/agent-session-flow-graph.d.ts +38 -0
- package/dist/src/agent-session-flow-graph.js +54 -0
- package/dist/src/agent-session-flow-graph.js.map +1 -0
- package/dist/src/agent-session-flow-graph.json +2187 -0
- package/dist/src/agent-session-flow.d.ts +317 -28
- package/dist/src/agent-session-flow.js +373 -21
- package/dist/src/agent-session-flow.js.map +1 -1
- package/dist/src/agent-session-persistence.d.ts +81 -4
- package/dist/src/agent-session-persistence.js +33 -2
- package/dist/src/agent-session-persistence.js.map +1 -1
- package/dist/src/agent-session-settings.d.ts +58 -0
- package/dist/src/agent-session-settings.js +81 -0
- package/dist/src/agent-session-settings.js.map +1 -0
- package/dist/src/agent-session-spend-limit.d.ts +156 -0
- package/dist/src/agent-session-spend-limit.js +42 -0
- package/dist/src/agent-session-spend-limit.js.map +1 -0
- package/dist/src/agent-session-start.d.ts +49 -0
- package/dist/src/agent-session-start.js +67 -0
- package/dist/src/agent-session-start.js.map +1 -0
- package/dist/src/agent-session-step-options.d.ts +78 -0
- package/dist/src/agent-session-step-options.js +71 -0
- package/dist/src/agent-session-step-options.js.map +1 -0
- package/dist/src/agent-session-step-types.d.ts +20 -0
- package/dist/src/agent-session-step-types.js +28 -0
- package/dist/src/agent-session-step-types.js.map +1 -0
- package/dist/src/agent-session-steps.d.ts +103 -8
- package/dist/src/agent-session-steps.js +997 -197
- package/dist/src/agent-session-steps.js.map +1 -1
- package/dist/src/agent-session-tracer.d.ts +61 -0
- package/dist/src/agent-session-tracer.js +608 -0
- package/dist/src/agent-session-tracer.js.map +1 -0
- package/dist/src/agent-session-transitions.d.ts +200 -26
- package/dist/src/agent-session-transitions.js +732 -32
- package/dist/src/agent-session-transitions.js.map +1 -1
- package/dist/src/agent-session-values.d.ts +696 -30
- package/dist/src/agent-session-values.js +39 -4
- package/dist/src/agent-session-values.js.map +1 -1
- package/dist/src/agent-session-wait-steps.d.ts +53 -0
- package/dist/src/agent-session-wait-steps.js +389 -0
- package/dist/src/agent-session-wait-steps.js.map +1 -0
- package/dist/src/agent-tracing-options.d.ts +107 -0
- package/dist/src/agent-tracing-options.js +20 -0
- package/dist/src/agent-tracing-options.js.map +1 -0
- package/dist/src/ai-sdk/ai-sdk-model-client.d.ts +40 -0
- package/dist/src/ai-sdk/ai-sdk-model-client.js +235 -0
- package/dist/src/ai-sdk/ai-sdk-model-client.js.map +1 -0
- package/dist/src/ai-sdk/index.d.ts +1 -0
- package/dist/src/ai-sdk/index.js +9 -0
- package/dist/src/ai-sdk/index.js.map +1 -0
- package/dist/src/index.d.ts +14 -3
- package/dist/src/index.js +12 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/index.d.ts +3 -0
- package/dist/src/mcp/index.js +10 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/mcp/mcp-resource-and-prompt-tools.d.ts +29 -0
- package/dist/src/mcp/mcp-resource-and-prompt-tools.js +185 -0
- package/dist/src/mcp/mcp-resource-and-prompt-tools.js.map +1 -0
- package/dist/src/mcp/mcp-server-config.d.ts +86 -0
- package/dist/src/mcp/mcp-server-config.js +38 -0
- package/dist/src/mcp/mcp-server-config.js.map +1 -0
- package/dist/src/mcp/mcp-tool-source.d.ts +470 -0
- package/dist/src/mcp/mcp-tool-source.js +1204 -0
- package/dist/src/mcp/mcp-tool-source.js.map +1 -0
- package/dist/src/stepwise/agent-definition.d.ts +166 -0
- package/dist/src/stepwise/agent-definition.js +9 -0
- package/dist/src/stepwise/agent-definition.js.map +1 -0
- package/dist/src/stepwise/function-tool.d.ts +130 -0
- package/dist/src/stepwise/function-tool.js +75 -0
- package/dist/src/stepwise/function-tool.js.map +1 -0
- package/dist/src/stepwise/index.d.ts +8 -0
- package/dist/src/stepwise/index.js +13 -0
- package/dist/src/stepwise/index.js.map +1 -0
- package/dist/src/stepwise/json-schema-validation.d.ts +9 -0
- package/dist/src/stepwise/json-schema-validation.js +141 -0
- package/dist/src/stepwise/json-schema-validation.js.map +1 -0
- package/dist/src/stepwise/model-client.d.ts +194 -0
- package/dist/src/stepwise/model-client.js +9 -0
- package/dist/src/stepwise/model-client.js.map +1 -0
- package/dist/src/stepwise/scripted-model-client.d.ts +99 -0
- package/dist/src/stepwise/scripted-model-client.js +156 -0
- package/dist/src/stepwise/scripted-model-client.js.map +1 -0
- package/dist/src/stepwise/stepwise-agent-runner.d.ts +171 -0
- package/dist/src/stepwise/stepwise-agent-runner.js +777 -0
- package/dist/src/stepwise/stepwise-agent-runner.js.map +1 -0
- package/dist/src/stepwise/stepwise-agent-session-flow.d.ts +35 -0
- package/dist/src/stepwise/stepwise-agent-session-flow.js +57 -0
- package/dist/src/stepwise/stepwise-agent-session-flow.js.map +1 -0
- package/dist/src/stepwise/stepwise-input-items.d.ts +12 -0
- package/dist/src/stepwise/stepwise-input-items.js +172 -0
- package/dist/src/stepwise/stepwise-input-items.js.map +1 -0
- package/dist/src/stepwise/tool-source.d.ts +103 -0
- package/dist/src/stepwise/tool-source.js +9 -0
- package/dist/src/stepwise/tool-source.js.map +1 -0
- package/dist/src/testing/agent-session-test-client.d.ts +65 -8
- package/dist/src/testing/agent-session-test-client.js +92 -22
- package/dist/src/testing/agent-session-test-client.js.map +1 -1
- package/dist/src/testing/context-window.d.ts +194 -0
- package/dist/src/testing/context-window.js +360 -0
- package/dist/src/testing/context-window.js.map +1 -0
- package/dist/src/testing/index.d.ts +2 -0
- package/dist/src/testing/index.js +2 -0
- package/dist/src/testing/index.js.map +1 -1
- package/dist/src/testing/private-dex-engine.d.ts +9 -0
- package/dist/src/testing/private-dex-engine.js +9 -1
- package/dist/src/testing/private-dex-engine.js.map +1 -1
- package/dist/src/testing/scripted-model-client.d.ts +1 -0
- package/dist/src/testing/scripted-model-client.js +10 -0
- package/dist/src/testing/scripted-model-client.js.map +1 -0
- package/dist/src/ui-stream/agent-event-json.d.ts +30 -0
- package/dist/src/ui-stream/agent-event-json.js +64 -0
- package/dist/src/ui-stream/agent-event-json.js.map +1 -0
- package/dist/src/ui-stream/agent-event-sse.d.ts +155 -0
- package/dist/src/ui-stream/agent-event-sse.js +167 -0
- package/dist/src/ui-stream/agent-event-sse.js.map +1 -0
- package/dist/src/ui-stream/agent-event-stream-positions.d.ts +42 -0
- package/dist/src/ui-stream/agent-event-stream-positions.js +153 -0
- package/dist/src/ui-stream/agent-event-stream-positions.js.map +1 -0
- package/dist/src/ui-stream/agent-session-record-reader.d.ts +74 -0
- package/dist/src/ui-stream/agent-session-record-reader.js +246 -0
- package/dist/src/ui-stream/agent-session-record-reader.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-message-stream-responses.d.ts +219 -0
- package/dist/src/ui-stream/agent-ui-message-stream-responses.js +441 -0
- package/dist/src/ui-stream/agent-ui-message-stream-responses.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-message-stream.d.ts +138 -0
- package/dist/src/ui-stream/agent-ui-message-stream.js +695 -0
- package/dist/src/ui-stream/agent-ui-message-stream.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-message-types.d.ts +238 -0
- package/dist/src/ui-stream/agent-ui-message-types.js +57 -0
- package/dist/src/ui-stream/agent-ui-message-types.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-messages.d.ts +68 -0
- package/dist/src/ui-stream/agent-ui-messages.js +222 -0
- package/dist/src/ui-stream/agent-ui-messages.js.map +1 -0
- package/dist/src/ui-stream/agent-ui-stream-cursor.d.ts +64 -0
- package/dist/src/ui-stream/agent-ui-stream-cursor.js +186 -0
- package/dist/src/ui-stream/agent-ui-stream-cursor.js.map +1 -0
- package/dist/src/ui-stream/index.d.ts +14 -0
- package/dist/src/ui-stream/index.js +22 -0
- package/dist/src/ui-stream/index.js.map +1 -0
- package/dist/src/ui-stream/server-sent-event-responses.d.ts +6 -0
- package/dist/src/ui-stream/server-sent-event-responses.js +34 -0
- package/dist/src/ui-stream/server-sent-event-responses.js.map +1 -0
- package/package.json +44 -5
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import { type CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import { type AgentEventWriter, type AgentTurnContext, type DeferredToolCall, type DeferredToolExecution, type McpToolAnnotations, type ToolExecutionResult, type ToolPolicy, type ToolTaskCancellation, type ToolTaskPoll, type ToolTaskPollOutcome, type ToolTaskStarted } from "../agent-framework-runner.js";
|
|
3
|
+
import type { ToolEffect } from "../agent-session-values.js";
|
|
4
|
+
import type { SourceToolDefinition } from "../stepwise/tool-source.js";
|
|
5
|
+
import { type McpServerConfig } from "./mcp-server-config.js";
|
|
6
|
+
/** `_meta` key that carries the session's idempotency key on every `tools/call`. */
|
|
7
|
+
export declare const mcpIdempotencyKeyMetaKey = "io.superdurable.dex/idempotencyKey";
|
|
8
|
+
/** `AgentEvents` type for an MCP `notifications/progress` of a running tool call. */
|
|
9
|
+
export declare const mcpToolProgressEventType = "mcp.tool_progress";
|
|
10
|
+
/** `AgentEvents` type for each observed status of an MCP task. */
|
|
11
|
+
export declare const mcpTaskStatusEventType = "mcp.task_status";
|
|
12
|
+
/** Default bound on one MCP `tools/call` or task request, in milliseconds: 10 minutes. */
|
|
13
|
+
export declare const defaultMcpRequestTimeoutMs = 600000;
|
|
14
|
+
/** Default bound on polling one MCP task inside one tool Step attempt, in milliseconds: 10 minutes. */
|
|
15
|
+
export declare const defaultMcpTaskWaitTimeoutMs = 600000;
|
|
16
|
+
/** Default TTL the source requests for a task that `PollToolTask` polls, in milliseconds: 24 hours. */
|
|
17
|
+
export declare const defaultMcpTaskTtlMs = 86400000;
|
|
18
|
+
/** Default bound on connecting, the `initialize` handshake, and `tools/list`, in milliseconds: 30 seconds. */
|
|
19
|
+
export declare const defaultMcpConnectionTimeoutMs = 30000;
|
|
20
|
+
/** Default number of connection attempts before a request reports the server unreachable. */
|
|
21
|
+
export declare const defaultMcpConnectionAttempts = 3;
|
|
22
|
+
/** Default {@link McpToolSourceOptions.sourceName}, which stored Stepwise calls are routed by. */
|
|
23
|
+
export declare const defaultMcpSourceName = "mcp";
|
|
24
|
+
/** Default age in milliseconds after which `listTools` lists a server again, in the background: 5 minutes. */
|
|
25
|
+
export declare const defaultMcpListingTtlMs = 300000;
|
|
26
|
+
/** Default wait in milliseconds after a failed listing before `listTools` tries that server again: 30 seconds. */
|
|
27
|
+
export declare const defaultMcpListingFailureBackoffMs = 30000;
|
|
28
|
+
/** Handler that runs one deferred tool call, as {@link McpToolSource.executeDeferredToolCall} does. */
|
|
29
|
+
export type DeferredToolHandler = (call: DeferredToolExecution) => Promise<ToolExecutionResult | ToolTaskStarted>;
|
|
30
|
+
/** One MCP tool described as an agent tool definition, returned by {@link McpToolSource.listTools}. */
|
|
31
|
+
export interface McpTool {
|
|
32
|
+
/**
|
|
33
|
+
* Agent tool name, `<serverName>__<mcpToolName>`. Characters other than letters, digits, `_`, and
|
|
34
|
+
* `-` become `_`. A name longer than 64 characters is cut to 55 and ends with `_` and 8 hex digits
|
|
35
|
+
* of its SHA-256. Key {@link ToolPolicy} entries by this name. The resource and prompt tools have the fixed
|
|
36
|
+
* names `mcp_list_resources_and_prompts`, `mcp_read_resource`, and `mcp_get_prompt`.
|
|
37
|
+
*/
|
|
38
|
+
readonly name: string;
|
|
39
|
+
/**
|
|
40
|
+
* Name of the configured server that offers the tool, or `""` for a resource and prompt tool, which takes the
|
|
41
|
+
* server as its `server` argument.
|
|
42
|
+
*/
|
|
43
|
+
readonly serverName: string;
|
|
44
|
+
/** The tool's name on its MCP server, or `""` for a resource and prompt tool. */
|
|
45
|
+
readonly mcpToolName: string;
|
|
46
|
+
/** Tool description for the model. */
|
|
47
|
+
readonly description: string;
|
|
48
|
+
/** JSON Schema of the tool's arguments object. */
|
|
49
|
+
readonly inputSchema: Readonly<Record<string, unknown>>;
|
|
50
|
+
/** The server's behavior hints, or `undefined` when it sent none. */
|
|
51
|
+
readonly annotations: McpToolAnnotations | undefined;
|
|
52
|
+
/**
|
|
53
|
+
* Effect from {@link toolEffectFromMcpToolAnnotations} when the server configuration trusts the
|
|
54
|
+
* annotations, else `undefined`. An explicit {@link ToolPolicy} overrides it.
|
|
55
|
+
*/
|
|
56
|
+
readonly frameworkEffect: ToolEffect | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* The tool's MCP `execution.taskSupport`. A `required` tool is called as a task; see
|
|
59
|
+
* {@link McpToolSource} for who polls it.
|
|
60
|
+
*/
|
|
61
|
+
readonly taskSupport: "required" | "optional" | "forbidden" | undefined;
|
|
62
|
+
}
|
|
63
|
+
/** Options of {@link McpToolSource}. */
|
|
64
|
+
export interface McpToolSourceOptions {
|
|
65
|
+
/**
|
|
66
|
+
* Bound on one `tools/call` or task request in milliseconds. A `tools/call` that times out throws
|
|
67
|
+
* {@link McpToolCallInterruptedError}. Defaults to {@link defaultMcpRequestTimeoutMs}.
|
|
68
|
+
*/
|
|
69
|
+
readonly requestTimeoutMs?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Bound on polling one MCP task inside one tool Step attempt, in milliseconds: a stdio server's task, a
|
|
72
|
+
* task of a server that keeps protocol sessions, and any task that {@link McpToolSource.callTool}
|
|
73
|
+
* polls. When it passes, the source throws {@link McpToolCallInterruptedError} and leaves the task
|
|
74
|
+
* running; a retried attempt resumes polling it. The source requests such a task's TTL as four times
|
|
75
|
+
* this bound, so the task outlives every attempt. Defaults to {@link defaultMcpTaskWaitTimeoutMs}.
|
|
76
|
+
*/
|
|
77
|
+
readonly taskWaitTimeoutMs?: number;
|
|
78
|
+
/**
|
|
79
|
+
* TTL the source requests for a task that `PollToolTask` polls, in milliseconds. The server keeps the
|
|
80
|
+
* task and its result for this long after it creates the task, and it may grant less. `PollToolTask`
|
|
81
|
+
* polls on Timers that outlive Worker restarts, so the TTL must cover the task's run time plus the
|
|
82
|
+
* longest time no Worker serves the session; a task whose TTL passes first is lost, and the call is
|
|
83
|
+
* recorded by its effect. Defaults to {@link defaultMcpTaskTtlMs}, 24 hours.
|
|
84
|
+
*/
|
|
85
|
+
readonly taskTtlMs?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Bound on connecting, the `initialize` handshake, and each `tools/list` request, in milliseconds.
|
|
88
|
+
* Defaults to {@link defaultMcpConnectionTimeoutMs}.
|
|
89
|
+
*/
|
|
90
|
+
readonly connectionTimeoutMs?: number;
|
|
91
|
+
/** Connection attempts per request. Defaults to {@link defaultMcpConnectionAttempts}. */
|
|
92
|
+
readonly connectionAttempts?: number;
|
|
93
|
+
/** `clientInfo.name` sent to the servers. Defaults to `dex-agents`. */
|
|
94
|
+
readonly clientName?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Whether {@link McpToolSource.listTools} also offers `mcp_list_resources_and_prompts`, `mcp_read_resource`,
|
|
97
|
+
* and `mcp_get_prompt`, after the servers' tools, when at least one server is configured. Their requests are
|
|
98
|
+
* bounded by `connectionTimeoutMs`. Defaults to `false`. Enable it on one source of an agent only: two sources
|
|
99
|
+
* with it list the same names, which the Stepwise runner refuses. See {@link McpToolSource}.
|
|
100
|
+
*/
|
|
101
|
+
readonly resourceAndPromptToolsEnabled?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Age in milliseconds after which {@link McpToolSource.listTools} lists a server again. The refresh runs in the
|
|
104
|
+
* background, and the earlier listing is returned meanwhile. Defaults to {@link defaultMcpListingTtlMs}.
|
|
105
|
+
*/
|
|
106
|
+
readonly listingTtlMs?: number;
|
|
107
|
+
/**
|
|
108
|
+
* How long in milliseconds {@link McpToolSource.listTools} leaves a server that failed to list alone before it
|
|
109
|
+
* tries again, in the background. Defaults to {@link defaultMcpListingFailureBackoffMs}.
|
|
110
|
+
*/
|
|
111
|
+
readonly listingFailureBackoffMs?: number;
|
|
112
|
+
/**
|
|
113
|
+
* The source's stable name in a Stepwise agent's `toolSources`, which stored calls are routed by. Defaults to
|
|
114
|
+
* {@link defaultMcpSourceName}, `"mcp"`, so adding or removing a server keeps it. An agent with two `McpToolSource`
|
|
115
|
+
* instances must name at least one, because names must be unique.
|
|
116
|
+
*/
|
|
117
|
+
readonly sourceName?: string;
|
|
118
|
+
}
|
|
119
|
+
/** Per-call options of {@link McpToolSource.callTool}. */
|
|
120
|
+
export interface McpToolCallOptions {
|
|
121
|
+
/** Key sent in `_meta` under {@link mcpIdempotencyKeyMetaKey}. Defaults to none. */
|
|
122
|
+
readonly idempotencyKey?: string;
|
|
123
|
+
/** Tool call ID stamped on progress and task events. */
|
|
124
|
+
readonly toolCallId?: string;
|
|
125
|
+
/** Writer for `mcp.tool_progress` and `mcp.task_status` events. */
|
|
126
|
+
readonly events?: AgentEventWriter;
|
|
127
|
+
/** Awaited between task polls. */
|
|
128
|
+
readonly heartbeat?: () => Promise<void>;
|
|
129
|
+
/** `DeferredToolExecution.heartbeatCheckpoint`, so a retried attempt resumes the earlier attempt's task. */
|
|
130
|
+
readonly heartbeatCheckpoint?: string;
|
|
131
|
+
/** `DeferredToolExecution.saveHeartbeatCheckpoint`, so an MCP task survives a retry. */
|
|
132
|
+
readonly saveHeartbeatCheckpoint?: (checkpoint: string) => Promise<void>;
|
|
133
|
+
/** Aborts the requests, for example the tool Step's cancellation signal. */
|
|
134
|
+
readonly signal?: AbortSignal;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* A `tools/call` that reached an MCP server but returned no result.
|
|
138
|
+
*
|
|
139
|
+
* {@link McpToolSource} throws it when the connection broke, the request timed out, the server process
|
|
140
|
+
* exited, the server or a gateway answered with an internal error, an HTTP error status, or an unreadable
|
|
141
|
+
* body, or an MCP task stopped being observable. The tool may or may not have taken effect. It is not a
|
|
142
|
+
* {@link ToolExecutionError}, so the tool Step's effect decides what happens next: `CallTool` re-issues
|
|
143
|
+
* a `read` or `idempotent_write` call as a new request with the same idempotency key, and
|
|
144
|
+
* `CallSingleAttemptTool` records `outcome_unknown` for the other effects and never sends it again.
|
|
145
|
+
*/
|
|
146
|
+
export declare class McpToolCallInterruptedError extends Error {
|
|
147
|
+
readonly serverName: string;
|
|
148
|
+
readonly mcpToolName: string;
|
|
149
|
+
readonly detail: string;
|
|
150
|
+
/**
|
|
151
|
+
* Creates the error.
|
|
152
|
+
* @param serverName - Configured name of the MCP server.
|
|
153
|
+
* @param mcpToolName - The tool's name on that server.
|
|
154
|
+
* @param detail - What went wrong.
|
|
155
|
+
*/
|
|
156
|
+
constructor(serverName: string, mcpToolName: string, detail: string);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* No configured MCP server could be listed.
|
|
160
|
+
*
|
|
161
|
+
* {@link McpToolSource.listTools} leaves out a server it cannot list and logs a warning; it throws this
|
|
162
|
+
* error only when every configured server failed and none has an earlier listing. Thrown from
|
|
163
|
+
* `runModelStep`, it fails the `RunModel` attempt, which retries.
|
|
164
|
+
*/
|
|
165
|
+
export declare class McpToolListingError extends Error {
|
|
166
|
+
readonly serverName: string;
|
|
167
|
+
readonly detail: string;
|
|
168
|
+
/**
|
|
169
|
+
* Creates the error.
|
|
170
|
+
* @param serverName - Configured name of the last MCP server that failed.
|
|
171
|
+
* @param detail - What went wrong with that server.
|
|
172
|
+
*/
|
|
173
|
+
constructor(serverName: string, detail: string);
|
|
174
|
+
}
|
|
175
|
+
declare const nodeInspectSymbol: unique symbol;
|
|
176
|
+
/**
|
|
177
|
+
* Offers the tools of configured MCP servers to an agent, one Dex Step per call.
|
|
178
|
+
*
|
|
179
|
+
* Configure the servers on the Worker, never from Flow input, a user message, or a browser.
|
|
180
|
+
* {@link listTools} lists each server's tools and caches them per server as {@link McpTool} definitions
|
|
181
|
+
* that a runner offers to the model. When the model calls one, the runner returns
|
|
182
|
+
* {@link deferredToolCall}, so the session runs the call in its own tool Step, and the Step calls
|
|
183
|
+
* {@link executeDeferredToolCall}. No MCP call runs inside `RunModel`. {@link deferredToolCall} stores
|
|
184
|
+
* the server and the tool's MCP name on the call's record, so the tool Step calls that server directly,
|
|
185
|
+
* whatever the other servers do.
|
|
186
|
+
*
|
|
187
|
+
* Each tool's effect comes from its annotations through {@link toolEffectFromMcpToolAnnotations}:
|
|
188
|
+
* `readOnlyHint` makes it `read`, and `idempotentHint` makes it `idempotent_write`. Any other tool gets
|
|
189
|
+
* the session's `defaultToolEffect`, `unclassified` by default. Annotations are trusted by default. A
|
|
190
|
+
* {@link ToolPolicy} in `AgentSessionOptions.toolPolicies` keyed by {@link McpTool.name} wins.
|
|
191
|
+
*
|
|
192
|
+
* The source uses `@modelcontextprotocol/sdk` 1.x, which speaks MCP up to 2025-11-25: every request
|
|
193
|
+
* opens a new connection, performs the `initialize` handshake, ends the HTTP protocol session, and
|
|
194
|
+
* closes it, so no protocol session outlives a request. Every `tools/call` carries the session's
|
|
195
|
+
* idempotency key in `_meta` under {@link mcpIdempotencyKeyMetaKey}.
|
|
196
|
+
*
|
|
197
|
+
* Results map onto the session contract:
|
|
198
|
+
* - A result becomes the tool output: text blocks joined with newlines, other blocks and structured
|
|
199
|
+
* content as JSON.
|
|
200
|
+
* - An `isError` result, a JSON-RPC error response other than an internal error, and a failed,
|
|
201
|
+
* cancelled, or `input_required` task throw {@link ToolExecutionError}, so the session records
|
|
202
|
+
* `failed` and the model sees the text. The 2025-11-25 tasks deliver input requests as server requests
|
|
203
|
+
* that must be answered on a live connection, so no durable question can carry them; the source cancels
|
|
204
|
+
* an `input_required` task.
|
|
205
|
+
* - No result after the request was sent throws {@link McpToolCallInterruptedError}; the tool Step's
|
|
206
|
+
* effect decides whether it is re-issued.
|
|
207
|
+
* - A call that was never sent, because its server is not configured or cannot be reached, throws
|
|
208
|
+
* {@link ToolExecutionError}.
|
|
209
|
+
* - A tool whose `execution.taskSupport` is `required` is called as a task. A Streamable HTTP server
|
|
210
|
+
* without protocol sessions gets {@link ToolTaskStarted}: the tool Step ends, and `PollToolTask` calls
|
|
211
|
+
* {@link pollToolTask} on a Timer, so no Step or connection is held while the task runs. The source
|
|
212
|
+
* requests a TTL of `taskTtlMs` for such a task. `cancel_turn` abandons the task, and
|
|
213
|
+
* {@link cancelToolTask} sends `tasks/cancel`.
|
|
214
|
+
* - A stdio server's task lives in its process, and a server that keeps protocol sessions, as the SDK's
|
|
215
|
+
* task store does, binds its tasks to the session, which ends with the request. The tool Step polls
|
|
216
|
+
* such a task with `tasks/get`, with a heartbeat per poll, for at most `taskWaitTimeoutMs` per attempt.
|
|
217
|
+
* A retried attempt of a stateful server's call cannot see the task from its new session, so it calls
|
|
218
|
+
* the tool again.
|
|
219
|
+
* - For a Streamable HTTP server the task ID is saved as the attempt's heartbeat checkpoint before
|
|
220
|
+
* anything else, so once that checkpoint reaches Dex, a retried attempt resumes the same task instead of
|
|
221
|
+
* calling again. Dex may drop a heartbeat checkpoint; the idempotency key lets the server drop the
|
|
222
|
+
* duplicate then.
|
|
223
|
+
* - Without `DeferredToolExecution.supportsToolTasks`, for a runner without `pollToolTask`, the tool Step
|
|
224
|
+
* polls every task itself, as {@link callTool} does.
|
|
225
|
+
*
|
|
226
|
+
* With `resourceAndPromptToolsEnabled`, the listing also offers three `read` tools for the servers' resources
|
|
227
|
+
* and prompts: `mcp_list_resources_and_prompts` lists a server's resources, resource templates, and prompts;
|
|
228
|
+
* `mcp_read_resource` reads one resource by URI; and `mcp_get_prompt` gets one prompt with its arguments. Each
|
|
229
|
+
* takes the configured server's name as its `server` argument and opens a new connection to that server with
|
|
230
|
+
* the same transport and headers as a tool call. Its output is the server's answer as JSON with sorted keys:
|
|
231
|
+
* `{"resources", "resource_templates", "prompts"}`, `{"contents"}`, or `{"messages", "description"}`. A server
|
|
232
|
+
* that does not offer resources or prompts lists none of them. An MCP error answer throws
|
|
233
|
+
* {@link ToolExecutionError}. The names, descriptions, and argument schemas match the Python core. Both cores
|
|
234
|
+
* support every resource and prompt request that `@modelcontextprotocol/sdk` 1.32.2 supports; this core does
|
|
235
|
+
* not follow `notifications/resources/list_changed` or subscribe to resources, and neither does Python.
|
|
236
|
+
*
|
|
237
|
+
* Share one source between the parallel tool Steps of a Worker; build it once at startup.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* ```ts
|
|
241
|
+
* const tools = new McpToolSource([
|
|
242
|
+
* { transport: "stdio", name: "files", command: "mcp-server-files" },
|
|
243
|
+
* { transport: "streamable_http", name: "tickets", url: ticketsUrl },
|
|
244
|
+
* ]);
|
|
245
|
+
* class MyRunner implements AgentFrameworkRunner {
|
|
246
|
+
* // buildUserMessage omitted
|
|
247
|
+
* public async runModelStep(turn: AgentTurnContext): Promise<AgentTurnOutcome> {
|
|
248
|
+
* const offered = await tools.listTools(); // name, description, inputSchema
|
|
249
|
+
* const response = await callMyModel(turn.messages, offered);
|
|
250
|
+
* return {
|
|
251
|
+
* kind: "tool_calls_requested",
|
|
252
|
+
* frameworkRunState: JSON.stringify(response),
|
|
253
|
+
* usage: response.usage,
|
|
254
|
+
* toolCalls: response.toolCalls.map((call) =>
|
|
255
|
+
* tools.deferredToolCall(turn, { toolCallId: call.id, toolName: call.name, arguments: call.arguments })),
|
|
256
|
+
* };
|
|
257
|
+
* }
|
|
258
|
+
* public executeDeferredToolCall(call: DeferredToolExecution): Promise<ToolExecutionResult | ToolTaskStarted> {
|
|
259
|
+
* return tools.executeDeferredToolCall(call);
|
|
260
|
+
* }
|
|
261
|
+
* public pollToolTask(poll: ToolTaskPoll): Promise<ToolTaskPollOutcome> {
|
|
262
|
+
* return tools.pollToolTask(poll);
|
|
263
|
+
* }
|
|
264
|
+
* public cancelToolTask(cancellation: ToolTaskCancellation): Promise<void> {
|
|
265
|
+
* return tools.cancelToolTask(cancellation);
|
|
266
|
+
* }
|
|
267
|
+
* }
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
export declare class McpToolSource {
|
|
271
|
+
private readonly servers;
|
|
272
|
+
private readonly requestTimeoutMs;
|
|
273
|
+
private readonly taskWaitTimeoutMs;
|
|
274
|
+
private readonly taskTtlMs;
|
|
275
|
+
private readonly connectionTimeoutMs;
|
|
276
|
+
private readonly connectionAttempts;
|
|
277
|
+
private readonly connector;
|
|
278
|
+
private readonly listings;
|
|
279
|
+
private readonly listingTtlMs;
|
|
280
|
+
private readonly listingFailureBackoffMs;
|
|
281
|
+
private readonly configuredSourceName;
|
|
282
|
+
private tools;
|
|
283
|
+
private readonly resourceAndPromptTools;
|
|
284
|
+
/**
|
|
285
|
+
* Describes the servers without connecting to them.
|
|
286
|
+
* @param servers - Server configurations with unique names.
|
|
287
|
+
* @param options - Timeouts, connection attempts, and client name.
|
|
288
|
+
* @throws {TypeError} When a configuration is invalid, server names repeat, a timeout, `taskTtlMs`,
|
|
289
|
+
* `listingTtlMs`, or `listingFailureBackoffMs` is not positive, or `connectionAttempts` is less than 1.
|
|
290
|
+
*/
|
|
291
|
+
constructor(servers: readonly McpServerConfig[], options?: McpToolSourceOptions);
|
|
292
|
+
/**
|
|
293
|
+
* Returns the tools of every reachable configured server.
|
|
294
|
+
*
|
|
295
|
+
* Each server is listed on its own and cached per Worker process. The first listing of a server is awaited.
|
|
296
|
+
* After that, a listing older than `listingTtlMs` is refreshed in the background while the earlier one is
|
|
297
|
+
* returned. A server that cannot be listed is left out with a warning and is not tried again until
|
|
298
|
+
* `listingFailureBackoffMs` has passed; then it is listed in the background. One listing per server runs at a
|
|
299
|
+
* time, however many sessions call this. `refresh: true` lists every server again now and waits for it. When two
|
|
300
|
+
* tools map to the same agent tool name, the first in server order wins and the other is left out with a
|
|
301
|
+
* warning. Call it from `runModelStep` to offer the tools, or at Worker startup to warm the cache.
|
|
302
|
+
* @param options - `refresh: true` lists every server again now, ignoring the cache and the failure backoff.
|
|
303
|
+
* @returns Every offered tool, in server order and then in each server's order, then the resource and prompt
|
|
304
|
+
* tools when enabled.
|
|
305
|
+
* @throws {McpToolListingError} When servers are configured and none has a listing, because every one failed.
|
|
306
|
+
*/
|
|
307
|
+
listTools(options?: {
|
|
308
|
+
readonly refresh?: boolean;
|
|
309
|
+
}): Promise<readonly McpTool[]>;
|
|
310
|
+
/**
|
|
311
|
+
* The name a Stepwise agent's `toolSources` routes stored calls by: `sourceName` as passed, or
|
|
312
|
+
* {@link defaultMcpSourceName}, `"mcp"`.
|
|
313
|
+
*/
|
|
314
|
+
get sourceName(): string;
|
|
315
|
+
/**
|
|
316
|
+
* Shows the source in `console.log` and `util.inspect` output without secrets.
|
|
317
|
+
* @param depth - Remaining inspection depth.
|
|
318
|
+
* @param options - Node's inspection options.
|
|
319
|
+
* @param inspect - Node's `util.inspect`.
|
|
320
|
+
* @returns The source name and the server configurations, with environment and header values replaced by `***`.
|
|
321
|
+
*/
|
|
322
|
+
[nodeInspectSymbol](depth: number, options: {
|
|
323
|
+
readonly depth?: number | null;
|
|
324
|
+
}, inspect: (value: unknown, options: object) => string): string;
|
|
325
|
+
/**
|
|
326
|
+
* Returns the tools of the last listings without listing, for estimates.
|
|
327
|
+
* @returns The cached tools, as {@link listTools} would return them, or none before any listing finished.
|
|
328
|
+
*/
|
|
329
|
+
cachedTools(): readonly McpTool[];
|
|
330
|
+
/**
|
|
331
|
+
* Returns the tool names this source lists whatever its servers offer, so the Stepwise runner refuses a name
|
|
332
|
+
* collision when it is constructed instead of on every model call.
|
|
333
|
+
* @returns The resource and prompt tool names when they are enabled, else none.
|
|
334
|
+
*/
|
|
335
|
+
declaredToolNames(): ReadonlySet<string>;
|
|
336
|
+
/**
|
|
337
|
+
* Returns one listed tool by its agent tool name.
|
|
338
|
+
* @param toolName - {@link McpTool.name}.
|
|
339
|
+
* @returns The cached definition.
|
|
340
|
+
* @throws {RangeError} When {@link listTools} has not run or no listed server offers the tool.
|
|
341
|
+
*/
|
|
342
|
+
tool(toolName: string): McpTool;
|
|
343
|
+
/**
|
|
344
|
+
* Returns a {@link ToolPolicy} for every listed tool whose annotations declare an effect.
|
|
345
|
+
*
|
|
346
|
+
* Use it with a framework adapter that offers the MCP tools as its own tools: pass it in the
|
|
347
|
+
* adapter's `toolPolicies` and spread your own policies after it, so yours win.
|
|
348
|
+
* @example
|
|
349
|
+
* ```ts
|
|
350
|
+
* await tools.listTools();
|
|
351
|
+
* const toolPolicies = { ...tools.toolPolicies(), files__delete: { effect: "non_idempotent_write" } };
|
|
352
|
+
* ```
|
|
353
|
+
* @returns Policies by {@link McpTool.name}, with the effect's default approval.
|
|
354
|
+
* @throws {RangeError} When {@link listTools} has not run.
|
|
355
|
+
*/
|
|
356
|
+
toolPolicies(): Record<string, ToolPolicy>;
|
|
357
|
+
/**
|
|
358
|
+
* Builds the {@link DeferredToolCall} for one model call of a listed MCP tool.
|
|
359
|
+
*
|
|
360
|
+
* The policy comes from `turn.resolveToolPolicy` with the tool's annotation effect, so an explicit
|
|
361
|
+
* {@link ToolPolicy} wins. The call's `toolSourceReference` names the server, the tool's MCP name, and
|
|
362
|
+
* its task support.
|
|
363
|
+
* @param turn - The `RunModel` context.
|
|
364
|
+
* @param call - Framework tool call ID, the {@link McpTool.name} the model called, the arguments as JSON
|
|
365
|
+
* text, and optionally `listedTool`, the {@link McpTool} the listing offered for this model call, as the
|
|
366
|
+
* Stepwise runner passes it, so a refresh that finished meanwhile cannot change or remove it. Without it, the
|
|
367
|
+
* tool is looked up in the current listing.
|
|
368
|
+
* @returns The call to put in `ToolCallsRequested.toolCalls`.
|
|
369
|
+
* @throws {RangeError} When no `listedTool` is given and {@link listTools} has not run or the tool is unknown.
|
|
370
|
+
*/
|
|
371
|
+
deferredToolCall(turn: AgentTurnContext, call: {
|
|
372
|
+
readonly toolCallId: string;
|
|
373
|
+
readonly toolName: string;
|
|
374
|
+
readonly arguments: string;
|
|
375
|
+
readonly listedTool?: SourceToolDefinition;
|
|
376
|
+
}): DeferredToolCall;
|
|
377
|
+
/**
|
|
378
|
+
* Returns one deferred-call handler per listed MCP tool, keyed by agent tool name.
|
|
379
|
+
*
|
|
380
|
+
* Merge them with a runner's own handlers and dispatch `executeDeferredToolCall` by
|
|
381
|
+
* `call.toolCall.toolName`. Build the map inside `executeDeferredToolCall`, not once at construction:
|
|
382
|
+
* a replacement Worker runs tool Steps before any `RunModel`.
|
|
383
|
+
* @example
|
|
384
|
+
* ```ts
|
|
385
|
+
* public async executeDeferredToolCall(call: DeferredToolExecution): Promise<ToolExecutionResult> {
|
|
386
|
+
* const handlers = { ...this.localHandlers, ...(await tools.deferredToolHandlers()) };
|
|
387
|
+
* return handlers[call.toolCall.toolName]!(call);
|
|
388
|
+
* }
|
|
389
|
+
* ```
|
|
390
|
+
* @returns Handlers that each call {@link executeDeferredToolCall}.
|
|
391
|
+
* @throws {McpToolListingError} When no server could be listed.
|
|
392
|
+
*/
|
|
393
|
+
deferredToolHandlers(): Promise<Record<string, DeferredToolHandler>>;
|
|
394
|
+
/**
|
|
395
|
+
* Runs one deferred MCP tool call in its tool Step.
|
|
396
|
+
*
|
|
397
|
+
* Call it from `AgentFrameworkRunner.executeDeferredToolCall`, and implement
|
|
398
|
+
* `AgentFrameworkRunner.pollToolTask` with {@link pollToolTask}. A call built by {@link deferredToolCall}
|
|
399
|
+
* goes straight to the server named on its record, without a listing. It passes the call's idempotency
|
|
400
|
+
* key, events, heartbeat, heartbeat checkpoint, and cancellation signal on.
|
|
401
|
+
*
|
|
402
|
+
* A Streamable HTTP server without protocol sessions that answers with a task gets {@link ToolTaskStarted}.
|
|
403
|
+
* The source saves the task ID as the heartbeat checkpoint first; a retried attempt that reads it returns
|
|
404
|
+
* the same task without calling the tool again.
|
|
405
|
+
* @param call - The approved call from the tool Step.
|
|
406
|
+
* @returns The tool output the model sees, or {@link ToolTaskStarted} for a task that `PollToolTask` polls.
|
|
407
|
+
* @throws {ToolExecutionError} When the arguments are not a JSON object, the tool failed, the server
|
|
408
|
+
* answered with an error or asked for input, or the call was never sent.
|
|
409
|
+
* @throws {McpToolCallInterruptedError} When the call was sent and no result came back.
|
|
410
|
+
*/
|
|
411
|
+
executeDeferredToolCall(call: DeferredToolExecution): Promise<ToolExecutionResult | ToolTaskStarted>;
|
|
412
|
+
/**
|
|
413
|
+
* Polls one MCP task that {@link executeDeferredToolCall} started, once.
|
|
414
|
+
*
|
|
415
|
+
* Call it from `AgentFrameworkRunner.pollToolTask`. It reads the task with `tasks/get` and writes an
|
|
416
|
+
* `mcp.task_status` event when the status changed. A completed task's result comes from `tasks/result`. A task in
|
|
417
|
+
* `input_required` is cancelled and fails, because its input requests need a live connection.
|
|
418
|
+
* @param poll - The call's record from `PollToolTask`.
|
|
419
|
+
* @returns The tool output, or `tool_task_pending` with the next poll interval, which backs off from the
|
|
420
|
+
* server's `pollInterval` to at most a minute.
|
|
421
|
+
* @throws {ToolExecutionError} When the task failed, was cancelled, returned an `isError` result, or asked
|
|
422
|
+
* for input.
|
|
423
|
+
* @throws {McpToolCallInterruptedError} When the server could not be reached, no longer knows the task, or
|
|
424
|
+
* answered a poll with an error. The task may still run, so `PollToolTask` retries and then records the
|
|
425
|
+
* call by its effect.
|
|
426
|
+
*/
|
|
427
|
+
pollToolTask(poll: ToolTaskPoll): Promise<ToolTaskPollOutcome>;
|
|
428
|
+
/**
|
|
429
|
+
* Sends `tasks/cancel` for one MCP task that `cancel_turn` abandoned.
|
|
430
|
+
*
|
|
431
|
+
* Call it from `AgentFrameworkRunner.cancelToolTask`. Cancellation is best-effort: the server may finish the
|
|
432
|
+
* task anyway, and the session drops a result that arrives later. Any answer from the server ends the
|
|
433
|
+
* cancellation, including an error for a task that already finished or that the server no longer knows, so a
|
|
434
|
+
* repeated call is harmless.
|
|
435
|
+
* @param cancellation - The abandoned call's record from `CancelToolTask`.
|
|
436
|
+
* @returns A Promise that resolves once the server answered.
|
|
437
|
+
* @throws {McpToolCallInterruptedError} When the server could not be reached or did not answer;
|
|
438
|
+
* `CancelToolTask` retries, then records the call `outcome_unknown` anyway.
|
|
439
|
+
*/
|
|
440
|
+
cancelToolTask(cancellation: ToolTaskCancellation): Promise<void>;
|
|
441
|
+
/**
|
|
442
|
+
* Calls one listed MCP tool once, as a tool Step does.
|
|
443
|
+
*
|
|
444
|
+
* Use it from a framework tool that wraps an MCP tool, when the adapter gives the tool only the
|
|
445
|
+
* idempotency key. It finds the tool's server through the per-server listing. Call it only inside a
|
|
446
|
+
* tool Step: the session's retry rules for the effect assume it.
|
|
447
|
+
* @param toolName - {@link McpTool.name}.
|
|
448
|
+
* @param toolArguments - Tool arguments.
|
|
449
|
+
* @param options - Idempotency key, events, heartbeat, checkpoints, and abort signal.
|
|
450
|
+
* @returns The tool output the model sees. A task is polled inside the call, for at most
|
|
451
|
+
* `taskWaitTimeoutMs`.
|
|
452
|
+
* @throws {ToolExecutionError} When the tool failed, the server answered with an error or asked for
|
|
453
|
+
* input, or the call was never sent.
|
|
454
|
+
* @throws {McpToolCallInterruptedError} When the call was sent and no result came back.
|
|
455
|
+
*/
|
|
456
|
+
callTool(toolName: string, toolArguments: Readonly<Record<string, unknown>>, options?: McpToolCallOptions): Promise<ToolExecutionResult>;
|
|
457
|
+
private isResourceAndPromptTool;
|
|
458
|
+
private runResourceAndPromptTool;
|
|
459
|
+
private callLimits;
|
|
460
|
+
private resolveTarget;
|
|
461
|
+
private callTarget;
|
|
462
|
+
private targetFromReference;
|
|
463
|
+
private targetFromListing;
|
|
464
|
+
private refreshListing;
|
|
465
|
+
private combineServerTools;
|
|
466
|
+
private listServerTools;
|
|
467
|
+
}
|
|
468
|
+
/** Joins text blocks; other content blocks and structured content render as `serializeToolOutputJson` text. */
|
|
469
|
+
export declare function renderToolResultText(result: CallToolResult): string;
|
|
470
|
+
export {};
|