@superdurable/dex-agents 0.0.0-stage → 0.2.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/LICENSE +105 -0
- package/README.md +1981 -2
- 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 +108 -0
- package/dist/src/agent-context-compaction.js +39 -0
- package/dist/src/agent-context-compaction.js.map +1 -0
- package/dist/src/agent-event-writer.d.ts +26 -0
- package/dist/src/agent-event-writer.js +110 -0
- package/dist/src/agent-event-writer.js.map +1 -0
- package/dist/src/agent-framework-runner.d.ts +808 -0
- package/dist/src/agent-framework-runner.js +82 -0
- package/dist/src/agent-framework-runner.js.map +1 -0
- 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 +105 -0
- package/dist/src/agent-session-codecs.js +689 -0
- package/dist/src/agent-session-codecs.js.map +1 -0
- package/dist/src/agent-session-flow.d.ts +416 -0
- package/dist/src/agent-session-flow.js +623 -0
- package/dist/src/agent-session-flow.js.map +1 -0
- package/dist/src/agent-session-persistence.d.ts +133 -0
- package/dist/src/agent-session-persistence.js +74 -0
- package/dist/src/agent-session-persistence.js.map +1 -0
- 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-step-options.d.ts +27 -0
- package/dist/src/agent-session-step-options.js +39 -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 +179 -0
- package/dist/src/agent-session-steps.js +1272 -0
- package/dist/src/agent-session-steps.js.map +1 -0
- 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 +224 -0
- package/dist/src/agent-session-transitions.js +850 -0
- package/dist/src/agent-session-transitions.js.map +1 -0
- package/dist/src/agent-session-values.d.ts +998 -0
- package/dist/src/agent-session-values.js +162 -0
- package/dist/src/agent-session-values.js.map +1 -0
- 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 +10 -0
- package/dist/src/index.js +17 -0
- package/dist/src/index.js.map +1 -0
- 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 +158 -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 +7 -0
- package/dist/src/stepwise/index.js +12 -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 +189 -0
- package/dist/src/stepwise/stepwise-agent-runner.js +804 -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 +56 -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 +205 -0
- package/dist/src/testing/agent-session-test-client.js +290 -0
- package/dist/src/testing/agent-session-test-client.js.map +1 -0
- package/dist/src/testing/agent-test-environment.d.ts +52 -0
- package/dist/src/testing/agent-test-environment.js +86 -0
- package/dist/src/testing/agent-test-environment.js.map +1 -0
- package/dist/src/testing/agent-worker-process.d.ts +91 -0
- package/dist/src/testing/agent-worker-process.js +150 -0
- package/dist/src/testing/agent-worker-process.js.map +1 -0
- package/dist/src/testing/child-process-group.d.ts +33 -0
- package/dist/src/testing/child-process-group.js +164 -0
- package/dist/src/testing/child-process-group.js.map +1 -0
- package/dist/src/testing/coordination.d.ts +99 -0
- package/dist/src/testing/coordination.js +155 -0
- package/dist/src/testing/coordination.js.map +1 -0
- package/dist/src/testing/index.d.ts +8 -0
- package/dist/src/testing/index.js +16 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/src/testing/polling.d.ts +31 -0
- package/dist/src/testing/polling.js +51 -0
- package/dist/src/testing/polling.js.map +1 -0
- package/dist/src/testing/private-dex-engine.d.ts +101 -0
- package/dist/src/testing/private-dex-engine.js +223 -0
- package/dist/src/testing/private-dex-engine.js.map +1 -0
- 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/testing/step-history.d.ts +40 -0
- package/dist/src/testing/step-history.js +59 -0
- package/dist/src/testing/step-history.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 +154 -0
- package/dist/src/ui-stream/agent-event-sse.js +159 -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 +72 -0
- package/dist/src/ui-stream/agent-session-record-reader.js +241 -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 +440 -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 +681 -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 +66 -0
- package/dist/src/ui-stream/agent-ui-messages.js +220 -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 +86 -4
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
// Copyright (c) 2026 Super Durable, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Sustainable Use License 1.0.
|
|
4
|
+
// You may not use this file except in compliance with the License.
|
|
5
|
+
// See the LICENSE file in the repository root.
|
|
6
|
+
//
|
|
7
|
+
// SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
|
|
8
|
+
import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
import { ToolExecutionError } from "../agent-framework-runner.js";
|
|
10
|
+
/** Name of the read tool that lists a server's resources, resource templates, and prompts. */
|
|
11
|
+
export const mcpListResourcesAndPromptsToolName = "mcp_list_resources_and_prompts";
|
|
12
|
+
/** Name of the read tool that reads one resource of a server. */
|
|
13
|
+
export const mcpReadResourceToolName = "mcp_read_resource";
|
|
14
|
+
/** Name of the read tool that gets one prompt of a server. */
|
|
15
|
+
export const mcpGetPromptToolName = "mcp_get_prompt";
|
|
16
|
+
export const resourceAndPromptToolNames = new Set([
|
|
17
|
+
mcpListResourcesAndPromptsToolName,
|
|
18
|
+
mcpReadResourceToolName,
|
|
19
|
+
mcpGetPromptToolName,
|
|
20
|
+
]);
|
|
21
|
+
const listingPageLimit = 100;
|
|
22
|
+
/** Returns the three read tools; the `server` argument names one of `serverNames`. */
|
|
23
|
+
export function buildResourceAndPromptToolDefinitions(serverNames) {
|
|
24
|
+
const server = { type: "string", enum: [...serverNames], description: "Name of a configured MCP server." };
|
|
25
|
+
const definitions = [
|
|
26
|
+
[
|
|
27
|
+
mcpListResourcesAndPromptsToolName,
|
|
28
|
+
"List the resources, resource templates, and prompts of a configured MCP server.",
|
|
29
|
+
{ server },
|
|
30
|
+
],
|
|
31
|
+
[
|
|
32
|
+
mcpReadResourceToolName,
|
|
33
|
+
"Read one resource of a configured MCP server by its URI.",
|
|
34
|
+
{ server, uri: { type: "string", description: "URI of the resource, as the server lists it." } },
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
mcpGetPromptToolName,
|
|
38
|
+
"Get one prompt of a configured MCP server, rendered with its arguments.",
|
|
39
|
+
{
|
|
40
|
+
server,
|
|
41
|
+
name: { type: "string", description: "Name of the prompt, as the server lists it." },
|
|
42
|
+
arguments: {
|
|
43
|
+
type: "object",
|
|
44
|
+
additionalProperties: { type: "string" },
|
|
45
|
+
description: "Prompt arguments by name. Defaults to none.",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
];
|
|
50
|
+
return definitions.map(([name, description, properties]) => ({
|
|
51
|
+
name,
|
|
52
|
+
description,
|
|
53
|
+
inputSchema: {
|
|
54
|
+
type: "object",
|
|
55
|
+
properties,
|
|
56
|
+
required: Object.keys(properties).filter((key) => key !== "arguments"),
|
|
57
|
+
additionalProperties: false,
|
|
58
|
+
},
|
|
59
|
+
}));
|
|
60
|
+
}
|
|
61
|
+
/** Returns the `server` argument, or throws the {@link ToolExecutionError} the model sees. */
|
|
62
|
+
export function readServerName(toolArguments) {
|
|
63
|
+
const serverName = toolArguments["server"];
|
|
64
|
+
if (typeof serverName !== "string") {
|
|
65
|
+
throw new ToolExecutionError("the server argument must be a string");
|
|
66
|
+
}
|
|
67
|
+
return serverName;
|
|
68
|
+
}
|
|
69
|
+
/** Sends one read tool's requests on an open connection and returns the output JSON text. */
|
|
70
|
+
export async function runResourceAndPromptTool(client, toolName, toolArguments, requestOptions) {
|
|
71
|
+
let output;
|
|
72
|
+
try {
|
|
73
|
+
if (toolName === mcpListResourcesAndPromptsToolName) {
|
|
74
|
+
output = {
|
|
75
|
+
resources: await listAll((cursor) => client.listResources(cursorParams(cursor), requestOptions), "resources"),
|
|
76
|
+
resource_templates: await listAll((cursor) => client.listResourceTemplates(cursorParams(cursor), requestOptions), "resourceTemplates"),
|
|
77
|
+
prompts: await listAll((cursor) => client.listPrompts(cursorParams(cursor), requestOptions), "prompts"),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
else if (toolName === mcpReadResourceToolName) {
|
|
81
|
+
const uri = toolArguments["uri"];
|
|
82
|
+
if (typeof uri !== "string") {
|
|
83
|
+
throw new ToolExecutionError("the uri argument must be a string");
|
|
84
|
+
}
|
|
85
|
+
const read = await client.readResource({ uri }, requestOptions);
|
|
86
|
+
output = { contents: read.contents };
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const name = toolArguments["name"];
|
|
90
|
+
if (typeof name !== "string") {
|
|
91
|
+
throw new ToolExecutionError("the name argument must be a string");
|
|
92
|
+
}
|
|
93
|
+
const promptArguments = toolArguments["arguments"];
|
|
94
|
+
if (promptArguments !== undefined &&
|
|
95
|
+
promptArguments !== null &&
|
|
96
|
+
(typeof promptArguments !== "object" ||
|
|
97
|
+
Array.isArray(promptArguments) ||
|
|
98
|
+
!Object.values(promptArguments).every((value) => typeof value === "string"))) {
|
|
99
|
+
throw new ToolExecutionError("the arguments argument must map names to strings");
|
|
100
|
+
}
|
|
101
|
+
const prompt = await client.getPrompt({
|
|
102
|
+
name,
|
|
103
|
+
...(promptArguments === undefined || promptArguments === null
|
|
104
|
+
? {}
|
|
105
|
+
: { arguments: promptArguments }),
|
|
106
|
+
}, requestOptions);
|
|
107
|
+
output = { messages: prompt.messages };
|
|
108
|
+
if (prompt.description !== undefined) {
|
|
109
|
+
output["description"] = prompt.description;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
if (error instanceof McpError) {
|
|
115
|
+
throw new ToolExecutionError(`MCP error ${error.code}: ${readMcpErrorMessage(error)}`, { cause: error });
|
|
116
|
+
}
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
return serializeToolOutputJson(output);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Serializes with sorted keys and spaced separators, as the Python core's `json.dumps(sort_keys=True)`.
|
|
123
|
+
* Keys sort by code point while the text is written, never through an object, because JavaScript objects
|
|
124
|
+
* put integer-like keys first.
|
|
125
|
+
*/
|
|
126
|
+
export function serializeToolOutputJson(value) {
|
|
127
|
+
if (Array.isArray(value)) {
|
|
128
|
+
return `[${value.map((item) => serializeToolOutputJson(item === undefined ? null : item)).join(", ")}]`;
|
|
129
|
+
}
|
|
130
|
+
if (typeof value === "object" && value !== null) {
|
|
131
|
+
const entries = Object.entries(value)
|
|
132
|
+
.filter(([, nested]) => nested !== undefined)
|
|
133
|
+
.sort(([left], [right]) => compareByCodePoint(left, right));
|
|
134
|
+
return `{${entries.map(([key, nested]) => `${JSON.stringify(key)}: ${serializeToolOutputJson(nested)}`).join(", ")}}`;
|
|
135
|
+
}
|
|
136
|
+
const text = JSON.stringify(value);
|
|
137
|
+
if (text === undefined) {
|
|
138
|
+
throw new TypeError(`a ${typeof value} value cannot be serialized as JSON`);
|
|
139
|
+
}
|
|
140
|
+
return text;
|
|
141
|
+
}
|
|
142
|
+
/** JavaScript's `<` compares UTF-16 code units, which orders characters above U+FFFF before U+E000. */
|
|
143
|
+
function compareByCodePoint(left, right) {
|
|
144
|
+
const leftCodePoints = Array.from(left, (character) => character.codePointAt(0) ?? 0);
|
|
145
|
+
const rightCodePoints = Array.from(right, (character) => character.codePointAt(0) ?? 0);
|
|
146
|
+
for (let index = 0; index < Math.min(leftCodePoints.length, rightCodePoints.length); index += 1) {
|
|
147
|
+
const difference = (leftCodePoints[index] ?? 0) - (rightCodePoints[index] ?? 0);
|
|
148
|
+
if (difference !== 0) {
|
|
149
|
+
return difference;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return leftCodePoints.length - rightCodePoints.length;
|
|
153
|
+
}
|
|
154
|
+
async function listAll(listPage, fieldName) {
|
|
155
|
+
const items = [];
|
|
156
|
+
let cursor;
|
|
157
|
+
for (let page = 0; page < listingPageLimit; page += 1) {
|
|
158
|
+
let result;
|
|
159
|
+
try {
|
|
160
|
+
result = await listPage(cursor);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (error instanceof McpError && error.code === ErrorCode.MethodNotFound) {
|
|
164
|
+
// The server does not offer this kind of item.
|
|
165
|
+
return items;
|
|
166
|
+
}
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
items.push(...result[fieldName]);
|
|
170
|
+
cursor = result.nextCursor;
|
|
171
|
+
if (cursor === undefined || cursor === "") {
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return items;
|
|
176
|
+
}
|
|
177
|
+
function cursorParams(cursor) {
|
|
178
|
+
return cursor === undefined ? {} : { cursor };
|
|
179
|
+
}
|
|
180
|
+
/** The SDK prefixes `MCP error <code>: ` to the server's message; the Python core shows the bare message. */
|
|
181
|
+
function readMcpErrorMessage(error) {
|
|
182
|
+
const prefix = `MCP error ${error.code}: `;
|
|
183
|
+
return error.message.startsWith(prefix) ? error.message.slice(prefix.length) : error.message;
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=mcp-resource-and-prompt-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-resource-and-prompt-tools.js","sourceRoot":"","sources":["../../../src/mcp/mcp-resource-and-prompt-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Launches one MCP server as a child process and talks to it over stdio.
|
|
3
|
+
*
|
|
4
|
+
* Build it from Worker configuration, never from Flow input, a user message, or a browser: the command
|
|
5
|
+
* runs with the Worker's privileges. Every request starts a new process, so a server that keeps state
|
|
6
|
+
* between calls must keep it outside the process.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* const files: McpStdioServerConfig = {
|
|
11
|
+
* transport: "stdio",
|
|
12
|
+
* name: "files",
|
|
13
|
+
* command: "npx",
|
|
14
|
+
* args: ["-y", "@modelcontextprotocol/server-filesystem", "/srv/reports"],
|
|
15
|
+
* };
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export interface McpStdioServerConfig {
|
|
19
|
+
/** Discriminator. */
|
|
20
|
+
readonly transport: "stdio";
|
|
21
|
+
/**
|
|
22
|
+
* Server name, unique within one {@link McpToolSource}. It prefixes the agent tool names, so it may
|
|
23
|
+
* contain only letters, digits, `_`, and `-`.
|
|
24
|
+
*/
|
|
25
|
+
readonly name: string;
|
|
26
|
+
/** Executable to run. */
|
|
27
|
+
readonly command: string;
|
|
28
|
+
/** Command-line arguments. Defaults to none. */
|
|
29
|
+
readonly args?: readonly string[];
|
|
30
|
+
/**
|
|
31
|
+
* Environment variables merged over the MCP SDK's default environment, which keeps only variables
|
|
32
|
+
* such as `PATH` and `HOME`. Defaults to none. An inspected {@link McpToolSource} shows the variable
|
|
33
|
+
* names with every value replaced by `***`.
|
|
34
|
+
*/
|
|
35
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
36
|
+
/** Working directory. Defaults to the Worker's. */
|
|
37
|
+
readonly cwd?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Whether the server's `readOnlyHint`, `idempotentHint`, and `destructiveHint` annotations pick a
|
|
40
|
+
* tool's effect. Defaults to `true`; set `false` for a server whose hints you do not trust, so its
|
|
41
|
+
* tools keep the session default unless a {@link ToolPolicy} names them.
|
|
42
|
+
*/
|
|
43
|
+
readonly trustsToolAnnotations?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Connects to one MCP server over the Streamable HTTP transport.
|
|
47
|
+
*
|
|
48
|
+
* Build it from Worker configuration, never from Flow input, a user message, or a browser. Read
|
|
49
|
+
* credentials such as bearer tokens from the Worker's environment or secret store and pass them in
|
|
50
|
+
* {@link headers}. Every request opens a new connection and protocol session, so a server restart
|
|
51
|
+
* between two calls is harmless.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* const tickets: McpStreamableHttpServerConfig = {
|
|
56
|
+
* transport: "streamable_http",
|
|
57
|
+
* name: "tickets",
|
|
58
|
+
* url: "https://tickets.example.com/mcp",
|
|
59
|
+
* headers: { Authorization: `Bearer ${process.env.TICKETS_TOKEN}` },
|
|
60
|
+
* };
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export interface McpStreamableHttpServerConfig {
|
|
64
|
+
/** Discriminator. */
|
|
65
|
+
readonly transport: "streamable_http";
|
|
66
|
+
/**
|
|
67
|
+
* Server name, unique within one {@link McpToolSource}. It prefixes the agent tool names, so it may
|
|
68
|
+
* contain only letters, digits, `_`, and `-`.
|
|
69
|
+
*/
|
|
70
|
+
readonly name: string;
|
|
71
|
+
/** The server's MCP endpoint, an `http` or `https` URL. */
|
|
72
|
+
readonly url: string;
|
|
73
|
+
/**
|
|
74
|
+
* HTTP headers sent with every request, such as `Authorization`. Defaults to none. An inspected
|
|
75
|
+
* {@link McpToolSource} shows the header names with every value replaced by `***`.
|
|
76
|
+
*/
|
|
77
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
78
|
+
/** Whether the server's annotations pick a tool's effect. Defaults to `true`. */
|
|
79
|
+
readonly trustsToolAnnotations?: boolean;
|
|
80
|
+
}
|
|
81
|
+
/** One MCP server configuration: stdio or Streamable HTTP. */
|
|
82
|
+
export type McpServerConfig = McpStdioServerConfig | McpStreamableHttpServerConfig;
|
|
83
|
+
/** Returns a copy whose environment and header values are `***`, safe to print or log. */
|
|
84
|
+
export declare function redactMcpServerConfigSecrets(server: McpServerConfig): McpServerConfig;
|
|
85
|
+
/** Throws a `TypeError` for an invalid configuration. */
|
|
86
|
+
export declare function validateMcpServerConfig(server: McpServerConfig): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright (c) 2026 Super Durable, Inc.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Sustainable Use License 1.0.
|
|
4
|
+
// You may not use this file except in compliance with the License.
|
|
5
|
+
// See the LICENSE file in the repository root.
|
|
6
|
+
//
|
|
7
|
+
// SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
|
|
8
|
+
const serverNamePattern = /^[A-Za-z0-9_-]+$/;
|
|
9
|
+
/** Returns a copy whose environment and header values are `***`, safe to print or log. */
|
|
10
|
+
export function redactMcpServerConfigSecrets(server) {
|
|
11
|
+
if (server.transport === "stdio") {
|
|
12
|
+
return server.env === undefined ? { ...server } : { ...server, env: redactValues(server.env) };
|
|
13
|
+
}
|
|
14
|
+
return server.headers === undefined ? { ...server } : { ...server, headers: redactValues(server.headers) };
|
|
15
|
+
}
|
|
16
|
+
function redactValues(values) {
|
|
17
|
+
return Object.fromEntries(Object.keys(values).map((key) => [key, "***"]));
|
|
18
|
+
}
|
|
19
|
+
/** Throws a `TypeError` for an invalid configuration. */
|
|
20
|
+
export function validateMcpServerConfig(server) {
|
|
21
|
+
if (!serverNamePattern.test(server.name)) {
|
|
22
|
+
throw new TypeError(`MCP server name ${JSON.stringify(server.name)} must be non-empty letters, digits, '_', or '-'`);
|
|
23
|
+
}
|
|
24
|
+
if (server.transport === "stdio") {
|
|
25
|
+
if (server.command === "") {
|
|
26
|
+
throw new TypeError(`MCP server ${server.name} needs a command`);
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (server.transport !== "streamable_http") {
|
|
31
|
+
throw new TypeError(`MCP server ${server.name} has an unknown transport`);
|
|
32
|
+
}
|
|
33
|
+
const protocol = URL.canParse(server.url) ? new URL(server.url).protocol : "";
|
|
34
|
+
if (protocol !== "http:" && protocol !== "https:") {
|
|
35
|
+
throw new TypeError(`MCP server ${server.name} needs an http or https URL`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=mcp-server-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server-config.js","sourceRoot":"","sources":["../../../src/mcp/mcp-server-config.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAuF1D,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;AAE7C,0FAA0F;AAC1F,MAAM,UAAU,4BAA4B,CAAC,MAAuB;IAClE,IAAI,MAAM,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACjG,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;AAC7G,CAAC;AAED,SAAS,YAAY,CAAC,MAAwC;IAC5D,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,uBAAuB,CAAC,MAAuB;IAC7D,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,SAAS,CAAC,mBAAmB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;IACvH,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;QACjC,IAAI,MAAM,CAAC,OAAO,KAAK,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,SAAS,CAAC,cAAc,MAAM,CAAC,IAAI,kBAAkB,CAAC,CAAC;QACnE,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,MAAM,CAAC,SAAS,KAAK,iBAAiB,EAAE,CAAC;QAC3C,MAAM,IAAI,SAAS,CAAC,cAAe,MAAoC,CAAC,IAAI,2BAA2B,CAAC,CAAC;IAC3G,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9E,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClD,MAAM,IAAI,SAAS,CAAC,cAAc,MAAM,CAAC,IAAI,6BAA6B,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
|