@01.software/cli 0.8.0 → 0.10.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/dist/index.js +208 -31
- package/dist/index.js.map +1 -1
- package/dist/mcp/{chunk-45ZCPS57.js → chunk-CADO6WG6.js} +1358 -854
- package/dist/mcp/chunk-CADO6WG6.js.map +1 -0
- package/dist/mcp/http.js +57 -30
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/stdio.js +1 -1
- package/dist/mcp/vercel.js +1396 -883
- package/package.json +3 -3
- package/dist/mcp/chunk-45ZCPS57.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -128,7 +128,7 @@ ${entry}
|
|
|
128
128
|
// src/lib/output.ts
|
|
129
129
|
import pc from "picocolors";
|
|
130
130
|
|
|
131
|
-
// src/lib/
|
|
131
|
+
// src/lib/admin-error.ts
|
|
132
132
|
var PERMISSION_CODES = [
|
|
133
133
|
"tenant_mismatch",
|
|
134
134
|
"account_suspended",
|
|
@@ -241,7 +241,7 @@ var CLI_I18N_KO = {
|
|
|
241
241
|
PassApiKey: "`--api-key <token>` \uC635\uC158\uC744 \uC804\uB2EC\uD558\uAC70\uB098,",
|
|
242
242
|
SetEnvVars: "`SOFTWARE_PUBLISHABLE_KEY` / `SOFTWARE_SECRET_KEY` \uD658\uACBD \uBCC0\uC218\uB97C \uC124\uC815\uD558\uC138\uC694.",
|
|
243
243
|
InvalidApiKeyFormat: "API \uD0A4 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. `sk01_` \uB610\uB294 `pat01_` \uD1A0\uD070\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.",
|
|
244
|
-
|
|
244
|
+
RetiredHexCredentialsRejected: "\uC774\uC804 hex \uC790\uACA9 \uC99D\uBA85\uC740 \uB354 \uC774\uC0C1 \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 `01 login`\uC73C\uB85C \uB2E4\uC2DC \uC778\uC99D\uD558\uC138\uC694.",
|
|
245
245
|
InvalidJsonObject: "`--{{label}}` \uC778\uC790\uB294 JSON \uAC1D\uCCB4\uC5EC\uC57C \uD569\uB2C8\uB2E4.",
|
|
246
246
|
InvalidJsonArray: "`--{{label}}` \uC778\uC790\uB294 JSON \uBC30\uC5F4\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4.",
|
|
247
247
|
InvalidJsonValue: "`--{{label}}` \uC778\uC790\uC758 JSON \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {{value}}",
|
|
@@ -273,7 +273,7 @@ var CLI_I18N_EN = {
|
|
|
273
273
|
PassApiKey: "pass `--api-key <token>`, or",
|
|
274
274
|
SetEnvVars: "set `SOFTWARE_PUBLISHABLE_KEY` and `SOFTWARE_SECRET_KEY` environment variables.",
|
|
275
275
|
InvalidApiKeyFormat: "Invalid API key format. Expected `sk01_` or `pat01_` token.",
|
|
276
|
-
|
|
276
|
+
RetiredHexCredentialsRejected: "Retired hex credentials are no longer accepted \u2014 run `01 login` to re-authenticate.",
|
|
277
277
|
InvalidJsonObject: "--{{label}} must be a JSON object.",
|
|
278
278
|
InvalidJsonArray: "--{{label}} must be a JSON array.",
|
|
279
279
|
InvalidJsonValue: "Invalid JSON for --{{label}}: {{value}}",
|
|
@@ -477,7 +477,7 @@ function resolveClient(apiKeyFlag) {
|
|
|
477
477
|
code: "credential_invalid",
|
|
478
478
|
detail: {
|
|
479
479
|
message: t("InvalidApiKeyFormat"),
|
|
480
|
-
suggestion: t("
|
|
480
|
+
suggestion: t("RetiredHexCredentialsRejected")
|
|
481
481
|
}
|
|
482
482
|
});
|
|
483
483
|
}
|
|
@@ -515,6 +515,40 @@ function failArg(label, value, expectedKind) {
|
|
|
515
515
|
detail: { message, value, field: label }
|
|
516
516
|
});
|
|
517
517
|
}
|
|
518
|
+
function stringifyValue(value) {
|
|
519
|
+
try {
|
|
520
|
+
return JSON.stringify(value);
|
|
521
|
+
} catch {
|
|
522
|
+
return String(value);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function formatSchemaIssues(label, issues) {
|
|
526
|
+
return issues.map((issue) => {
|
|
527
|
+
const path = issue.path.length > 0 ? issue.path.join(".") : label;
|
|
528
|
+
return `${path}: ${issue.message}`;
|
|
529
|
+
}).join("; ");
|
|
530
|
+
}
|
|
531
|
+
function parseWithSchema(value, label, schema) {
|
|
532
|
+
const parsed = schema.safeParse(value);
|
|
533
|
+
if (parsed.success) return parsed.data;
|
|
534
|
+
const issues = parsed.error.issues.map((issue) => ({
|
|
535
|
+
path: issue.path.map(String),
|
|
536
|
+
message: issue.message
|
|
537
|
+
}));
|
|
538
|
+
const message = `Invalid value for --${label}: ${formatSchemaIssues(label, issues)}`;
|
|
539
|
+
exitWithError({
|
|
540
|
+
type: "validation",
|
|
541
|
+
code: "invalid_argument",
|
|
542
|
+
field: label,
|
|
543
|
+
message,
|
|
544
|
+
detail: {
|
|
545
|
+
message,
|
|
546
|
+
value: stringifyValue(value),
|
|
547
|
+
field: label,
|
|
548
|
+
issues
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
}
|
|
518
552
|
function parseJson(value, label, options = {}) {
|
|
519
553
|
let parsed;
|
|
520
554
|
try {
|
|
@@ -736,15 +770,65 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
736
770
|
}
|
|
737
771
|
|
|
738
772
|
// src/commands/order.ts
|
|
773
|
+
import { z } from "zod";
|
|
774
|
+
var idSchema = z.union([z.string().min(1), z.number()]).transform(String);
|
|
775
|
+
var customerSnapshotSchema = z.object({
|
|
776
|
+
email: z.string().email("Invalid email format"),
|
|
777
|
+
name: z.string().optional(),
|
|
778
|
+
phone: z.string().optional()
|
|
779
|
+
}).strict();
|
|
780
|
+
var shippingAddressSchema = z.object({
|
|
781
|
+
postalCode: z.string().optional(),
|
|
782
|
+
address: z.string().optional(),
|
|
783
|
+
detailAddress: z.string().optional(),
|
|
784
|
+
deliveryMessage: z.string().optional(),
|
|
785
|
+
recipientName: z.string().optional(),
|
|
786
|
+
phone: z.string().optional()
|
|
787
|
+
}).strict();
|
|
788
|
+
var orderItemSchema = z.object({
|
|
789
|
+
product: idSchema,
|
|
790
|
+
variant: idSchema,
|
|
791
|
+
option: idSchema,
|
|
792
|
+
quantity: z.number().int().positive("quantity must be a positive integer"),
|
|
793
|
+
unitPrice: z.number().optional(),
|
|
794
|
+
totalPrice: z.number().optional()
|
|
795
|
+
}).strict();
|
|
796
|
+
var orderItemsSchema = z.array(orderItemSchema).min(1, "At least one order item is required").max(100, "Maximum 100 items per order");
|
|
797
|
+
var orderStatusSchema = z.enum([
|
|
798
|
+
"pending",
|
|
799
|
+
"paid",
|
|
800
|
+
"failed",
|
|
801
|
+
"canceled",
|
|
802
|
+
"preparing",
|
|
803
|
+
"shipped",
|
|
804
|
+
"delivered",
|
|
805
|
+
"confirmed"
|
|
806
|
+
]);
|
|
807
|
+
var fulfillmentItemsSchema = z.array(
|
|
808
|
+
z.object({
|
|
809
|
+
orderItem: idSchema,
|
|
810
|
+
quantity: z.number().int().positive("quantity must be a positive integer")
|
|
811
|
+
}).strict()
|
|
812
|
+
).min(1, "At least one fulfillment item is required").max(100, "Maximum 100 items per fulfillment");
|
|
739
813
|
function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
740
814
|
const order = program2.command("order").description("Order management");
|
|
741
815
|
order.command("create").description("Create a new order").option("--payment-id <id>", "Payment ID").requiredOption("--order-number <num>", "Order number").requiredOption("--email <email>", "Customer email").option("--customer <id>", "Customer ID").option("--name <name>", "Customer name").option("--phone <phone>", "Customer phone").requiredOption("--shipping-address <json>", "Shipping address (JSON)").requiredOption("--products <json>", "Order products array (JSON)").requiredOption("--total-amount <n>", "Total amount", parseFloat).option("--dry-run", "Validate inputs without executing").action(async (opts) => {
|
|
742
816
|
try {
|
|
743
|
-
const shippingAddress =
|
|
744
|
-
opts.shippingAddress,
|
|
745
|
-
"shipping-address"
|
|
817
|
+
const shippingAddress = parseWithSchema(
|
|
818
|
+
parseJson(opts.shippingAddress, "shipping-address"),
|
|
819
|
+
"shipping-address",
|
|
820
|
+
shippingAddressSchema
|
|
821
|
+
);
|
|
822
|
+
const orderItems = parseWithSchema(
|
|
823
|
+
parseJsonArray(opts.products, "products"),
|
|
824
|
+
"products",
|
|
825
|
+
orderItemsSchema
|
|
826
|
+
);
|
|
827
|
+
const totalAmount = parseWithSchema(
|
|
828
|
+
opts.totalAmount,
|
|
829
|
+
"total-amount",
|
|
830
|
+
z.number().nonnegative("totalAmount must be non-negative")
|
|
746
831
|
);
|
|
747
|
-
const orderItems = parseJsonArray(opts.products, "products");
|
|
748
832
|
const data = {
|
|
749
833
|
pgPaymentId: opts.paymentId,
|
|
750
834
|
orderNumber: opts.orderNumber,
|
|
@@ -756,7 +840,7 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
756
840
|
customer: opts.customer,
|
|
757
841
|
shippingAddress,
|
|
758
842
|
orderItems,
|
|
759
|
-
totalAmount
|
|
843
|
+
totalAmount
|
|
760
844
|
};
|
|
761
845
|
if (opts.dryRun) {
|
|
762
846
|
printResult(
|
|
@@ -787,7 +871,8 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
787
871
|
});
|
|
788
872
|
order.command("update <orderNumber>").description("Update order status").requiredOption("--status <status>", "New status").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
789
873
|
try {
|
|
790
|
-
const
|
|
874
|
+
const status = parseWithSchema(opts.status, "status", orderStatusSchema);
|
|
875
|
+
const data = { orderNumber, status };
|
|
791
876
|
if (opts.dryRun) {
|
|
792
877
|
printResult(
|
|
793
878
|
{ dryRun: true, valid: true, action: "order update", data },
|
|
@@ -804,7 +889,11 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
804
889
|
});
|
|
805
890
|
order.command("checkout").description("Convert a cart to an order").requiredOption("--cart-id <id>", "Cart ID").option("--payment-id <id>", "Payment ID (optional for free orders)").requiredOption("--order-number <num>", "Order number").requiredOption("--customer <json>", "Customer snapshot (JSON)").option("--dry-run", "Validate inputs without executing").action(async (opts) => {
|
|
806
891
|
try {
|
|
807
|
-
const customerSnapshot =
|
|
892
|
+
const customerSnapshot = parseWithSchema(
|
|
893
|
+
parseJson(opts.customer, "customer"),
|
|
894
|
+
"customer",
|
|
895
|
+
customerSnapshotSchema
|
|
896
|
+
);
|
|
808
897
|
const data = {
|
|
809
898
|
cartId: opts.cartId,
|
|
810
899
|
pgPaymentId: opts.paymentId,
|
|
@@ -830,7 +919,11 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
830
919
|
});
|
|
831
920
|
order.command("fulfill <orderNumber>").description("Create a fulfillment for an order").requiredOption("--items <json>", "Fulfillment items array (JSON)").option("--carrier <name>", "Shipping carrier").option("--tracking-number <num>", "Tracking number").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
832
921
|
try {
|
|
833
|
-
const items =
|
|
922
|
+
const items = parseWithSchema(
|
|
923
|
+
parseJsonArray(opts.items, "items"),
|
|
924
|
+
"items",
|
|
925
|
+
fulfillmentItemsSchema
|
|
926
|
+
);
|
|
834
927
|
const data = {
|
|
835
928
|
orderNumber,
|
|
836
929
|
items,
|
|
@@ -857,6 +950,23 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
857
950
|
}
|
|
858
951
|
|
|
859
952
|
// src/commands/return.ts
|
|
953
|
+
import { z as z2 } from "zod";
|
|
954
|
+
var idSchema2 = z2.union([z2.string().min(1), z2.number()]).transform(String);
|
|
955
|
+
var returnReasonSchema = z2.enum(["change_of_mind", "defective", "wrong_delivery", "damaged", "other"]).optional();
|
|
956
|
+
var returnItemsSchema = z2.array(
|
|
957
|
+
z2.object({
|
|
958
|
+
orderItem: idSchema2,
|
|
959
|
+
quantity: z2.number().int().positive("quantity must be a positive integer"),
|
|
960
|
+
restockAction: z2.enum(["return_to_stock", "discard"]).default("return_to_stock")
|
|
961
|
+
}).strict()
|
|
962
|
+
).min(1, "At least one return item is required").max(100, "Too many return items");
|
|
963
|
+
var returnStatusSchema = z2.enum([
|
|
964
|
+
"processing",
|
|
965
|
+
"approved",
|
|
966
|
+
"rejected",
|
|
967
|
+
"completed"
|
|
968
|
+
]);
|
|
969
|
+
var refundAmountSchema = z2.number().nonnegative("refundAmount must be non-negative");
|
|
860
970
|
function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
861
971
|
const ret = program2.command("return").description("Return management");
|
|
862
972
|
ret.command("create <orderNumber>").description("Create a return request").requiredOption("--products <json>", "Return products array (JSON)").requiredOption("--refund-amount <n>", "Refund amount", parseFloat).option(
|
|
@@ -864,12 +974,26 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
864
974
|
"Return reason (change_of_mind, defective, wrong_delivery, damaged, other)"
|
|
865
975
|
).option("--reason-detail <text>", "Detailed reason").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
866
976
|
try {
|
|
867
|
-
const returnItems =
|
|
977
|
+
const returnItems = parseWithSchema(
|
|
978
|
+
parseJsonArray(opts.products, "products"),
|
|
979
|
+
"products",
|
|
980
|
+
returnItemsSchema
|
|
981
|
+
);
|
|
982
|
+
const refundAmount = parseWithSchema(
|
|
983
|
+
opts.refundAmount,
|
|
984
|
+
"refund-amount",
|
|
985
|
+
refundAmountSchema
|
|
986
|
+
);
|
|
987
|
+
const reason = parseWithSchema(
|
|
988
|
+
opts.reason,
|
|
989
|
+
"reason",
|
|
990
|
+
returnReasonSchema
|
|
991
|
+
);
|
|
868
992
|
const data = {
|
|
869
993
|
orderNumber,
|
|
870
994
|
returnItems,
|
|
871
|
-
refundAmount
|
|
872
|
-
reason
|
|
995
|
+
refundAmount,
|
|
996
|
+
reason,
|
|
873
997
|
reasonDetail: opts.reasonDetail
|
|
874
998
|
};
|
|
875
999
|
if (opts.dryRun) {
|
|
@@ -894,7 +1018,8 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
894
1018
|
"New status (processing, approved, rejected, completed)"
|
|
895
1019
|
).option("--dry-run", "Validate inputs without executing").action(async (returnId, opts) => {
|
|
896
1020
|
try {
|
|
897
|
-
const
|
|
1021
|
+
const status = parseWithSchema(opts.status, "status", returnStatusSchema);
|
|
1022
|
+
const data = { returnId, status };
|
|
898
1023
|
if (opts.dryRun) {
|
|
899
1024
|
printResult(
|
|
900
1025
|
{ dryRun: true, valid: true, action: "return update", data },
|
|
@@ -911,13 +1036,27 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
911
1036
|
});
|
|
912
1037
|
ret.command("refund <orderNumber>").description("Return with refund").requiredOption("--products <json>", "Return products array (JSON)").requiredOption("--refund-amount <n>", "Refund amount", parseFloat).requiredOption("--payment-id <id>", "Payment ID").option("--reason <reason>", "Return reason").option("--reason-detail <text>", "Detailed reason").option("--refund-receipt-url <url>", "Refund receipt URL").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
913
1038
|
try {
|
|
914
|
-
const returnItems =
|
|
1039
|
+
const returnItems = parseWithSchema(
|
|
1040
|
+
parseJsonArray(opts.products, "products"),
|
|
1041
|
+
"products",
|
|
1042
|
+
returnItemsSchema
|
|
1043
|
+
);
|
|
1044
|
+
const refundAmount = parseWithSchema(
|
|
1045
|
+
opts.refundAmount,
|
|
1046
|
+
"refund-amount",
|
|
1047
|
+
refundAmountSchema
|
|
1048
|
+
);
|
|
1049
|
+
const reason = parseWithSchema(
|
|
1050
|
+
opts.reason,
|
|
1051
|
+
"reason",
|
|
1052
|
+
returnReasonSchema
|
|
1053
|
+
);
|
|
915
1054
|
const data = {
|
|
916
1055
|
orderNumber,
|
|
917
1056
|
returnItems,
|
|
918
|
-
refundAmount
|
|
1057
|
+
refundAmount,
|
|
919
1058
|
pgPaymentId: opts.paymentId,
|
|
920
|
-
reason
|
|
1059
|
+
reason,
|
|
921
1060
|
reasonDetail: opts.reasonDetail,
|
|
922
1061
|
refundReceiptUrl: opts.refundReceiptUrl
|
|
923
1062
|
};
|
|
@@ -1419,19 +1558,51 @@ import { existsSync as existsSync2 } from "fs";
|
|
|
1419
1558
|
import { spawn } from "child_process";
|
|
1420
1559
|
import { fileURLToPath } from "url";
|
|
1421
1560
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1422
|
-
function
|
|
1423
|
-
const
|
|
1424
|
-
|
|
1561
|
+
function getStdioEntryCandidates(baseDir = __dirname) {
|
|
1562
|
+
const candidates = [
|
|
1563
|
+
{
|
|
1564
|
+
label: "packaged CLI artifact",
|
|
1565
|
+
path: resolve(baseDir, "mcp/stdio.js")
|
|
1566
|
+
}
|
|
1567
|
+
];
|
|
1425
1568
|
const roots = ["../../../..", "../../..", "../.."];
|
|
1426
|
-
const entries = [
|
|
1569
|
+
const entries = [
|
|
1570
|
+
{
|
|
1571
|
+
label: "monorepo build output",
|
|
1572
|
+
path: "apps/mcp/dist/stdio.js"
|
|
1573
|
+
},
|
|
1574
|
+
{
|
|
1575
|
+
label: "xmcp build output",
|
|
1576
|
+
path: "apps/mcp/.xmcp/stdio.js"
|
|
1577
|
+
}
|
|
1578
|
+
];
|
|
1427
1579
|
for (const entry of entries) {
|
|
1428
1580
|
for (const root of roots) {
|
|
1429
|
-
|
|
1430
|
-
|
|
1581
|
+
candidates.push({
|
|
1582
|
+
label: entry.label,
|
|
1583
|
+
path: resolve(baseDir, root, entry.path)
|
|
1584
|
+
});
|
|
1431
1585
|
}
|
|
1432
1586
|
}
|
|
1587
|
+
return candidates;
|
|
1588
|
+
}
|
|
1589
|
+
function findStdioEntry(baseDir = __dirname) {
|
|
1590
|
+
for (const candidate of getStdioEntryCandidates(baseDir)) {
|
|
1591
|
+
if (existsSync2(candidate.path)) return candidate.path;
|
|
1592
|
+
}
|
|
1433
1593
|
return null;
|
|
1434
1594
|
}
|
|
1595
|
+
function formatMissingStdioEntryMessage(baseDir = __dirname) {
|
|
1596
|
+
const checked = getStdioEntryCandidates(baseDir).map((candidate) => ` - ${candidate.label}: ${candidate.path}`).join("\n");
|
|
1597
|
+
return [
|
|
1598
|
+
"MCP stdio entry not found.",
|
|
1599
|
+
"Checked:",
|
|
1600
|
+
checked,
|
|
1601
|
+
"Fix:",
|
|
1602
|
+
" - Monorepo checkout: run pnpm --filter mcp build.",
|
|
1603
|
+
" - Published CLI: reinstall or update @01.software/cli so dist/mcp/stdio.js is included."
|
|
1604
|
+
].join("\n");
|
|
1605
|
+
}
|
|
1435
1606
|
function createMcpEnv(baseEnv, client) {
|
|
1436
1607
|
const env = {
|
|
1437
1608
|
...baseEnv,
|
|
@@ -1442,15 +1613,21 @@ function createMcpEnv(baseEnv, client) {
|
|
|
1442
1613
|
return env;
|
|
1443
1614
|
}
|
|
1444
1615
|
function registerMcpCommands(program2) {
|
|
1445
|
-
program2.command("mcp").description("Start MCP server
|
|
1616
|
+
program2.command("mcp").description("Start local MCP stdio server for trusted server-key workflows").addHelpText(
|
|
1617
|
+
"after",
|
|
1618
|
+
`
|
|
1619
|
+
Prerequisites:
|
|
1620
|
+
Run 01 login, or set SOFTWARE_PUBLISHABLE_KEY and SOFTWARE_SECRET_KEY.
|
|
1621
|
+
Local stdio exposes the full MCP tool surface; HTTP OAuth MCP uses the
|
|
1622
|
+
narrower remote surface documented in the web integration guide.
|
|
1623
|
+
In a monorepo checkout, build the stdio artifact first:
|
|
1624
|
+
pnpm --filter mcp build
|
|
1625
|
+
`
|
|
1626
|
+
).action(() => {
|
|
1446
1627
|
const client = resolveClient(program2.opts().apiKey);
|
|
1447
1628
|
const stdioEntry = findStdioEntry();
|
|
1448
1629
|
if (!stdioEntry) {
|
|
1449
|
-
exitWithError(
|
|
1450
|
-
new Error(
|
|
1451
|
-
"MCP server not found. Ensure apps/mcp is built (pnpm --filter mcp build)."
|
|
1452
|
-
)
|
|
1453
|
-
);
|
|
1630
|
+
exitWithError(new Error(formatMissingStdioEntryMessage()));
|
|
1454
1631
|
}
|
|
1455
1632
|
const child = spawn(process.execPath, [stdioEntry], {
|
|
1456
1633
|
env: createMcpEnv(process.env, client),
|