@ryuhq/sdk 0.1.14 → 0.2.2
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 +69 -7
- package/dist/action.cjs +839 -0
- package/dist/action.d.cts +88 -0
- package/dist/action.d.ts +88 -0
- package/dist/action.js +8 -0
- package/dist/agent-plugin.cjs +46 -0
- package/dist/agent-plugin.d.cts +43 -33
- package/dist/agent-plugin.d.ts +43 -33
- package/dist/agent-plugin.js +1 -1
- package/dist/agent.cjs +16 -0
- package/dist/agent.d.cts +377 -1
- package/dist/agent.d.ts +377 -1
- package/dist/agent.js +4 -2
- package/dist/app-B0Z9Ew_R.d.cts +141 -0
- package/dist/app-C-BDJwfG.d.ts +141 -0
- package/dist/builder.cjs +1194 -0
- package/dist/builder.d.cts +217 -0
- package/dist/builder.d.ts +217 -0
- package/dist/builder.js +29 -0
- package/dist/chunk-4TPUZDTI.js +94 -0
- package/dist/chunk-BC3A7HMO.js +164 -0
- package/dist/chunk-FZSFZOIN.js +200 -0
- package/dist/{chunk-ODFEUVPW.js → chunk-HACAGK65.js} +1 -18
- package/dist/chunk-HLKJZAFK.js +361 -0
- package/dist/chunk-IKEDLLFY.js +19 -0
- package/dist/{chunk-G6FLVEC4.js → chunk-JX6DDRXV.js} +46 -0
- package/dist/{chunk-AO2KJRDD.js → chunk-NZKVOSC2.js} +192 -3
- package/dist/chunk-QYFUNJOH.js +83 -0
- package/dist/chunk-SN2QBJUF.js +148 -0
- package/dist/chunk-TLDPEGC7.js +21 -0
- package/dist/chunk-TXSHHZF2.js +0 -0
- package/dist/chunk-VLIRNNAE.js +154 -0
- package/dist/{chunk-MTUBUPIV.js → chunk-Z57QDDJR.js} +8 -227
- package/dist/chunk-ZTJWBRUL.js +282 -0
- package/dist/cli.cjs +347 -18
- package/dist/cli.js +128 -23
- package/dist/client-D5U6ssPc.d.cts +84 -0
- package/dist/client-D5U6ssPc.d.ts +84 -0
- package/dist/index.cjs +810 -86
- package/dist/index.d.cts +19 -634
- package/dist/index.d.ts +19 -634
- package/dist/index.js +82 -699
- package/dist/manifest.cjs +200 -4
- package/dist/manifest.d.cts +260 -5
- package/dist/manifest.d.ts +260 -5
- package/dist/manifest.js +15 -1
- package/dist/mcp/client.cjs +180 -0
- package/dist/mcp/client.d.cts +49 -0
- package/dist/mcp/client.d.ts +49 -0
- package/dist/mcp/client.js +10 -0
- package/dist/mcp/server.cjs +370 -0
- package/dist/mcp/server.d.cts +127 -0
- package/dist/mcp/server.d.ts +127 -0
- package/dist/mcp/server.js +9 -0
- package/dist/mcp.cjs +376 -0
- package/dist/mcp.d.cts +2 -0
- package/dist/mcp.d.ts +2 -0
- package/dist/mcp.js +17 -0
- package/dist/model.cjs +141 -0
- package/dist/model.d.cts +33 -0
- package/dist/model.d.ts +33 -0
- package/dist/model.js +18 -0
- package/dist/plugin.cjs +46 -0
- package/dist/plugin.d.cts +215 -0
- package/dist/plugin.d.ts +215 -0
- package/dist/plugin.js +8 -0
- package/dist/runnable.cjs +1438 -0
- package/dist/runnable.d.cts +274 -0
- package/dist/runnable.d.ts +274 -0
- package/dist/runnable.js +34 -0
- package/dist/{index-B6SkaAjJ.d.ts → tool-AjkdFvhE.d.ts} +88 -461
- package/dist/{index-BvAB5eMk.d.cts → tool-CgzW92O_.d.cts} +88 -461
- package/package.json +48 -3
- package/src/agent/loop.test.ts +4 -4
- package/src/agent/tools.ts +3 -3
- package/src/agent-plugin.test.ts +58 -0
- package/src/agent-plugin.ts +109 -36
- package/src/builder.ts +9 -0
- package/src/cli/dev.test.ts +26 -47
- package/src/cli/dev.ts +10 -2
- package/src/cli-security.test.ts +109 -0
- package/src/cli.ts +141 -25
- package/src/contracts-lockstep.test.ts +16 -2
- package/src/exports-lockstep.test.ts +93 -0
- package/src/generated/plugin-manifest.ts +322 -29
- package/src/index.ts +53 -0
- package/src/manifest-schema.test.ts +30 -1
- package/src/manifest.fixtures.test.ts +22 -6
- package/src/manifest.test.ts +165 -10
- package/src/manifest.ts +454 -188
- package/src/mcp/index.ts +18 -0
- package/src/mcp/server.ts +2 -1
- package/src/model/index.ts +22 -0
- package/src/plugin/ryu-plugin.ts +82 -0
- package/src/runnable/action.test.ts +128 -0
- package/src/runnable/action.ts +202 -0
- package/src/runnable/app.test.ts +2 -0
- package/src/runnable/app.ts +50 -14
- package/src/runnable/index.ts +20 -3
- package/src/runnable/primitives.test.ts +34 -0
- package/src/runnable/primitives.ts +116 -0
- package/src/runnable/runnable-types.ts +3 -0
- package/src/runnable/tool.ts +36 -5
- package/src/runnable/turn-hook.ts +8 -3
- package/src/slash-command.test.ts +69 -0
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineApp
|
|
3
|
+
} from "./chunk-SN2QBJUF.js";
|
|
4
|
+
import {
|
|
5
|
+
PluginManifestSchema,
|
|
6
|
+
RunnableMetaSchema
|
|
7
|
+
} from "./chunk-NZKVOSC2.js";
|
|
8
|
+
|
|
9
|
+
// src/builder.ts
|
|
10
|
+
var RunnableBuilder = class {
|
|
11
|
+
_id = "";
|
|
12
|
+
_name = "";
|
|
13
|
+
id(value) {
|
|
14
|
+
this._id = value;
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
name(value) {
|
|
18
|
+
this._name = value;
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var AgentBuilder = class extends RunnableBuilder {
|
|
23
|
+
build() {
|
|
24
|
+
const result = RunnableMetaSchema.safeParse({
|
|
25
|
+
id: this._id,
|
|
26
|
+
name: this._name,
|
|
27
|
+
kind: "agent"
|
|
28
|
+
});
|
|
29
|
+
if (!result.success) {
|
|
30
|
+
throw new Error(
|
|
31
|
+
`Invalid agent runnable: ${result.error.issues.map((i) => i.message).join("; ")}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
return result.data;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var WorkflowBuilder = class extends RunnableBuilder {
|
|
38
|
+
build() {
|
|
39
|
+
const result = RunnableMetaSchema.safeParse({
|
|
40
|
+
id: this._id,
|
|
41
|
+
name: this._name,
|
|
42
|
+
kind: "workflow"
|
|
43
|
+
});
|
|
44
|
+
if (!result.success) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Invalid workflow runnable: ${result.error.issues.map((i) => i.message).join("; ")}`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
return result.data;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var ToolBuilder = class extends RunnableBuilder {
|
|
53
|
+
build() {
|
|
54
|
+
const result = RunnableMetaSchema.safeParse({
|
|
55
|
+
id: this._id,
|
|
56
|
+
name: this._name,
|
|
57
|
+
kind: "tool"
|
|
58
|
+
});
|
|
59
|
+
if (!result.success) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
`Invalid tool runnable: ${result.error.issues.map((i) => i.message).join("; ")}`
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return result.data;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var SkillBuilder = class extends RunnableBuilder {
|
|
68
|
+
build() {
|
|
69
|
+
const result = RunnableMetaSchema.safeParse({
|
|
70
|
+
id: this._id,
|
|
71
|
+
name: this._name,
|
|
72
|
+
kind: "skill"
|
|
73
|
+
});
|
|
74
|
+
if (!result.success) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Invalid skill runnable: ${result.error.issues.map((i) => i.message).join("; ")}`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
return result.data;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
var agent = () => new AgentBuilder();
|
|
83
|
+
var workflow = () => new WorkflowBuilder();
|
|
84
|
+
var tool = () => new ToolBuilder();
|
|
85
|
+
var skill = () => new SkillBuilder();
|
|
86
|
+
var PluginBuilder = class {
|
|
87
|
+
_id = "";
|
|
88
|
+
_name = "";
|
|
89
|
+
_version = "";
|
|
90
|
+
_runnables = [];
|
|
91
|
+
_grants = [];
|
|
92
|
+
_companion = void 0;
|
|
93
|
+
_dependencies = [];
|
|
94
|
+
_requiredCapabilities = [];
|
|
95
|
+
_requiredGrants = [];
|
|
96
|
+
_targets = [];
|
|
97
|
+
/** Set the reverse-domain app id (e.g. `"com.example.my-app"`). */
|
|
98
|
+
id(value) {
|
|
99
|
+
this._id = value;
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
/** Set the human-readable display name. */
|
|
103
|
+
name(value) {
|
|
104
|
+
this._name = value;
|
|
105
|
+
return this;
|
|
106
|
+
}
|
|
107
|
+
/** Set the semver version string (e.g. `"1.0.0"`). */
|
|
108
|
+
version(value) {
|
|
109
|
+
this._version = value;
|
|
110
|
+
return this;
|
|
111
|
+
}
|
|
112
|
+
/** Append a pre-built `RunnableMeta` (from any per-kind builder). */
|
|
113
|
+
runnable(meta) {
|
|
114
|
+
this._runnables.push(meta);
|
|
115
|
+
return this;
|
|
116
|
+
}
|
|
117
|
+
/** Declare a permission grant (e.g. `"mcp:web_search"`). */
|
|
118
|
+
grant(permission) {
|
|
119
|
+
this._grants.push(permission);
|
|
120
|
+
return this;
|
|
121
|
+
}
|
|
122
|
+
/** Set an optional Companion surface descriptor. */
|
|
123
|
+
companion(surface) {
|
|
124
|
+
this._companion = surface;
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Declare a **plugin-to-plugin dependency**: `id` must be installed and is
|
|
129
|
+
* auto-enabled (in dependency order) before this plugin enables.
|
|
130
|
+
*
|
|
131
|
+
* `minVersion` is a MINIMUM — a bare `"1.2.0"` means `">=1.2.0"`, so an
|
|
132
|
+
* installed `2.0.0` satisfies it (comparator syntax like `">=1.2, <2"` is
|
|
133
|
+
* honoured verbatim).
|
|
134
|
+
*/
|
|
135
|
+
dependsOn(id, minVersion) {
|
|
136
|
+
this._dependencies.push(
|
|
137
|
+
minVersion ? { id, min_version: minVersion } : { id }
|
|
138
|
+
);
|
|
139
|
+
return this;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Declare a permission grant implied by this plugin's dependencies
|
|
143
|
+
* (`requires.grants`). Declaration only — the Gateway remains the sole
|
|
144
|
+
* authority on what a grant allows. Use {@link PluginBuilder.grant} for the
|
|
145
|
+
* grants this plugin needs in its own right.
|
|
146
|
+
*/
|
|
147
|
+
requiredGrant(permission) {
|
|
148
|
+
this._requiredGrants.push(permission);
|
|
149
|
+
return this;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Declare an abstract **capability** edge (`requires.capabilities`) the broker
|
|
153
|
+
* resolves to a bound provider at enable time — e.g. `requiresCapability("rag")`.
|
|
154
|
+
* Distinct from a specific-plugin dependency: a capability edge lets the
|
|
155
|
+
* binding registry choose the provider. `minVersion` is a MINIMUM (`"1.2.0"`
|
|
156
|
+
* = `">=1.2.0"`).
|
|
157
|
+
*/
|
|
158
|
+
requiresCapability(capability, minVersion) {
|
|
159
|
+
this._requiredCapabilities.push(
|
|
160
|
+
minVersion ? { capability, min_version: minVersion } : { capability }
|
|
161
|
+
);
|
|
162
|
+
return this;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Restrict this plugin to a host surface (`"desktop"`, `"island"`, …).
|
|
166
|
+
* Declaring NO target is the default and means **every** surface.
|
|
167
|
+
*/
|
|
168
|
+
target(surface) {
|
|
169
|
+
this._targets.push(surface);
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Validate and return the assembled `PluginManifest`. Throws an `Error` with
|
|
174
|
+
* the failing field name and message when validation fails.
|
|
175
|
+
*/
|
|
176
|
+
build() {
|
|
177
|
+
const hasRequires = this._dependencies.length > 0 || this._requiredCapabilities.length > 0 || this._requiredGrants.length > 0;
|
|
178
|
+
const raw = {
|
|
179
|
+
id: this._id,
|
|
180
|
+
name: this._name,
|
|
181
|
+
version: this._version,
|
|
182
|
+
runnables: this._runnables,
|
|
183
|
+
permission_grants: this._grants,
|
|
184
|
+
companion: this._companion,
|
|
185
|
+
targets: this._targets,
|
|
186
|
+
...hasRequires ? {
|
|
187
|
+
requires: {
|
|
188
|
+
apps: this._dependencies,
|
|
189
|
+
capabilities: this._requiredCapabilities,
|
|
190
|
+
grants: this._requiredGrants
|
|
191
|
+
}
|
|
192
|
+
} : {}
|
|
193
|
+
};
|
|
194
|
+
const result = PluginManifestSchema.safeParse(raw);
|
|
195
|
+
if (!result.success) {
|
|
196
|
+
const first = result.error.issues[0];
|
|
197
|
+
const field = first?.path.join(".") ?? "unknown";
|
|
198
|
+
const message = first?.message ?? "validation failed";
|
|
199
|
+
throw new Error(
|
|
200
|
+
`manifest.json validation failed at '${field}': ${message}`
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return result.data;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
var AppBuilder = class {
|
|
207
|
+
_id = "";
|
|
208
|
+
_title = "";
|
|
209
|
+
_version = "";
|
|
210
|
+
_slug = "";
|
|
211
|
+
_server = void 0;
|
|
212
|
+
_displayMode = void 0;
|
|
213
|
+
_mime = void 0;
|
|
214
|
+
_uiEntry = "";
|
|
215
|
+
_grants = [];
|
|
216
|
+
_activationEvents = [];
|
|
217
|
+
_tools = [];
|
|
218
|
+
_dependencies = [];
|
|
219
|
+
_requiredCapabilities = [];
|
|
220
|
+
_requiredGrants = [];
|
|
221
|
+
_slashCommands = [];
|
|
222
|
+
_targets = [];
|
|
223
|
+
/** Set the reverse-domain app id (e.g. `"com.example.checklist"`). */
|
|
224
|
+
id(value) {
|
|
225
|
+
this._id = value;
|
|
226
|
+
return this;
|
|
227
|
+
}
|
|
228
|
+
/** Set the human-readable display name. */
|
|
229
|
+
title(value) {
|
|
230
|
+
this._title = value;
|
|
231
|
+
return this;
|
|
232
|
+
}
|
|
233
|
+
/** Set the semver version string (e.g. `"1.0.0"`). */
|
|
234
|
+
version(value) {
|
|
235
|
+
this._version = value;
|
|
236
|
+
return this;
|
|
237
|
+
}
|
|
238
|
+
/** Set the app slug (drives `ui://widget/<slug>.html` and the server default). */
|
|
239
|
+
slug(value) {
|
|
240
|
+
this._slug = value;
|
|
241
|
+
return this;
|
|
242
|
+
}
|
|
243
|
+
/** Override the MCP server namespace for tool ids (defaults to the slug). */
|
|
244
|
+
server(value) {
|
|
245
|
+
this._server = value;
|
|
246
|
+
return this;
|
|
247
|
+
}
|
|
248
|
+
/** Set the default widget display mode (`inline` | `fullscreen` | `pip`). */
|
|
249
|
+
displayMode(value) {
|
|
250
|
+
this._displayMode = value;
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
/** Override the widget MIME dialect (defaults to `text/html+skybridge`). */
|
|
254
|
+
mime(value) {
|
|
255
|
+
this._mime = value;
|
|
256
|
+
return this;
|
|
257
|
+
}
|
|
258
|
+
/** Set the widget UI source entry `ryu pack` bundles into `ui_code`. */
|
|
259
|
+
uiEntry(value) {
|
|
260
|
+
this._uiEntry = value;
|
|
261
|
+
return this;
|
|
262
|
+
}
|
|
263
|
+
/** Declare a permission grant (e.g. `"mcp:web_search"`). */
|
|
264
|
+
grant(permission) {
|
|
265
|
+
this._grants.push(permission);
|
|
266
|
+
return this;
|
|
267
|
+
}
|
|
268
|
+
/** Add a VS-Code-style activation event (empty = eager `["*"]`). */
|
|
269
|
+
activationEvent(event) {
|
|
270
|
+
this._activationEvents.push(event);
|
|
271
|
+
return this;
|
|
272
|
+
}
|
|
273
|
+
/** Append a tool spec (render tool unless `accessible:true`). */
|
|
274
|
+
tool(spec) {
|
|
275
|
+
this._tools.push(spec);
|
|
276
|
+
return this;
|
|
277
|
+
}
|
|
278
|
+
/** Add a slash command and its optional sequential argument choices. */
|
|
279
|
+
slashCommand(command) {
|
|
280
|
+
this._slashCommands.push(command);
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Declare a **plugin-to-plugin dependency** (auto-enabled, in dependency order,
|
|
285
|
+
* before this app). `minVersion` is a MINIMUM (`"1.2.0"` = `">=1.2.0"`).
|
|
286
|
+
*/
|
|
287
|
+
dependsOn(id, minVersion) {
|
|
288
|
+
this._dependencies.push(
|
|
289
|
+
minVersion ? { id, min_version: minVersion } : { id }
|
|
290
|
+
);
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
/** Declare a grant implied by this app's dependencies (`requires.grants`). */
|
|
294
|
+
requiredGrant(permission) {
|
|
295
|
+
this._requiredGrants.push(permission);
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Declare an abstract **capability** edge (`requires.capabilities`) the broker
|
|
300
|
+
* resolves to a bound provider at enable time — e.g. `requiresCapability("rag")`.
|
|
301
|
+
* Distinct from a specific-plugin dependency: a capability edge lets the
|
|
302
|
+
* binding registry choose the provider. `minVersion` is a MINIMUM (`"1.2.0"`
|
|
303
|
+
* = `">=1.2.0"`).
|
|
304
|
+
*/
|
|
305
|
+
requiresCapability(capability, minVersion) {
|
|
306
|
+
this._requiredCapabilities.push(
|
|
307
|
+
minVersion ? { capability, min_version: minVersion } : { capability }
|
|
308
|
+
);
|
|
309
|
+
return this;
|
|
310
|
+
}
|
|
311
|
+
/** Restrict this app to a host surface. No target = every surface. */
|
|
312
|
+
target(surface) {
|
|
313
|
+
this._targets.push(surface);
|
|
314
|
+
return this;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Validate and return the assembled `PluginManifest`. Throws an `Error` naming
|
|
318
|
+
* the failing field when validation fails.
|
|
319
|
+
*/
|
|
320
|
+
build() {
|
|
321
|
+
const hasRequires = this._dependencies.length > 0 || this._requiredCapabilities.length > 0 || this._requiredGrants.length > 0;
|
|
322
|
+
const options = {
|
|
323
|
+
id: this._id,
|
|
324
|
+
title: this._title,
|
|
325
|
+
version: this._version,
|
|
326
|
+
slug: this._slug,
|
|
327
|
+
uiEntry: this._uiEntry,
|
|
328
|
+
tools: this._tools,
|
|
329
|
+
grants: this._grants,
|
|
330
|
+
slashCommands: this._slashCommands,
|
|
331
|
+
...this._server ? { server: this._server } : {},
|
|
332
|
+
...this._displayMode ? { displayMode: this._displayMode } : {},
|
|
333
|
+
...this._mime ? { mime: this._mime } : {},
|
|
334
|
+
...this._activationEvents.length > 0 ? { activationEvents: this._activationEvents } : {},
|
|
335
|
+
...hasRequires ? {
|
|
336
|
+
requires: {
|
|
337
|
+
apps: this._dependencies,
|
|
338
|
+
capabilities: this._requiredCapabilities,
|
|
339
|
+
grants: this._requiredGrants
|
|
340
|
+
}
|
|
341
|
+
} : {},
|
|
342
|
+
...this._targets.length > 0 ? { targets: this._targets } : {}
|
|
343
|
+
};
|
|
344
|
+
return defineApp(options);
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
var app = () => new AppBuilder();
|
|
348
|
+
|
|
349
|
+
export {
|
|
350
|
+
AgentBuilder,
|
|
351
|
+
WorkflowBuilder,
|
|
352
|
+
ToolBuilder,
|
|
353
|
+
SkillBuilder,
|
|
354
|
+
agent,
|
|
355
|
+
workflow,
|
|
356
|
+
tool,
|
|
357
|
+
skill,
|
|
358
|
+
PluginBuilder,
|
|
359
|
+
AppBuilder,
|
|
360
|
+
app
|
|
361
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// src/model/gateway.ts
|
|
2
|
+
import * as native from "@ryuhq/sdk-native";
|
|
3
|
+
var DEFAULT_GATEWAY_URL = "http://127.0.0.1:7981";
|
|
4
|
+
function resolveGatewayUrl2() {
|
|
5
|
+
return native.resolveGatewayUrl();
|
|
6
|
+
}
|
|
7
|
+
function resolveGatewayToken2() {
|
|
8
|
+
return native.resolveGatewayToken() ?? void 0;
|
|
9
|
+
}
|
|
10
|
+
function assertAllowedEgressUrl(baseUrl) {
|
|
11
|
+
native.assertAllowedEgress(baseUrl);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export {
|
|
15
|
+
DEFAULT_GATEWAY_URL,
|
|
16
|
+
resolveGatewayUrl2 as resolveGatewayUrl,
|
|
17
|
+
resolveGatewayToken2 as resolveGatewayToken,
|
|
18
|
+
assertAllowedEgressUrl
|
|
19
|
+
};
|
|
@@ -74,6 +74,21 @@ function toSpecEnv(value) {
|
|
|
74
74
|
}
|
|
75
75
|
return Object.keys(env).length > 0 ? env : void 0;
|
|
76
76
|
}
|
|
77
|
+
function validateRemoteUrl(name, raw) {
|
|
78
|
+
let parsed;
|
|
79
|
+
try {
|
|
80
|
+
parsed = new URL(raw);
|
|
81
|
+
} catch {
|
|
82
|
+
return `mcp server '${name}' remote url ${JSON.stringify(raw)} is invalid and was omitted`;
|
|
83
|
+
}
|
|
84
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
85
|
+
return `mcp server '${name}' remote url must use http or https and was omitted`;
|
|
86
|
+
}
|
|
87
|
+
if (parsed.username || parsed.password || parsed.hash) {
|
|
88
|
+
return `mcp server '${name}' remote url must not contain credentials or a fragment and was omitted`;
|
|
89
|
+
}
|
|
90
|
+
return void 0;
|
|
91
|
+
}
|
|
77
92
|
function toSpecServer(name, decl) {
|
|
78
93
|
const extras = {};
|
|
79
94
|
const commandEnv = asString(decl.command_env);
|
|
@@ -91,6 +106,37 @@ function toSpecServer(name, decl) {
|
|
|
91
106
|
note: `mcp server '${name}' is disabled in the native manifest and was omitted from ${AGENT_PLUGIN_MCP_FILE}`
|
|
92
107
|
};
|
|
93
108
|
}
|
|
109
|
+
const declaredType = asString(decl.type);
|
|
110
|
+
const remoteUrl = asString(decl.url);
|
|
111
|
+
const remoteType = declaredType === "sse" ? "sse" : declaredType === "streamable-http" || declaredType === "streamable_http" || declaredType === "http" || !declaredType && remoteUrl ? "streamable-http" : void 0;
|
|
112
|
+
if (remoteType) {
|
|
113
|
+
if (!remoteUrl) {
|
|
114
|
+
return {
|
|
115
|
+
extras,
|
|
116
|
+
note: `mcp server '${name}' has remote type '${remoteType}' but no url and was omitted`
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const urlNote = validateRemoteUrl(name, remoteUrl);
|
|
120
|
+
if (urlNote) {
|
|
121
|
+
return { extras, note: urlNote };
|
|
122
|
+
}
|
|
123
|
+
const server2 = {
|
|
124
|
+
type: remoteType,
|
|
125
|
+
url: remoteUrl
|
|
126
|
+
};
|
|
127
|
+
const headers = toSpecEnv(decl.headers);
|
|
128
|
+
if (headers) {
|
|
129
|
+
server2.headers = headers;
|
|
130
|
+
}
|
|
131
|
+
const note = decl.auth ? `mcp server '${name}' uses Ryu OAuth metadata that is not portable; static headers were exported` : void 0;
|
|
132
|
+
return { server: server2, extras, note };
|
|
133
|
+
}
|
|
134
|
+
if (declaredType && declaredType !== "stdio") {
|
|
135
|
+
return {
|
|
136
|
+
extras,
|
|
137
|
+
note: `mcp server '${name}' has unsupported transport '${declaredType}' and was omitted`
|
|
138
|
+
};
|
|
139
|
+
}
|
|
94
140
|
const command = asString(decl.command);
|
|
95
141
|
if (!command) {
|
|
96
142
|
return {
|