poe-code 3.0.187 → 3.0.188
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/dist/cli/commands/experiment.js +1 -1
- package/dist/cli/commands/experiment.js.map +1 -1
- package/dist/cli/commands/pipeline-init.js +1 -1
- package/dist/cli/commands/pipeline-init.js.map +1 -1
- package/dist/cli/commands/pipeline.js +1 -1
- package/dist/cli/commands/pipeline.js.map +1 -1
- package/dist/cli/commands/spawn.js +2 -1
- package/dist/cli/commands/spawn.js.map +1 -1
- package/dist/cli/program.js +6 -6
- package/dist/cli/program.js.map +1 -1
- package/dist/index.js +122 -225
- package/dist/index.js.map +4 -4
- package/dist/providers/claude-code.js +2 -76
- package/dist/providers/claude-code.js.map +4 -4
- package/dist/providers/codex.js +2 -76
- package/dist/providers/codex.js.map +4 -4
- package/dist/providers/goose.js +2 -76
- package/dist/providers/goose.js.map +4 -4
- package/dist/providers/kimi.js +2 -76
- package/dist/providers/kimi.js.map +4 -4
- package/dist/providers/opencode.js +2 -76
- package/dist/providers/opencode.js.map +4 -4
- package/dist/providers/poe-agent.js +23 -107
- package/dist/providers/poe-agent.js.map +4 -4
- package/dist/sdk/experiment.js +1 -1
- package/dist/sdk/experiment.js.map +1 -1
- package/package.json +10 -30
- package/packages/design-system/dist/prompts/primitives/cancel.d.ts +1 -1
- package/packages/design-system/dist/prompts/primitives/cancel.js +1 -1
- package/packages/cmdkit/dist/cli.compile-check.d.ts +0 -1
- package/packages/cmdkit/dist/cli.compile-check.js +0 -26
- package/packages/cmdkit/dist/cli.d.ts +0 -12
- package/packages/cmdkit/dist/cli.js +0 -2331
- package/packages/cmdkit/dist/cli.js.map +0 -7
- package/packages/cmdkit/dist/index.compile-check.d.ts +0 -1
- package/packages/cmdkit/dist/index.compile-check.js +0 -50
- package/packages/cmdkit/dist/index.d.ts +0 -164
- package/packages/cmdkit/dist/index.js +0 -561
- package/packages/cmdkit/dist/index.js.map +0 -7
- package/packages/cmdkit/dist/mcp.compile-check.d.ts +0 -1
- package/packages/cmdkit/dist/mcp.compile-check.js +0 -26
- package/packages/cmdkit/dist/mcp.d.ts +0 -31
- package/packages/cmdkit/dist/mcp.js +0 -1254
- package/packages/cmdkit/dist/mcp.js.map +0 -7
- package/packages/cmdkit/dist/number-schema.d.ts +0 -3
- package/packages/cmdkit/dist/number-schema.js +0 -8
- package/packages/cmdkit/dist/renderer.d.ts +0 -5
- package/packages/cmdkit/dist/renderer.js +0 -164
- package/packages/cmdkit/dist/renderer.js.map +0 -7
- package/packages/cmdkit/dist/schema-scope.d.ts +0 -4
- package/packages/cmdkit/dist/schema-scope.js +0 -34
- package/packages/cmdkit/dist/sdk.compile-check.d.ts +0 -1
- package/packages/cmdkit/dist/sdk.compile-check.js +0 -79
- package/packages/cmdkit/dist/sdk.d.ts +0 -63
- package/packages/cmdkit/dist/sdk.js +0 -369
- package/packages/cmdkit/dist/sdk.js.map +0 -7
- package/packages/cmdkit-openapi/dist/api-command.d.ts +0 -7
- package/packages/cmdkit-openapi/dist/api-command.js +0 -4
- package/packages/cmdkit-openapi/dist/auth/bearer-token-auth.d.ts +0 -8
- package/packages/cmdkit-openapi/dist/auth/bearer-token-auth.js +0 -216
- package/packages/cmdkit-openapi/dist/auth/types.d.ts +0 -9
- package/packages/cmdkit-openapi/dist/auth/types.js +0 -1
- package/packages/cmdkit-openapi/dist/bin/generate.d.ts +0 -40
- package/packages/cmdkit-openapi/dist/bin/generate.js +0 -248
- package/packages/cmdkit-openapi/dist/define-client.d.ts +0 -20
- package/packages/cmdkit-openapi/dist/define-client.js +0 -148
- package/packages/cmdkit-openapi/dist/generate.d.ts +0 -210
- package/packages/cmdkit-openapi/dist/generate.js +0 -1131
- package/packages/cmdkit-openapi/dist/group-by-noun.d.ts +0 -6
- package/packages/cmdkit-openapi/dist/group-by-noun.js +0 -17
- package/packages/cmdkit-openapi/dist/http.d.ts +0 -26
- package/packages/cmdkit-openapi/dist/http.js +0 -123
- package/packages/cmdkit-openapi/dist/index.d.ts +0 -12
- package/packages/cmdkit-openapi/dist/index.js +0 -6
- package/packages/cmdkit-openapi/dist/interpreter.d.ts +0 -6
- package/packages/cmdkit-openapi/dist/interpreter.js +0 -289
- package/packages/cmdkit-openapi/dist/lock.d.ts +0 -14
- package/packages/cmdkit-openapi/dist/lock.js +0 -48
- package/packages/cmdkit-openapi/dist/naming.d.ts +0 -24
- package/packages/cmdkit-openapi/dist/naming.js +0 -218
- package/packages/cmdkit-openapi/dist/request-shape.d.ts +0 -15
- package/packages/cmdkit-openapi/dist/request-shape.js +0 -5
- package/packages/cmdkit-openapi/dist/runtime.d.ts +0 -13
- package/packages/cmdkit-openapi/dist/runtime.js +0 -94
- package/packages/cmdkit-openapi/dist/spec-source.d.ts +0 -11
- package/packages/cmdkit-openapi/dist/spec-source.js +0 -63
- package/packages/cmdkit-schema/dist/index.compile-check.d.ts +0 -1
- package/packages/cmdkit-schema/dist/index.compile-check.js +0 -12
- package/packages/cmdkit-schema/dist/index.d.ts +0 -124
- package/packages/cmdkit-schema/dist/index.js +0 -175
|
@@ -1,1254 +0,0 @@
|
|
|
1
|
-
// packages/cmdkit/src/mcp.ts
|
|
2
|
-
import { access, readFile, writeFile } from "node:fs/promises";
|
|
3
|
-
|
|
4
|
-
// packages/tiny-stdio-mcp-server/src/server.ts
|
|
5
|
-
import * as readline from "readline";
|
|
6
|
-
|
|
7
|
-
// packages/tiny-stdio-mcp-server/src/types.ts
|
|
8
|
-
var JSON_RPC_ERROR_CODES = {
|
|
9
|
-
PARSE_ERROR: -32700,
|
|
10
|
-
INVALID_REQUEST: -32600,
|
|
11
|
-
METHOD_NOT_FOUND: -32601,
|
|
12
|
-
INVALID_PARAMS: -32602,
|
|
13
|
-
INTERNAL_ERROR: -32603
|
|
14
|
-
};
|
|
15
|
-
var ToolError = class extends Error {
|
|
16
|
-
constructor(code, message) {
|
|
17
|
-
super(message);
|
|
18
|
-
this.code = code;
|
|
19
|
-
this.name = "ToolError";
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// packages/tiny-stdio-mcp-server/src/jsonrpc.ts
|
|
24
|
-
function parseMessage(line) {
|
|
25
|
-
let parsed;
|
|
26
|
-
try {
|
|
27
|
-
parsed = JSON.parse(line);
|
|
28
|
-
} catch {
|
|
29
|
-
return {
|
|
30
|
-
success: false,
|
|
31
|
-
error: {
|
|
32
|
-
code: JSON_RPC_ERROR_CODES.PARSE_ERROR,
|
|
33
|
-
message: "Parse error"
|
|
34
|
-
},
|
|
35
|
-
id: null
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
39
|
-
return {
|
|
40
|
-
success: false,
|
|
41
|
-
error: {
|
|
42
|
-
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
43
|
-
message: "Invalid Request"
|
|
44
|
-
},
|
|
45
|
-
id: null
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
const obj = parsed;
|
|
49
|
-
const hasId = "id" in obj;
|
|
50
|
-
const id = typeof obj.id === "string" || typeof obj.id === "number" ? obj.id : null;
|
|
51
|
-
if (obj.jsonrpc !== "2.0") {
|
|
52
|
-
return {
|
|
53
|
-
success: false,
|
|
54
|
-
error: {
|
|
55
|
-
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
56
|
-
message: "Invalid Request"
|
|
57
|
-
},
|
|
58
|
-
id
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
if (typeof obj.method !== "string") {
|
|
62
|
-
return {
|
|
63
|
-
success: false,
|
|
64
|
-
error: {
|
|
65
|
-
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
66
|
-
message: "Invalid Request"
|
|
67
|
-
},
|
|
68
|
-
id
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
if (!hasId) {
|
|
72
|
-
return {
|
|
73
|
-
success: true,
|
|
74
|
-
isNotification: true,
|
|
75
|
-
request: {
|
|
76
|
-
jsonrpc: "2.0",
|
|
77
|
-
method: obj.method,
|
|
78
|
-
params: obj.params
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
if (id === null) {
|
|
83
|
-
return {
|
|
84
|
-
success: false,
|
|
85
|
-
error: {
|
|
86
|
-
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
87
|
-
message: "Invalid Request"
|
|
88
|
-
},
|
|
89
|
-
id: null
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
return {
|
|
93
|
-
success: true,
|
|
94
|
-
isNotification: false,
|
|
95
|
-
request: {
|
|
96
|
-
jsonrpc: "2.0",
|
|
97
|
-
id,
|
|
98
|
-
method: obj.method,
|
|
99
|
-
params: obj.params
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
function formatSuccessResponse(id, result) {
|
|
104
|
-
const response = {
|
|
105
|
-
jsonrpc: "2.0",
|
|
106
|
-
id,
|
|
107
|
-
result
|
|
108
|
-
};
|
|
109
|
-
return JSON.stringify(response);
|
|
110
|
-
}
|
|
111
|
-
function formatErrorResponse(id, error) {
|
|
112
|
-
const response = {
|
|
113
|
-
jsonrpc: "2.0",
|
|
114
|
-
id,
|
|
115
|
-
error
|
|
116
|
-
};
|
|
117
|
-
return JSON.stringify(response);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// packages/tiny-stdio-mcp-server/src/content/file-type.ts
|
|
121
|
-
function fileTypeFromBuffer(data) {
|
|
122
|
-
if (data.length < 12) {
|
|
123
|
-
return void 0;
|
|
124
|
-
}
|
|
125
|
-
if (data[0] === 137 && data[1] === 80 && data[2] === 78 && data[3] === 71 && data[4] === 13 && data[5] === 10 && data[6] === 26 && data[7] === 10) {
|
|
126
|
-
return { mime: "image/png", ext: "png" };
|
|
127
|
-
}
|
|
128
|
-
if (data[0] === 255 && data[1] === 216 && data[2] === 255) {
|
|
129
|
-
return { mime: "image/jpeg", ext: "jpg" };
|
|
130
|
-
}
|
|
131
|
-
if (data[0] === 71 && data[1] === 73 && data[2] === 70 && data[3] === 56) {
|
|
132
|
-
return { mime: "image/gif", ext: "gif" };
|
|
133
|
-
}
|
|
134
|
-
if (data[0] === 82 && data[1] === 73 && data[2] === 70 && data[3] === 70 && data[8] === 87 && data[9] === 69 && data[10] === 66 && data[11] === 80) {
|
|
135
|
-
return { mime: "image/webp", ext: "webp" };
|
|
136
|
-
}
|
|
137
|
-
if (data[0] === 255 && (data[1] === 251 || data[1] === 250) || data[0] === 73 && data[1] === 68 && data[2] === 51) {
|
|
138
|
-
return { mime: "audio/mpeg", ext: "mp3" };
|
|
139
|
-
}
|
|
140
|
-
if (data[0] === 82 && data[1] === 73 && data[2] === 70 && data[3] === 70 && data[8] === 87 && data[9] === 65 && data[10] === 86 && data[11] === 69) {
|
|
141
|
-
return { mime: "audio/wav", ext: "wav" };
|
|
142
|
-
}
|
|
143
|
-
if (data[0] === 79 && data[1] === 103 && data[2] === 103 && data[3] === 83) {
|
|
144
|
-
return { mime: "audio/ogg", ext: "ogg" };
|
|
145
|
-
}
|
|
146
|
-
if (data[4] === 102 && data[5] === 116 && data[6] === 121 && data[7] === 112 && data[8] === 77 && data[9] === 52 && data[10] === 65) {
|
|
147
|
-
return { mime: "audio/mp4", ext: "m4a" };
|
|
148
|
-
}
|
|
149
|
-
if (data[4] === 102 && data[5] === 116 && data[6] === 121 && data[7] === 112) {
|
|
150
|
-
return { mime: "video/mp4", ext: "mp4" };
|
|
151
|
-
}
|
|
152
|
-
if (data[0] === 26 && data[1] === 69 && data[2] === 223 && data[3] === 163) {
|
|
153
|
-
return { mime: "video/webm", ext: "webm" };
|
|
154
|
-
}
|
|
155
|
-
return void 0;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// packages/tiny-stdio-mcp-server/src/content/image.ts
|
|
159
|
-
var SUPPORTED_IMAGE_MIMES = /* @__PURE__ */ new Set([
|
|
160
|
-
"image/png",
|
|
161
|
-
"image/jpeg",
|
|
162
|
-
"image/gif",
|
|
163
|
-
"image/webp"
|
|
164
|
-
]);
|
|
165
|
-
var Image = class _Image {
|
|
166
|
-
constructor(base64Data, mimeType) {
|
|
167
|
-
this.base64Data = base64Data;
|
|
168
|
-
this.mimeType = mimeType;
|
|
169
|
-
}
|
|
170
|
-
static async fromUrl(url) {
|
|
171
|
-
const response = await fetch(url);
|
|
172
|
-
if (!response.ok) {
|
|
173
|
-
throw new Error(`Failed to fetch image from ${url}: ${response.status} ${response.statusText}`);
|
|
174
|
-
}
|
|
175
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
176
|
-
const data = new Uint8Array(arrayBuffer);
|
|
177
|
-
const detected = fileTypeFromBuffer(data);
|
|
178
|
-
let mimeType;
|
|
179
|
-
if (detected && SUPPORTED_IMAGE_MIMES.has(detected.mime)) {
|
|
180
|
-
mimeType = detected.mime;
|
|
181
|
-
} else {
|
|
182
|
-
const contentType = response.headers.get("content-type")?.split(";")[0];
|
|
183
|
-
if (contentType && SUPPORTED_IMAGE_MIMES.has(contentType)) {
|
|
184
|
-
mimeType = contentType;
|
|
185
|
-
} else {
|
|
186
|
-
throw new Error(`Unable to detect image MIME type from ${url}`);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
const base64 = Buffer.from(data).toString("base64");
|
|
190
|
-
return new _Image(base64, mimeType);
|
|
191
|
-
}
|
|
192
|
-
static fromBytes(data, format) {
|
|
193
|
-
let mimeType;
|
|
194
|
-
if (format) {
|
|
195
|
-
mimeType = format.includes("/") ? format : `image/${format}`;
|
|
196
|
-
} else {
|
|
197
|
-
const detected = fileTypeFromBuffer(data);
|
|
198
|
-
if (!detected || !SUPPORTED_IMAGE_MIMES.has(detected.mime)) {
|
|
199
|
-
throw new Error("Unable to detect image MIME type from bytes");
|
|
200
|
-
}
|
|
201
|
-
mimeType = detected.mime;
|
|
202
|
-
}
|
|
203
|
-
const base64 = Buffer.from(data).toString("base64");
|
|
204
|
-
return new _Image(base64, mimeType);
|
|
205
|
-
}
|
|
206
|
-
static fromBase64(base64, mimeType) {
|
|
207
|
-
return new _Image(base64, mimeType);
|
|
208
|
-
}
|
|
209
|
-
toContentBlock() {
|
|
210
|
-
return {
|
|
211
|
-
type: "image",
|
|
212
|
-
data: this.base64Data,
|
|
213
|
-
mimeType: this.mimeType
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
};
|
|
217
|
-
|
|
218
|
-
// packages/tiny-stdio-mcp-server/src/content/audio.ts
|
|
219
|
-
var SUPPORTED_AUDIO_MIMES = /* @__PURE__ */ new Set([
|
|
220
|
-
"audio/mpeg",
|
|
221
|
-
"audio/wav",
|
|
222
|
-
"audio/ogg",
|
|
223
|
-
"audio/mp4"
|
|
224
|
-
]);
|
|
225
|
-
var AUDIO_FORMAT_MAP = {
|
|
226
|
-
mp3: "audio/mpeg",
|
|
227
|
-
wav: "audio/wav",
|
|
228
|
-
ogg: "audio/ogg",
|
|
229
|
-
m4a: "audio/mp4",
|
|
230
|
-
mpeg: "audio/mpeg"
|
|
231
|
-
};
|
|
232
|
-
var Audio = class _Audio {
|
|
233
|
-
constructor(base64Data, mimeType) {
|
|
234
|
-
this.base64Data = base64Data;
|
|
235
|
-
this.mimeType = mimeType;
|
|
236
|
-
}
|
|
237
|
-
static async fromUrl(url) {
|
|
238
|
-
const response = await fetch(url);
|
|
239
|
-
if (!response.ok) {
|
|
240
|
-
throw new Error(`Failed to fetch audio from ${url}: ${response.status} ${response.statusText}`);
|
|
241
|
-
}
|
|
242
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
243
|
-
const data = new Uint8Array(arrayBuffer);
|
|
244
|
-
const detected = fileTypeFromBuffer(data);
|
|
245
|
-
let mimeType;
|
|
246
|
-
if (detected && SUPPORTED_AUDIO_MIMES.has(detected.mime)) {
|
|
247
|
-
mimeType = detected.mime;
|
|
248
|
-
} else {
|
|
249
|
-
const contentType = response.headers.get("content-type")?.split(";")[0];
|
|
250
|
-
if (contentType && SUPPORTED_AUDIO_MIMES.has(contentType)) {
|
|
251
|
-
mimeType = contentType;
|
|
252
|
-
} else {
|
|
253
|
-
throw new Error(`Unable to detect audio MIME type from ${url}`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
const base64 = Buffer.from(data).toString("base64");
|
|
257
|
-
return new _Audio(base64, mimeType);
|
|
258
|
-
}
|
|
259
|
-
static fromBytes(data, format) {
|
|
260
|
-
let mimeType;
|
|
261
|
-
if (format) {
|
|
262
|
-
if (format.includes("/")) {
|
|
263
|
-
mimeType = format;
|
|
264
|
-
} else {
|
|
265
|
-
mimeType = AUDIO_FORMAT_MAP[format.toLowerCase()] || `audio/${format}`;
|
|
266
|
-
}
|
|
267
|
-
} else {
|
|
268
|
-
const detected = fileTypeFromBuffer(data);
|
|
269
|
-
if (!detected || !SUPPORTED_AUDIO_MIMES.has(detected.mime)) {
|
|
270
|
-
throw new Error("Unable to detect audio MIME type from bytes");
|
|
271
|
-
}
|
|
272
|
-
mimeType = detected.mime;
|
|
273
|
-
}
|
|
274
|
-
const base64 = Buffer.from(data).toString("base64");
|
|
275
|
-
return new _Audio(base64, mimeType);
|
|
276
|
-
}
|
|
277
|
-
static fromBase64(base64, mimeType) {
|
|
278
|
-
return new _Audio(base64, mimeType);
|
|
279
|
-
}
|
|
280
|
-
toContentBlock() {
|
|
281
|
-
return {
|
|
282
|
-
type: "audio",
|
|
283
|
-
data: this.base64Data,
|
|
284
|
-
mimeType: this.mimeType
|
|
285
|
-
};
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
// packages/tiny-stdio-mcp-server/src/content/file.ts
|
|
290
|
-
function isTextMimeType(mimeType) {
|
|
291
|
-
return mimeType.startsWith("text/") || mimeType === "application/json" || mimeType === "application/xml" || mimeType === "application/javascript" || mimeType === "application/typescript";
|
|
292
|
-
}
|
|
293
|
-
var File = class _File {
|
|
294
|
-
constructor(data, mimeType, isText, name) {
|
|
295
|
-
this.data = data;
|
|
296
|
-
this.mimeType = mimeType;
|
|
297
|
-
this.isText = isText;
|
|
298
|
-
this.name = name;
|
|
299
|
-
}
|
|
300
|
-
static async fromUrl(url) {
|
|
301
|
-
const response = await fetch(url);
|
|
302
|
-
if (!response.ok) {
|
|
303
|
-
throw new Error(`Failed to fetch file from ${url}: ${response.status} ${response.statusText}`);
|
|
304
|
-
}
|
|
305
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
306
|
-
const data = new Uint8Array(arrayBuffer);
|
|
307
|
-
const detected = fileTypeFromBuffer(data);
|
|
308
|
-
let mimeType;
|
|
309
|
-
if (detected) {
|
|
310
|
-
mimeType = detected.mime;
|
|
311
|
-
} else {
|
|
312
|
-
const contentType = response.headers.get("content-type")?.split(";")[0];
|
|
313
|
-
if (contentType) {
|
|
314
|
-
mimeType = contentType;
|
|
315
|
-
} else {
|
|
316
|
-
throw new Error(`Unable to detect MIME type from ${url}`);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
const isText = isTextMimeType(mimeType);
|
|
320
|
-
const name = url.split("/").pop() || "file";
|
|
321
|
-
return new _File(data, mimeType, isText, name);
|
|
322
|
-
}
|
|
323
|
-
static fromBytes(data, mimeType) {
|
|
324
|
-
const isText = isTextMimeType(mimeType);
|
|
325
|
-
return new _File(data, mimeType, isText);
|
|
326
|
-
}
|
|
327
|
-
static fromText(text, mimeType = "text/plain") {
|
|
328
|
-
return new _File(text, mimeType, true);
|
|
329
|
-
}
|
|
330
|
-
static fromBase64(base64, mimeType) {
|
|
331
|
-
const data = Buffer.from(base64, "base64");
|
|
332
|
-
const isText = isTextMimeType(mimeType);
|
|
333
|
-
return new _File(new Uint8Array(data), mimeType, isText);
|
|
334
|
-
}
|
|
335
|
-
toContentBlock() {
|
|
336
|
-
const uri = this.name ? `file:///${this.name}` : "file:///data";
|
|
337
|
-
if (this.isText) {
|
|
338
|
-
let text;
|
|
339
|
-
if (typeof this.data === "string") {
|
|
340
|
-
text = this.data;
|
|
341
|
-
} else {
|
|
342
|
-
text = new TextDecoder("utf-8").decode(this.data);
|
|
343
|
-
}
|
|
344
|
-
return {
|
|
345
|
-
type: "resource",
|
|
346
|
-
resource: {
|
|
347
|
-
uri,
|
|
348
|
-
mimeType: this.mimeType,
|
|
349
|
-
text
|
|
350
|
-
}
|
|
351
|
-
};
|
|
352
|
-
} else {
|
|
353
|
-
let blob;
|
|
354
|
-
if (typeof this.data === "string") {
|
|
355
|
-
blob = Buffer.from(this.data).toString("base64");
|
|
356
|
-
} else {
|
|
357
|
-
blob = Buffer.from(this.data).toString("base64");
|
|
358
|
-
}
|
|
359
|
-
return {
|
|
360
|
-
type: "resource",
|
|
361
|
-
resource: {
|
|
362
|
-
uri,
|
|
363
|
-
mimeType: this.mimeType,
|
|
364
|
-
blob
|
|
365
|
-
}
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
};
|
|
370
|
-
|
|
371
|
-
// packages/tiny-stdio-mcp-server/src/content/convert.ts
|
|
372
|
-
function convertSingleValue(value) {
|
|
373
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
374
|
-
return { type: "text", text: String(value) };
|
|
375
|
-
}
|
|
376
|
-
if (value === null) {
|
|
377
|
-
return { type: "text", text: "null" };
|
|
378
|
-
}
|
|
379
|
-
if (value instanceof Image) {
|
|
380
|
-
return value.toContentBlock();
|
|
381
|
-
}
|
|
382
|
-
if (value instanceof Audio) {
|
|
383
|
-
return value.toContentBlock();
|
|
384
|
-
}
|
|
385
|
-
if (value instanceof File) {
|
|
386
|
-
return value.toContentBlock();
|
|
387
|
-
}
|
|
388
|
-
if (isContentBlock(value)) {
|
|
389
|
-
return value;
|
|
390
|
-
}
|
|
391
|
-
return { type: "text", text: JSON.stringify(value) };
|
|
392
|
-
}
|
|
393
|
-
function toContentBlocks(result) {
|
|
394
|
-
if (result === void 0) {
|
|
395
|
-
return [];
|
|
396
|
-
}
|
|
397
|
-
if (Array.isArray(result)) {
|
|
398
|
-
return result.flatMap((item) => toContentBlocks(item));
|
|
399
|
-
}
|
|
400
|
-
return [convertSingleValue(result)];
|
|
401
|
-
}
|
|
402
|
-
function isContentBlock(value) {
|
|
403
|
-
if (!("type" in value) || typeof value.type !== "string") {
|
|
404
|
-
return false;
|
|
405
|
-
}
|
|
406
|
-
return value.type === "text" || value.type === "image" || value.type === "audio" || value.type === "resource";
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// packages/tiny-stdio-mcp-server/src/server.ts
|
|
410
|
-
var PROTOCOL_VERSION = "2025-11-25";
|
|
411
|
-
function createServer(options) {
|
|
412
|
-
const tools = /* @__PURE__ */ new Map();
|
|
413
|
-
const notificationListeners = /* @__PURE__ */ new Set();
|
|
414
|
-
let initialized = false;
|
|
415
|
-
const handleMessage = async (method, params) => {
|
|
416
|
-
if (method === "ping") {
|
|
417
|
-
return { result: {} };
|
|
418
|
-
}
|
|
419
|
-
if (method === "initialize") {
|
|
420
|
-
initialized = true;
|
|
421
|
-
const requestedProtocol = typeof params?.protocolVersion === "string" ? params.protocolVersion : null;
|
|
422
|
-
const result = {
|
|
423
|
-
protocolVersion: requestedProtocol ?? PROTOCOL_VERSION,
|
|
424
|
-
capabilities: {
|
|
425
|
-
tools: {
|
|
426
|
-
listChanged: true
|
|
427
|
-
}
|
|
428
|
-
},
|
|
429
|
-
serverInfo: {
|
|
430
|
-
name: options.name,
|
|
431
|
-
version: options.version
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
return { result };
|
|
435
|
-
}
|
|
436
|
-
if (method === "notifications/initialized") {
|
|
437
|
-
return { result: void 0 };
|
|
438
|
-
}
|
|
439
|
-
if (!initialized) {
|
|
440
|
-
return {
|
|
441
|
-
error: {
|
|
442
|
-
code: JSON_RPC_ERROR_CODES.INVALID_REQUEST,
|
|
443
|
-
message: "Server not initialized"
|
|
444
|
-
}
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
if (method === "tools/list") {
|
|
448
|
-
const toolList = [];
|
|
449
|
-
for (const tool of tools.values()) {
|
|
450
|
-
toolList.push({
|
|
451
|
-
name: tool.name,
|
|
452
|
-
description: tool.description,
|
|
453
|
-
inputSchema: tool.inputSchema
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
return { result: { tools: toolList } };
|
|
457
|
-
}
|
|
458
|
-
if (method === "tools/call") {
|
|
459
|
-
const toolName = params?.name;
|
|
460
|
-
const toolArgs = params?.arguments || {};
|
|
461
|
-
if (!toolName) {
|
|
462
|
-
return {
|
|
463
|
-
error: {
|
|
464
|
-
code: JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
465
|
-
message: "Tool name required"
|
|
466
|
-
}
|
|
467
|
-
};
|
|
468
|
-
}
|
|
469
|
-
const tool = tools.get(toolName);
|
|
470
|
-
if (!tool) {
|
|
471
|
-
return {
|
|
472
|
-
error: {
|
|
473
|
-
code: JSON_RPC_ERROR_CODES.INVALID_PARAMS,
|
|
474
|
-
message: `Tool not found: ${toolName}`
|
|
475
|
-
}
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
try {
|
|
479
|
-
const handlerResult = await tool.handler(toolArgs);
|
|
480
|
-
const result = { content: toContentBlocks(handlerResult) };
|
|
481
|
-
return { result };
|
|
482
|
-
} catch (err) {
|
|
483
|
-
if (err instanceof ToolError) {
|
|
484
|
-
return {
|
|
485
|
-
error: {
|
|
486
|
-
code: err.code,
|
|
487
|
-
message: err.message
|
|
488
|
-
}
|
|
489
|
-
};
|
|
490
|
-
}
|
|
491
|
-
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
492
|
-
const result = {
|
|
493
|
-
content: [{ type: "text", text: `Error: ${errorMessage}` }],
|
|
494
|
-
isError: true
|
|
495
|
-
};
|
|
496
|
-
return { result };
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
return {
|
|
500
|
-
error: {
|
|
501
|
-
code: JSON_RPC_ERROR_CODES.METHOD_NOT_FOUND,
|
|
502
|
-
message: "Method not found"
|
|
503
|
-
}
|
|
504
|
-
};
|
|
505
|
-
};
|
|
506
|
-
const processLine = async (line, write) => {
|
|
507
|
-
const parsed = parseMessage(line);
|
|
508
|
-
if (!parsed.success) {
|
|
509
|
-
write(formatErrorResponse(parsed.id, parsed.error) + "\n");
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
const { request, isNotification } = parsed;
|
|
513
|
-
const { result, error } = await server.handleMessage(
|
|
514
|
-
request.method,
|
|
515
|
-
request.params
|
|
516
|
-
);
|
|
517
|
-
if (isNotification) {
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
520
|
-
const requestWithId = request;
|
|
521
|
-
if (error) {
|
|
522
|
-
write(formatErrorResponse(requestWithId.id, error) + "\n");
|
|
523
|
-
} else if (result !== void 0) {
|
|
524
|
-
write(formatSuccessResponse(requestWithId.id, result) + "\n");
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
const broadcastNotification = (method) => {
|
|
528
|
-
const notification = {
|
|
529
|
-
jsonrpc: "2.0",
|
|
530
|
-
method
|
|
531
|
-
};
|
|
532
|
-
for (const listener of notificationListeners) {
|
|
533
|
-
listener(notification);
|
|
534
|
-
}
|
|
535
|
-
};
|
|
536
|
-
const server = {
|
|
537
|
-
tool(name, description, inputSchema, handler) {
|
|
538
|
-
tools.set(name, {
|
|
539
|
-
name,
|
|
540
|
-
description,
|
|
541
|
-
inputSchema,
|
|
542
|
-
handler
|
|
543
|
-
});
|
|
544
|
-
return server;
|
|
545
|
-
},
|
|
546
|
-
onNotification(listener) {
|
|
547
|
-
notificationListeners.add(listener);
|
|
548
|
-
return () => {
|
|
549
|
-
notificationListeners.delete(listener);
|
|
550
|
-
};
|
|
551
|
-
},
|
|
552
|
-
removeTool(name) {
|
|
553
|
-
return tools.delete(name);
|
|
554
|
-
},
|
|
555
|
-
async notifyToolsChanged() {
|
|
556
|
-
if (initialized) {
|
|
557
|
-
broadcastNotification("notifications/tools/list_changed");
|
|
558
|
-
}
|
|
559
|
-
},
|
|
560
|
-
handleMessage,
|
|
561
|
-
async listen() {
|
|
562
|
-
return server.connect({
|
|
563
|
-
readable: process.stdin,
|
|
564
|
-
writable: process.stdout
|
|
565
|
-
});
|
|
566
|
-
},
|
|
567
|
-
async connect(transport) {
|
|
568
|
-
return new Promise((resolve) => {
|
|
569
|
-
const unsubscribe = server.onNotification((notification) => {
|
|
570
|
-
transport.writable.write(`${JSON.stringify(notification)}
|
|
571
|
-
`);
|
|
572
|
-
});
|
|
573
|
-
const rl = readline.createInterface({
|
|
574
|
-
input: transport.readable,
|
|
575
|
-
crlfDelay: Infinity
|
|
576
|
-
});
|
|
577
|
-
rl.on("line", (line) => {
|
|
578
|
-
processLine(line, (data) => transport.writable.write(data));
|
|
579
|
-
});
|
|
580
|
-
rl.on("close", () => {
|
|
581
|
-
unsubscribe();
|
|
582
|
-
resolve();
|
|
583
|
-
});
|
|
584
|
-
});
|
|
585
|
-
},
|
|
586
|
-
async connectSDK(transport) {
|
|
587
|
-
return new Promise((resolve) => {
|
|
588
|
-
const unsubscribe = server.onNotification((notification) => {
|
|
589
|
-
void transport.send(notification);
|
|
590
|
-
});
|
|
591
|
-
transport.onmessage = async (message) => {
|
|
592
|
-
if (!("method" in message)) {
|
|
593
|
-
return;
|
|
594
|
-
}
|
|
595
|
-
if (!("id" in message) || message.id === void 0) {
|
|
596
|
-
await server.handleMessage(message.method, message.params);
|
|
597
|
-
return;
|
|
598
|
-
}
|
|
599
|
-
const request = message;
|
|
600
|
-
const { result, error } = await server.handleMessage(
|
|
601
|
-
request.method,
|
|
602
|
-
request.params
|
|
603
|
-
);
|
|
604
|
-
if (error) {
|
|
605
|
-
const response = {
|
|
606
|
-
jsonrpc: "2.0",
|
|
607
|
-
id: request.id,
|
|
608
|
-
error
|
|
609
|
-
};
|
|
610
|
-
await transport.send(response);
|
|
611
|
-
} else if (result !== void 0) {
|
|
612
|
-
const response = {
|
|
613
|
-
jsonrpc: "2.0",
|
|
614
|
-
id: request.id,
|
|
615
|
-
result
|
|
616
|
-
};
|
|
617
|
-
await transport.send(response);
|
|
618
|
-
}
|
|
619
|
-
};
|
|
620
|
-
transport.onclose = () => {
|
|
621
|
-
unsubscribe();
|
|
622
|
-
resolve();
|
|
623
|
-
};
|
|
624
|
-
transport.start();
|
|
625
|
-
});
|
|
626
|
-
}
|
|
627
|
-
};
|
|
628
|
-
return server;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// packages/cmdkit-schema/src/index.ts
|
|
632
|
-
function withMetadata(schema, jsonSchema) {
|
|
633
|
-
if (schema.description !== void 0) {
|
|
634
|
-
jsonSchema.description = schema.description;
|
|
635
|
-
}
|
|
636
|
-
if (schema.default !== void 0) {
|
|
637
|
-
jsonSchema.default = schema.default;
|
|
638
|
-
}
|
|
639
|
-
if (schema.nullable === true) {
|
|
640
|
-
jsonSchema.nullable = true;
|
|
641
|
-
}
|
|
642
|
-
return jsonSchema;
|
|
643
|
-
}
|
|
644
|
-
function withStringMetadata(schema, jsonSchema) {
|
|
645
|
-
if (schema.minLength !== void 0) {
|
|
646
|
-
jsonSchema.minLength = schema.minLength;
|
|
647
|
-
}
|
|
648
|
-
if (schema.maxLength !== void 0) {
|
|
649
|
-
jsonSchema.maxLength = schema.maxLength;
|
|
650
|
-
}
|
|
651
|
-
if (schema.pattern !== void 0) {
|
|
652
|
-
jsonSchema.pattern = schema.pattern;
|
|
653
|
-
}
|
|
654
|
-
if (schema.format !== void 0) {
|
|
655
|
-
jsonSchema.format = schema.format;
|
|
656
|
-
}
|
|
657
|
-
return withMetadata(schema, jsonSchema);
|
|
658
|
-
}
|
|
659
|
-
function withNumberMetadata(schema, jsonSchema) {
|
|
660
|
-
if (schema.minimum !== void 0) {
|
|
661
|
-
jsonSchema.minimum = schema.minimum;
|
|
662
|
-
}
|
|
663
|
-
if (schema.maximum !== void 0) {
|
|
664
|
-
jsonSchema.maximum = schema.maximum;
|
|
665
|
-
}
|
|
666
|
-
return withMetadata(schema, jsonSchema);
|
|
667
|
-
}
|
|
668
|
-
function withArrayMetadata(schema, jsonSchema) {
|
|
669
|
-
if (schema.minItems !== void 0) {
|
|
670
|
-
jsonSchema.minItems = schema.minItems;
|
|
671
|
-
}
|
|
672
|
-
if (schema.maxItems !== void 0) {
|
|
673
|
-
jsonSchema.maxItems = schema.maxItems;
|
|
674
|
-
}
|
|
675
|
-
return withMetadata(schema, jsonSchema);
|
|
676
|
-
}
|
|
677
|
-
function withObjectMetadata(schema, jsonSchema) {
|
|
678
|
-
if (schema.additionalProperties !== void 0) {
|
|
679
|
-
jsonSchema.additionalProperties = schema.additionalProperties;
|
|
680
|
-
}
|
|
681
|
-
return withMetadata(schema, jsonSchema);
|
|
682
|
-
}
|
|
683
|
-
function getEnumJsonType(values) {
|
|
684
|
-
const [firstValue] = values;
|
|
685
|
-
if (firstValue === void 0) {
|
|
686
|
-
return void 0;
|
|
687
|
-
}
|
|
688
|
-
const firstType = typeof firstValue;
|
|
689
|
-
const isSinglePrimitiveType = values.every((value) => typeof value === firstType);
|
|
690
|
-
if (!isSinglePrimitiveType) {
|
|
691
|
-
return void 0;
|
|
692
|
-
}
|
|
693
|
-
if (firstType === "string" || firstType === "number" || firstType === "boolean") {
|
|
694
|
-
return firstType;
|
|
695
|
-
}
|
|
696
|
-
return void 0;
|
|
697
|
-
}
|
|
698
|
-
function isOptionalSchema(schema) {
|
|
699
|
-
return schema.kind === "optional";
|
|
700
|
-
}
|
|
701
|
-
function unwrapOptional(schema) {
|
|
702
|
-
if (isOptionalSchema(schema)) {
|
|
703
|
-
return unwrapOptional(schema.inner);
|
|
704
|
-
}
|
|
705
|
-
return schema;
|
|
706
|
-
}
|
|
707
|
-
function toJsonSchema(schema) {
|
|
708
|
-
const unwrappedSchema = unwrapOptional(schema);
|
|
709
|
-
switch (unwrappedSchema.kind) {
|
|
710
|
-
case "string":
|
|
711
|
-
return withStringMetadata(unwrappedSchema, { type: "string" });
|
|
712
|
-
case "number":
|
|
713
|
-
return withNumberMetadata(unwrappedSchema, { type: unwrappedSchema.jsonType ?? "number" });
|
|
714
|
-
case "boolean":
|
|
715
|
-
return withMetadata(unwrappedSchema, { type: "boolean" });
|
|
716
|
-
case "enum": {
|
|
717
|
-
const jsonSchema = {
|
|
718
|
-
enum: unwrappedSchema.nullable === true ? [...unwrappedSchema.values, null] : [...unwrappedSchema.values]
|
|
719
|
-
};
|
|
720
|
-
const enumType = unwrappedSchema.jsonType ?? getEnumJsonType(unwrappedSchema.values);
|
|
721
|
-
if (enumType !== void 0) {
|
|
722
|
-
jsonSchema.type = enumType;
|
|
723
|
-
}
|
|
724
|
-
return withMetadata(unwrappedSchema, jsonSchema);
|
|
725
|
-
}
|
|
726
|
-
case "array":
|
|
727
|
-
return withArrayMetadata(unwrappedSchema, {
|
|
728
|
-
type: "array",
|
|
729
|
-
items: toJsonSchema(unwrappedSchema.item)
|
|
730
|
-
});
|
|
731
|
-
case "object": {
|
|
732
|
-
const properties = {};
|
|
733
|
-
const required = [];
|
|
734
|
-
for (const [key, propertySchema] of Object.entries(unwrappedSchema.shape)) {
|
|
735
|
-
properties[key] = toJsonSchema(propertySchema);
|
|
736
|
-
if (!isOptionalSchema(propertySchema)) {
|
|
737
|
-
required.push(key);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
|
-
return withObjectMetadata(unwrappedSchema, {
|
|
741
|
-
type: "object",
|
|
742
|
-
properties,
|
|
743
|
-
required
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
// packages/cmdkit/src/index.ts
|
|
750
|
-
import { fileURLToPath } from "node:url";
|
|
751
|
-
var UserError = class extends Error {
|
|
752
|
-
constructor(message) {
|
|
753
|
-
super(message);
|
|
754
|
-
this.name = "UserError";
|
|
755
|
-
}
|
|
756
|
-
};
|
|
757
|
-
function parseSimpleSemver(value) {
|
|
758
|
-
const parts = value.split(".");
|
|
759
|
-
if (parts.length !== 3) {
|
|
760
|
-
return void 0;
|
|
761
|
-
}
|
|
762
|
-
const parsed = parts.map((part) => {
|
|
763
|
-
if (part.length === 0) {
|
|
764
|
-
return Number.NaN;
|
|
765
|
-
}
|
|
766
|
-
for (const char of part) {
|
|
767
|
-
if (char < "0" || char > "9") {
|
|
768
|
-
return Number.NaN;
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
return Number(part);
|
|
772
|
-
});
|
|
773
|
-
if (parsed.some((part) => !Number.isInteger(part) || part < 0)) {
|
|
774
|
-
return void 0;
|
|
775
|
-
}
|
|
776
|
-
return parsed;
|
|
777
|
-
}
|
|
778
|
-
function parseMinimumApiVersion(requirement) {
|
|
779
|
-
if (!requirement.startsWith(">=")) {
|
|
780
|
-
return void 0;
|
|
781
|
-
}
|
|
782
|
-
return parseSimpleSemver(requirement.slice(2).trim());
|
|
783
|
-
}
|
|
784
|
-
function compareSemver(left, right) {
|
|
785
|
-
for (let index = 0; index < left.length; index += 1) {
|
|
786
|
-
if (left[index] === right[index]) {
|
|
787
|
-
continue;
|
|
788
|
-
}
|
|
789
|
-
return left[index] > right[index] ? 1 : -1;
|
|
790
|
-
}
|
|
791
|
-
return 0;
|
|
792
|
-
}
|
|
793
|
-
function resolveCommandSecrets(command, env = process.env) {
|
|
794
|
-
const secrets = {};
|
|
795
|
-
for (const [name, secret] of Object.entries(command.secrets)) {
|
|
796
|
-
const value = env[secret.env];
|
|
797
|
-
if (value === void 0 && secret.optional !== true) {
|
|
798
|
-
const details = secret.description ? `
|
|
799
|
-
${secret.description}` : "";
|
|
800
|
-
throw new UserError(`Error: Missing required secret ${secret.env}${details}`);
|
|
801
|
-
}
|
|
802
|
-
secrets[name] = value;
|
|
803
|
-
}
|
|
804
|
-
return secrets;
|
|
805
|
-
}
|
|
806
|
-
async function assertCommandRequirements(command, context, options = {}) {
|
|
807
|
-
const requires = command.requires;
|
|
808
|
-
if (requires === void 0) {
|
|
809
|
-
return;
|
|
810
|
-
}
|
|
811
|
-
const env = options.env ?? process.env;
|
|
812
|
-
const authEnvVar = options.authEnvVar ?? "POE_API_KEY";
|
|
813
|
-
if (requires.auth === true && env[authEnvVar] === void 0) {
|
|
814
|
-
throw new UserError(
|
|
815
|
-
`Error: Command "${command.name}" requires authentication.
|
|
816
|
-
Run 'poe-code login' first.`
|
|
817
|
-
);
|
|
818
|
-
}
|
|
819
|
-
if (requires.apiVersion !== void 0) {
|
|
820
|
-
const minimumVersion = parseMinimumApiVersion(requires.apiVersion);
|
|
821
|
-
if (minimumVersion === void 0) {
|
|
822
|
-
throw new UserError(
|
|
823
|
-
`Error: Command "${command.name}" has invalid apiVersion requirement "${requires.apiVersion}". Expected format ">=X.Y.Z".`
|
|
824
|
-
);
|
|
825
|
-
}
|
|
826
|
-
if (options.apiVersion === void 0) {
|
|
827
|
-
throw new UserError(
|
|
828
|
-
`Error: Command "${command.name}" requires API version ${requires.apiVersion}, but no runner API version was provided.`
|
|
829
|
-
);
|
|
830
|
-
}
|
|
831
|
-
const runnerVersion = parseSimpleSemver(options.apiVersion);
|
|
832
|
-
if (runnerVersion === void 0) {
|
|
833
|
-
throw new UserError(
|
|
834
|
-
`Error: Command "${command.name}" requires API version ${requires.apiVersion}, but runner API version "${options.apiVersion}" is not valid semver.`
|
|
835
|
-
);
|
|
836
|
-
}
|
|
837
|
-
if (compareSemver(runnerVersion, minimumVersion) < 0) {
|
|
838
|
-
throw new UserError(
|
|
839
|
-
`Error: Command "${command.name}" requires API version ${requires.apiVersion}, but runner API version is ${options.apiVersion}.`
|
|
840
|
-
);
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
const checkResult = await requires.check?.(context);
|
|
844
|
-
if (checkResult && !checkResult.ok) {
|
|
845
|
-
throw new UserError(checkResult.message ?? "Command precondition failed.");
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
// packages/cmdkit/src/number-schema.ts
|
|
850
|
-
function isValidNumberSchemaValue(value, schema) {
|
|
851
|
-
return typeof value === "number" && Number.isFinite(value) && (schema.jsonType !== "integer" || Number.isInteger(value));
|
|
852
|
-
}
|
|
853
|
-
function getExpectedNumberDescription(schema) {
|
|
854
|
-
return schema.jsonType === "integer" ? "an integer" : "a number";
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
// packages/cmdkit/src/schema-scope.ts
|
|
858
|
-
function filterSchemaForScope(schema, scope) {
|
|
859
|
-
if (schema.scope !== void 0 && !schema.scope.includes(scope)) {
|
|
860
|
-
return void 0;
|
|
861
|
-
}
|
|
862
|
-
switch (schema.kind) {
|
|
863
|
-
case "optional": {
|
|
864
|
-
const inner = filterSchemaForScope(schema.inner, scope);
|
|
865
|
-
if (inner === void 0) {
|
|
866
|
-
return void 0;
|
|
867
|
-
}
|
|
868
|
-
if (inner.requiredScopes?.includes(scope)) {
|
|
869
|
-
return inner;
|
|
870
|
-
}
|
|
871
|
-
return { ...schema, inner };
|
|
872
|
-
}
|
|
873
|
-
case "array": {
|
|
874
|
-
const item = filterSchemaForScope(schema.item, scope);
|
|
875
|
-
return item === void 0 ? void 0 : { ...schema, item };
|
|
876
|
-
}
|
|
877
|
-
case "string":
|
|
878
|
-
case "number":
|
|
879
|
-
case "boolean":
|
|
880
|
-
case "enum":
|
|
881
|
-
return schema;
|
|
882
|
-
case "object":
|
|
883
|
-
return {
|
|
884
|
-
...schema,
|
|
885
|
-
shape: Object.fromEntries(
|
|
886
|
-
Object.entries(schema.shape).flatMap(([key, childSchema]) => {
|
|
887
|
-
const filtered = filterSchemaForScope(childSchema, scope);
|
|
888
|
-
return filtered === void 0 ? [] : [[key, filtered]];
|
|
889
|
-
})
|
|
890
|
-
)
|
|
891
|
-
};
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
// packages/cmdkit/src/mcp.ts
|
|
896
|
-
var RESERVED_SERVICE_NAMES = /* @__PURE__ */ new Set(["params", "secrets", "fetch", "fs", "env", "progress"]);
|
|
897
|
-
function normalizeRoots(roots) {
|
|
898
|
-
if (!Array.isArray(roots)) {
|
|
899
|
-
return roots;
|
|
900
|
-
}
|
|
901
|
-
return {
|
|
902
|
-
kind: "group",
|
|
903
|
-
name: "",
|
|
904
|
-
aliases: [],
|
|
905
|
-
secrets: {},
|
|
906
|
-
children: roots
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
function splitWords(value) {
|
|
910
|
-
const words = [];
|
|
911
|
-
let current = "";
|
|
912
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
913
|
-
const char = value[index] ?? "";
|
|
914
|
-
const lower = char.toLowerCase();
|
|
915
|
-
const upper = char.toUpperCase();
|
|
916
|
-
const isSeparator = char === "-" || char === "_" || char === " " || char === ".";
|
|
917
|
-
if (isSeparator) {
|
|
918
|
-
if (current.length > 0) {
|
|
919
|
-
words.push(current.toLowerCase());
|
|
920
|
-
current = "";
|
|
921
|
-
}
|
|
922
|
-
continue;
|
|
923
|
-
}
|
|
924
|
-
const isUppercase = char !== lower && char === upper;
|
|
925
|
-
const previous = value[index - 1];
|
|
926
|
-
const next = value[index + 1];
|
|
927
|
-
const previousIsLowercase = previous !== void 0 && previous === previous.toLowerCase() && previous !== previous.toUpperCase();
|
|
928
|
-
const nextIsLowercase = next !== void 0 && next === next.toLowerCase() && next !== next.toUpperCase();
|
|
929
|
-
if (isUppercase && current.length > 0 && (previousIsLowercase || nextIsLowercase)) {
|
|
930
|
-
words.push(current.toLowerCase());
|
|
931
|
-
current = char;
|
|
932
|
-
continue;
|
|
933
|
-
}
|
|
934
|
-
current += char;
|
|
935
|
-
}
|
|
936
|
-
if (current.length > 0) {
|
|
937
|
-
words.push(current.toLowerCase());
|
|
938
|
-
}
|
|
939
|
-
return words;
|
|
940
|
-
}
|
|
941
|
-
function formatSegment(segment, casing) {
|
|
942
|
-
const words = splitWords(segment);
|
|
943
|
-
if (casing === "snake") {
|
|
944
|
-
return words.join("_");
|
|
945
|
-
}
|
|
946
|
-
return words.map(
|
|
947
|
-
(word, index) => index === 0 ? word : `${word[0]?.toUpperCase() ?? ""}${word.slice(1)}`
|
|
948
|
-
).join("");
|
|
949
|
-
}
|
|
950
|
-
function unwrapOptional2(schema) {
|
|
951
|
-
if (schema.kind === "optional") {
|
|
952
|
-
return unwrapOptional2(schema.inner);
|
|
953
|
-
}
|
|
954
|
-
return schema;
|
|
955
|
-
}
|
|
956
|
-
function isOptional(schema) {
|
|
957
|
-
return schema.kind === "optional";
|
|
958
|
-
}
|
|
959
|
-
function isPlainObject(value) {
|
|
960
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
961
|
-
}
|
|
962
|
-
function createFs() {
|
|
963
|
-
return {
|
|
964
|
-
readFile: async (path, encoding = "utf8") => readFile(path, { encoding }),
|
|
965
|
-
writeFile: async (path, contents) => {
|
|
966
|
-
await writeFile(path, contents);
|
|
967
|
-
},
|
|
968
|
-
exists: async (path) => {
|
|
969
|
-
try {
|
|
970
|
-
await access(path);
|
|
971
|
-
return true;
|
|
972
|
-
} catch {
|
|
973
|
-
return false;
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
};
|
|
977
|
-
}
|
|
978
|
-
function createEnv(values = process.env) {
|
|
979
|
-
return {
|
|
980
|
-
get(key) {
|
|
981
|
-
return values[key];
|
|
982
|
-
}
|
|
983
|
-
};
|
|
984
|
-
}
|
|
985
|
-
function validateServices(services) {
|
|
986
|
-
for (const name of Object.keys(services)) {
|
|
987
|
-
if (RESERVED_SERVICE_NAMES.has(name)) {
|
|
988
|
-
throw new Error(`Service name "${name}" is reserved. Choose a different name.`);
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
function applySchemaCasing(schema, casing) {
|
|
993
|
-
if (schema.type !== "object" || schema.properties === void 0) {
|
|
994
|
-
if (schema.type === "array" && schema.items !== void 0) {
|
|
995
|
-
return {
|
|
996
|
-
...schema,
|
|
997
|
-
items: applySchemaCasing(schema.items, casing)
|
|
998
|
-
};
|
|
999
|
-
}
|
|
1000
|
-
return schema;
|
|
1001
|
-
}
|
|
1002
|
-
const properties = Object.fromEntries(
|
|
1003
|
-
Object.entries(schema.properties).map(([key, value]) => [
|
|
1004
|
-
formatSegment(key, casing),
|
|
1005
|
-
applySchemaCasing(value, casing)
|
|
1006
|
-
])
|
|
1007
|
-
);
|
|
1008
|
-
const required = schema.required?.map((key) => formatSegment(key, casing));
|
|
1009
|
-
return {
|
|
1010
|
-
...schema,
|
|
1011
|
-
properties,
|
|
1012
|
-
...required === void 0 ? {} : { required }
|
|
1013
|
-
};
|
|
1014
|
-
}
|
|
1015
|
-
function collectParamSummaries(schema, casing, path = [], inheritedOptional = false) {
|
|
1016
|
-
const summaries = [];
|
|
1017
|
-
for (const [key, rawChildSchema] of Object.entries(schema.shape)) {
|
|
1018
|
-
const childSchema = unwrapOptional2(rawChildSchema);
|
|
1019
|
-
const nextPath = [...path, formatSegment(key, casing)];
|
|
1020
|
-
const optional = inheritedOptional || isOptional(rawChildSchema);
|
|
1021
|
-
if (childSchema.kind === "object") {
|
|
1022
|
-
summaries.push(...collectParamSummaries(childSchema, casing, nextPath, optional));
|
|
1023
|
-
continue;
|
|
1024
|
-
}
|
|
1025
|
-
summaries.push(`${nextPath.join(".")}${optional ? "" : " (required)"}`);
|
|
1026
|
-
}
|
|
1027
|
-
return summaries;
|
|
1028
|
-
}
|
|
1029
|
-
function buildToolDescription(description, params, casing) {
|
|
1030
|
-
const summary = collectParamSummaries(params, casing);
|
|
1031
|
-
const parameterSummary = summary.length === 0 ? "" : `Parameters: ${summary.join(", ")}.`;
|
|
1032
|
-
if (description === void 0) {
|
|
1033
|
-
return parameterSummary;
|
|
1034
|
-
}
|
|
1035
|
-
if (parameterSummary.length === 0) {
|
|
1036
|
-
return description;
|
|
1037
|
-
}
|
|
1038
|
-
return `${description} ${parameterSummary}`;
|
|
1039
|
-
}
|
|
1040
|
-
function matchesAllowlist(toolName, allowlist) {
|
|
1041
|
-
if (allowlist === void 0) {
|
|
1042
|
-
return true;
|
|
1043
|
-
}
|
|
1044
|
-
const segments = toolName.split("__");
|
|
1045
|
-
const candidates = segments.map((_segment, index) => segments.slice(0, index + 1).join("__"));
|
|
1046
|
-
return candidates.some((candidate) => allowlist.includes(candidate));
|
|
1047
|
-
}
|
|
1048
|
-
function formatToolName(path) {
|
|
1049
|
-
return path.map((segment) => formatSegment(segment, "snake")).join("__");
|
|
1050
|
-
}
|
|
1051
|
-
function enumerateTools(root, casing, allowlist) {
|
|
1052
|
-
const tools = [];
|
|
1053
|
-
function visit(node, path) {
|
|
1054
|
-
if (node.kind === "command") {
|
|
1055
|
-
if (!node.scope.includes("mcp")) {
|
|
1056
|
-
return;
|
|
1057
|
-
}
|
|
1058
|
-
const name = formatToolName([...path, node.name]);
|
|
1059
|
-
const params = filterSchemaForScope(node.params, "mcp");
|
|
1060
|
-
if (!matchesAllowlist(name, allowlist)) {
|
|
1061
|
-
return;
|
|
1062
|
-
}
|
|
1063
|
-
if (params === void 0 || params.kind !== "object") {
|
|
1064
|
-
throw new Error(`Bug: command "${name}" must define an object params schema for MCP.`);
|
|
1065
|
-
}
|
|
1066
|
-
tools.push({
|
|
1067
|
-
command: node,
|
|
1068
|
-
name,
|
|
1069
|
-
description: buildToolDescription(node.description, params, casing),
|
|
1070
|
-
inputSchema: applySchemaCasing(toJsonSchema(params), casing)
|
|
1071
|
-
});
|
|
1072
|
-
return;
|
|
1073
|
-
}
|
|
1074
|
-
const nextPath = [...path, node.name];
|
|
1075
|
-
for (const child of node.children) {
|
|
1076
|
-
visit(child, nextPath);
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
const rootPath = root.name.length === 0 ? [] : [root.name];
|
|
1080
|
-
for (const child of root.children) {
|
|
1081
|
-
visit(child, rootPath);
|
|
1082
|
-
}
|
|
1083
|
-
return tools;
|
|
1084
|
-
}
|
|
1085
|
-
function validateEnum(value, schema, label) {
|
|
1086
|
-
if (!schema.values.includes(value)) {
|
|
1087
|
-
throw new UserError(
|
|
1088
|
-
`Invalid value for "${label}". Expected one of: ${schema.values.map((candidate) => String(candidate)).join(", ")}.`
|
|
1089
|
-
);
|
|
1090
|
-
}
|
|
1091
|
-
return value;
|
|
1092
|
-
}
|
|
1093
|
-
function validateSchemaValue(schema, value, casing, label) {
|
|
1094
|
-
const unwrappedSchema = unwrapOptional2(schema);
|
|
1095
|
-
if (value === null && unwrappedSchema.nullable === true) {
|
|
1096
|
-
return null;
|
|
1097
|
-
}
|
|
1098
|
-
switch (unwrappedSchema.kind) {
|
|
1099
|
-
case "string":
|
|
1100
|
-
if (typeof value !== "string") {
|
|
1101
|
-
throw new UserError(`Invalid value for "${label}". Expected a string.`);
|
|
1102
|
-
}
|
|
1103
|
-
return value;
|
|
1104
|
-
case "number":
|
|
1105
|
-
if (!isValidNumberSchemaValue(value, unwrappedSchema)) {
|
|
1106
|
-
throw new UserError(
|
|
1107
|
-
`Invalid value for "${label}". Expected ${getExpectedNumberDescription(unwrappedSchema)}.`
|
|
1108
|
-
);
|
|
1109
|
-
}
|
|
1110
|
-
return value;
|
|
1111
|
-
case "boolean":
|
|
1112
|
-
if (typeof value !== "boolean") {
|
|
1113
|
-
throw new UserError(`Invalid value for "${label}". Expected a boolean.`);
|
|
1114
|
-
}
|
|
1115
|
-
return value;
|
|
1116
|
-
case "enum":
|
|
1117
|
-
return validateEnum(value, unwrappedSchema, label);
|
|
1118
|
-
case "array":
|
|
1119
|
-
if (!Array.isArray(value)) {
|
|
1120
|
-
throw new UserError(`Invalid value for "${label}". Expected an array.`);
|
|
1121
|
-
}
|
|
1122
|
-
return value.map(
|
|
1123
|
-
(item, index) => validateSchemaValue(unwrappedSchema.item, item, casing, `${label}[${index}]`)
|
|
1124
|
-
);
|
|
1125
|
-
case "object":
|
|
1126
|
-
return validateObjectSchema(unwrappedSchema, value, casing, label);
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
function validateObjectSchema(schema, value, casing, label) {
|
|
1130
|
-
if (!isPlainObject(value)) {
|
|
1131
|
-
throw new UserError(`Invalid value for "${label}". Expected an object.`);
|
|
1132
|
-
}
|
|
1133
|
-
const result = {};
|
|
1134
|
-
const expectedKeys = /* @__PURE__ */ new Map();
|
|
1135
|
-
for (const [key, childSchema] of Object.entries(schema.shape)) {
|
|
1136
|
-
expectedKeys.set(formatSegment(key, casing), [key, childSchema]);
|
|
1137
|
-
}
|
|
1138
|
-
for (const key of Object.keys(value)) {
|
|
1139
|
-
if (!expectedKeys.has(key)) {
|
|
1140
|
-
const fieldLabel = label.length === 0 ? key : `${label}.${key}`;
|
|
1141
|
-
throw new UserError(`Unexpected parameter "${fieldLabel}".`);
|
|
1142
|
-
}
|
|
1143
|
-
}
|
|
1144
|
-
for (const [inputKey, [outputKey, rawChildSchema]] of expectedKeys.entries()) {
|
|
1145
|
-
const childSchema = unwrapOptional2(rawChildSchema);
|
|
1146
|
-
const hasValue = Object.prototype.hasOwnProperty.call(value, inputKey);
|
|
1147
|
-
const fieldLabel = label.length === 0 ? inputKey : `${label}.${inputKey}`;
|
|
1148
|
-
if (!hasValue) {
|
|
1149
|
-
if (childSchema.default !== void 0) {
|
|
1150
|
-
result[outputKey] = childSchema.default;
|
|
1151
|
-
continue;
|
|
1152
|
-
}
|
|
1153
|
-
if (isOptional(rawChildSchema)) {
|
|
1154
|
-
continue;
|
|
1155
|
-
}
|
|
1156
|
-
throw new UserError(`Missing required parameter "${fieldLabel}".`);
|
|
1157
|
-
}
|
|
1158
|
-
result[outputKey] = validateSchemaValue(rawChildSchema, value[inputKey], casing, fieldLabel);
|
|
1159
|
-
}
|
|
1160
|
-
return result;
|
|
1161
|
-
}
|
|
1162
|
-
function validateToolArguments(schema, argumentsValue, casing) {
|
|
1163
|
-
return validateObjectSchema(schema, argumentsValue ?? {}, casing, "");
|
|
1164
|
-
}
|
|
1165
|
-
function isContentBlock2(value) {
|
|
1166
|
-
if (!isPlainObject(value) || typeof value.type !== "string") {
|
|
1167
|
-
return false;
|
|
1168
|
-
}
|
|
1169
|
-
return value.type === "text" || value.type === "image" || value.type === "audio" || value.type === "resource";
|
|
1170
|
-
}
|
|
1171
|
-
function toToolContent(result) {
|
|
1172
|
-
if (result === void 0) {
|
|
1173
|
-
return [];
|
|
1174
|
-
}
|
|
1175
|
-
if (Array.isArray(result)) {
|
|
1176
|
-
return result.flatMap((item) => toToolContent(item));
|
|
1177
|
-
}
|
|
1178
|
-
if (typeof result === "string" || typeof result === "number" || typeof result === "boolean") {
|
|
1179
|
-
return [{ type: "text", text: String(result) }];
|
|
1180
|
-
}
|
|
1181
|
-
if (result === null) {
|
|
1182
|
-
return [{ type: "text", text: "null" }];
|
|
1183
|
-
}
|
|
1184
|
-
if (isContentBlock2(result)) {
|
|
1185
|
-
return [result];
|
|
1186
|
-
}
|
|
1187
|
-
return [{ type: "text", text: JSON.stringify(result) }];
|
|
1188
|
-
}
|
|
1189
|
-
function toToolError(error) {
|
|
1190
|
-
if (error instanceof ToolError) {
|
|
1191
|
-
return error;
|
|
1192
|
-
}
|
|
1193
|
-
if (error instanceof UserError) {
|
|
1194
|
-
return new ToolError(JSON_RPC_ERROR_CODES.INVALID_PARAMS, error.message);
|
|
1195
|
-
}
|
|
1196
|
-
if (error instanceof Error) {
|
|
1197
|
-
return new ToolError(JSON_RPC_ERROR_CODES.INTERNAL_ERROR, error.message);
|
|
1198
|
-
}
|
|
1199
|
-
return new ToolError(JSON_RPC_ERROR_CODES.INTERNAL_ERROR, String(error));
|
|
1200
|
-
}
|
|
1201
|
-
function createMCPServer(roots, options) {
|
|
1202
|
-
const root = normalizeRoots(roots);
|
|
1203
|
-
const casing = options.casing ?? "snake";
|
|
1204
|
-
const services = options.services ?? {};
|
|
1205
|
-
validateServices(services);
|
|
1206
|
-
const tools = enumerateTools(root, casing, options.tools);
|
|
1207
|
-
const server = createServer({ name: options.name, version: options.version });
|
|
1208
|
-
for (const tool of tools) {
|
|
1209
|
-
server.tool(
|
|
1210
|
-
tool.name,
|
|
1211
|
-
tool.description,
|
|
1212
|
-
tool.inputSchema,
|
|
1213
|
-
async (argumentsValue) => {
|
|
1214
|
-
try {
|
|
1215
|
-
const secrets = resolveCommandSecrets(tool.command);
|
|
1216
|
-
const baseContext = {
|
|
1217
|
-
...services,
|
|
1218
|
-
secrets,
|
|
1219
|
-
fetch: globalThis.fetch,
|
|
1220
|
-
fs: createFs(),
|
|
1221
|
-
env: createEnv(),
|
|
1222
|
-
progress() {
|
|
1223
|
-
return void 0;
|
|
1224
|
-
}
|
|
1225
|
-
};
|
|
1226
|
-
await assertCommandRequirements(tool.command, { ...baseContext, params: void 0 });
|
|
1227
|
-
const params = validateToolArguments(tool.command.params, argumentsValue, casing);
|
|
1228
|
-
const result = await tool.command.handler({
|
|
1229
|
-
...baseContext,
|
|
1230
|
-
params
|
|
1231
|
-
});
|
|
1232
|
-
return toToolContent(result);
|
|
1233
|
-
} catch (error) {
|
|
1234
|
-
throw toToolError(error);
|
|
1235
|
-
}
|
|
1236
|
-
}
|
|
1237
|
-
);
|
|
1238
|
-
}
|
|
1239
|
-
return {
|
|
1240
|
-
...server,
|
|
1241
|
-
connect(transport) {
|
|
1242
|
-
return server.connectSDK(transport);
|
|
1243
|
-
}
|
|
1244
|
-
};
|
|
1245
|
-
}
|
|
1246
|
-
async function runMCP(roots, options) {
|
|
1247
|
-
const server = createMCPServer(roots, options);
|
|
1248
|
-
await server.listen();
|
|
1249
|
-
}
|
|
1250
|
-
export {
|
|
1251
|
-
createMCPServer,
|
|
1252
|
-
runMCP
|
|
1253
|
-
};
|
|
1254
|
-
//# sourceMappingURL=mcp.js.map
|