toolcraft 0.0.6 → 0.0.8

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 CHANGED
@@ -441,19 +441,23 @@ If you have an existing MCP server you want to keep running, use the MCP proxy:
441
441
  - `casing?: "kebab" | "snake"` — generated CLI flag style.
442
442
  - `services?: TServices` — merged into every handler context.
443
443
  - `version?: string` — surfaced via `--version`.
444
+ - `presets?: boolean` — enables `--preset <path>` for loading parameter defaults from JSON files.
444
445
  - `apiVersion?: string` — for `requires.apiVersion`.
445
446
  - `humanInLoop?: HumanInLoopRuntimeOptions`
447
+ - `projectRoot?: string` — root used for MCP proxy cache files (`.toolcraft/mcp/*.json`).
446
448
 
447
449
  ### `createSDK(root, options)`
448
450
 
449
451
  - `casing?: "camel"` — generated SDK member style.
450
452
  - `services?` / `humanInLoop?` / `apiVersion?`
453
+ - `projectRoot?: string` — root used for MCP proxy cache files (`.toolcraft/mcp/*.json`).
451
454
 
452
455
  ### `createMCPServer(root, options)` / `runMCP(root, options)`
453
456
 
454
457
  - `name: string`
455
458
  - `version: string`
456
459
  - `services?` / `humanInLoop?` / `apiVersion?`
460
+ - `projectRoot?: string` — root used for MCP proxy cache files (`.toolcraft/mcp/*.json`).
457
461
  - `tools?: string[]` — allowlist of MCP tool names or group prefixes. Tool names are `__`-joined snake_case path segments (`root__bot__create`); a prefix like `root__bot` includes every descendant tool.
458
462
  - `casing?: "snake" | "camel"` — affects MCP **input-schema property names** only. Tool names always stay `__`-joined snake_case.
459
463
 
package/dist/cli.d.ts CHANGED
@@ -5,10 +5,12 @@ export interface RunCLIOptions<TServices extends object = Record<string, unknown
5
5
  apiVersion?: string;
6
6
  casing?: Casing;
7
7
  humanInLoop?: HumanInLoopRuntimeOptions;
8
+ projectRoot?: string;
8
9
  rootDisplayName?: string;
9
10
  rootUsageName?: string;
10
11
  services?: TServices;
11
12
  version?: string;
13
+ presets?: boolean;
12
14
  }
13
15
  export declare function runCLI<TServices extends object = Record<string, unknown>>(roots: Group<TServices> | Group<TServices>[], options?: RunCLIOptions<TServices>): Promise<void>;
14
16
  export {};
package/dist/cli.js CHANGED
@@ -126,7 +126,7 @@ function getRequiredBranchFingerprint(branch, casing) {
126
126
  .sort();
127
127
  return requiredKeys.join("+");
128
128
  }
129
- function collectFields(schema, casing, path = [], inheritedOptional = false, variantContext) {
129
+ function collectFields(schema, casing, globalLongOptionFlags, path = [], inheritedOptional = false, variantContext) {
130
130
  const collected = {
131
131
  dynamicFields: [],
132
132
  fields: [],
@@ -138,7 +138,7 @@ function collectFields(schema, casing, path = [], inheritedOptional = false, var
138
138
  const childSchema = unwrapOptional(rawChildSchema);
139
139
  const requiredWhenActive = rawChildSchema.kind !== "optional" && childSchema.default === undefined;
140
140
  if (childSchema.kind === "object") {
141
- const nested = collectFields(childSchema, casing, nextPath, runtimeOptional, variantContext);
141
+ const nested = collectFields(childSchema, casing, globalLongOptionFlags, nextPath, runtimeOptional, variantContext);
142
142
  collected.dynamicFields.push(...nested.dynamicFields);
143
143
  collected.fields.push(...nested.fields);
144
144
  collected.variants.push(...nested.variants);
@@ -152,7 +152,7 @@ function collectFields(schema, casing, path = [], inheritedOptional = false, var
152
152
  path: [...nextPath, childSchema.discriminator],
153
153
  displayPath: toDisplayPath([...nextPath, childSchema.discriminator]),
154
154
  optionAttribute: toOptionAttribute([...nextPath, childSchema.discriminator], casing),
155
- commanderOptionAttribute: toCommanderOptionAttribute([...nextPath, childSchema.discriminator], casing),
155
+ commanderOptionAttribute: toCommanderOptionAttribute([...nextPath, childSchema.discriminator], casing, globalLongOptionFlags),
156
156
  optionFlag: toOptionFlag([...nextPath, childSchema.discriminator], casing),
157
157
  shortFlag: undefined,
158
158
  schema: createSyntheticEnumSchema(branchIds),
@@ -165,7 +165,7 @@ function collectFields(schema, casing, path = [], inheritedOptional = false, var
165
165
  collected.fields.push(controlField);
166
166
  const branches = [];
167
167
  for (const [branchId, branchSchema] of Object.entries(childSchema.branches)) {
168
- const branch = collectFields(branchSchema, casing, nextPath, true, {
168
+ const branch = collectFields(branchSchema, casing, globalLongOptionFlags, nextPath, true, {
169
169
  id: variantId,
170
170
  branchId,
171
171
  });
@@ -203,7 +203,7 @@ function collectFields(schema, casing, path = [], inheritedOptional = false, var
203
203
  path: controlPath,
204
204
  displayPath: controlDisplayPath,
205
205
  optionAttribute: toOptionAttribute(controlPath, casing),
206
- commanderOptionAttribute: toCommanderOptionAttribute(controlPath, casing),
206
+ commanderOptionAttribute: toCommanderOptionAttribute(controlPath, casing, globalLongOptionFlags),
207
207
  optionFlag: toOptionFlag(controlPath, casing),
208
208
  shortFlag: undefined,
209
209
  schema: createSyntheticEnumSchema(branchIds),
@@ -218,7 +218,7 @@ function collectFields(schema, casing, path = [], inheritedOptional = false, var
218
218
  const branches = [];
219
219
  childSchema.branches.forEach((branchSchema, index) => {
220
220
  const branchId = branchIds[index] ?? "";
221
- const branch = collectFields(branchSchema, casing, nextPath, true, {
221
+ const branch = collectFields(branchSchema, casing, globalLongOptionFlags, nextPath, true, {
222
222
  id: variantId,
223
223
  branchId,
224
224
  });
@@ -289,7 +289,7 @@ function collectFields(schema, casing, path = [], inheritedOptional = false, var
289
289
  path: nextPath,
290
290
  displayPath: toDisplayPath(nextPath),
291
291
  optionAttribute: toOptionAttribute(nextPath, casing),
292
- commanderOptionAttribute: toCommanderOptionAttribute(nextPath, casing),
292
+ commanderOptionAttribute: toCommanderOptionAttribute(nextPath, casing, globalLongOptionFlags),
293
293
  optionFlag: toOptionFlag(nextPath, casing),
294
294
  shortFlag: childSchema.short,
295
295
  schema: childSchema,
@@ -304,10 +304,10 @@ function collectFields(schema, casing, path = [], inheritedOptional = false, var
304
304
  }
305
305
  return collected;
306
306
  }
307
- function toCommanderOptionAttribute(path, casing) {
307
+ function toCommanderOptionAttribute(path, casing, globalLongOptionFlags) {
308
308
  const optionAttribute = toOptionAttribute(path, casing);
309
309
  const optionFlag = toOptionFlag(path, casing);
310
- if (!GLOBAL_LONG_OPTION_FLAGS.has(optionFlag)) {
310
+ if (!globalLongOptionFlags.has(optionFlag)) {
311
311
  return optionAttribute;
312
312
  }
313
313
  return `param_${optionAttribute}`;
@@ -337,8 +337,8 @@ function assignPositionals(fields, positional) {
337
337
  });
338
338
  return fields;
339
339
  }
340
- function formatOptionFlags(field) {
341
- const collidesWithGlobalFlag = GLOBAL_LONG_OPTION_FLAGS.has(field.optionFlag);
340
+ function formatOptionFlags(field, globalLongOptionFlags) {
341
+ const collidesWithGlobalFlag = globalLongOptionFlags.has(field.optionFlag);
342
342
  if (collidesWithGlobalFlag) {
343
343
  if (field.shortFlag === undefined) {
344
344
  throw new UserError(`Parameter "${field.displayPath}" uses reserved CLI flag "${field.optionFlag}". Add a short flag or rename the parameter.`);
@@ -449,9 +449,9 @@ function parseArrayValue(value, schema, label) {
449
449
  }
450
450
  return splitArrayInput(value).map((item) => parseScalarValue(item, itemSchema, label));
451
451
  }
452
- function createOption(field) {
453
- const flags = formatOptionFlags(field);
454
- const collidesWithGlobalFlag = GLOBAL_LONG_OPTION_FLAGS.has(field.optionFlag);
452
+ function createOption(field, globalLongOptionFlags) {
453
+ const flags = formatOptionFlags(field, globalLongOptionFlags);
454
+ const collidesWithGlobalFlag = globalLongOptionFlags.has(field.optionFlag);
455
455
  const commanderValue = (value) => (value === null ? NULL_OPTION_VALUE : value);
456
456
  if (field.schema.kind === "boolean") {
457
457
  if (collidesWithGlobalFlag) {
@@ -489,7 +489,10 @@ function createOption(field) {
489
489
  option.argParser((value) => commanderValue(parseScalarValue(value, field.schema, field.displayPath)));
490
490
  return [option];
491
491
  }
492
- const GLOBAL_LONG_OPTION_FLAGS = new Set(["--preset", "--yes", "--output", "--verbose"]);
492
+ const ALWAYS_GLOBAL_LONG_OPTION_FLAGS = ["--yes", "--output", "--verbose"];
493
+ function getGlobalLongOptionFlags(presetsEnabled) {
494
+ return new Set(presetsEnabled ? ["--preset", ...ALWAYS_GLOBAL_LONG_OPTION_FLAGS] : ALWAYS_GLOBAL_LONG_OPTION_FLAGS);
495
+ }
493
496
  function createCommanderOption(flags, description, field) {
494
497
  const option = new Option(flags, description);
495
498
  if (field.commanderOptionAttribute !== field.optionAttribute) {
@@ -580,14 +583,14 @@ function describeSchemaType(schema) {
580
583
  throw new UserError("Unsupported CLI schema kind.");
581
584
  }
582
585
  }
583
- function formatHelpFieldFlags(field) {
586
+ function formatHelpFieldFlags(field, globalLongOptionFlags) {
584
587
  if (field.positionalIndex !== undefined) {
585
588
  return formatPositionalToken(field);
586
589
  }
587
590
  if (field.schema.kind === "boolean") {
588
- return `${formatOptionFlags(field)} [value]`;
591
+ return `${formatOptionFlags(field, globalLongOptionFlags)} [value]`;
589
592
  }
590
- return `${formatOptionFlags(field)} <${describeSchemaType(field.schema)}>`;
593
+ return `${formatOptionFlags(field, globalLongOptionFlags)} <${describeSchemaType(field.schema)}>`;
591
594
  }
592
595
  function appendHelpMetadata(description, metadata) {
593
596
  if (metadata.length === 0) {
@@ -711,31 +714,40 @@ function formatSecretDescription(secret) {
711
714
  }
712
715
  return secret.optional === true ? "Optional secret" : "Required secret";
713
716
  }
714
- function formatCommandRows(group, scope) {
715
- return getVisibleChildren(group, scope).map((child) => ({
716
- name: child.aliases.length === 0 ? child.name : `${child.name} (${child.aliases.join(", ")})`,
717
- description: child.description ?? "",
718
- }));
717
+ function formatCommandRowName(node, depth) {
718
+ const name = node.aliases.length === 0 ? node.name : `${node.name} (${node.aliases.join(", ")})`;
719
+ return `${" ".repeat(depth)}${name}`;
720
+ }
721
+ function formatCommandRows(group, scope, depth = 0) {
722
+ return getVisibleChildren(group, scope).flatMap((child) => {
723
+ const row = {
724
+ name: formatCommandRowName(child, depth),
725
+ description: child.description ?? "",
726
+ };
727
+ if (child.kind === "command") {
728
+ return [row];
729
+ }
730
+ return [row, ...formatCommandRows(child, scope, depth + 1)];
731
+ });
719
732
  }
720
- function formatGlobalOptionRows(showVersion) {
721
- const rows = [
722
- {
733
+ function formatGlobalOptionRows(showVersion, presetsEnabled) {
734
+ const rows = [];
735
+ if (presetsEnabled) {
736
+ rows.push({
723
737
  flags: "--preset <path>",
724
738
  description: "Load parameter defaults from a JSON file",
725
- },
726
- {
727
- flags: "--yes",
728
- description: "Accept defaults, skip prompts",
729
- },
730
- {
731
- flags: "--output <format>",
732
- description: "Output format (rich, md, json)",
733
- },
734
- {
735
- flags: "-h, --help",
736
- description: "Show help",
737
- },
738
- ];
739
+ });
740
+ }
741
+ rows.push({
742
+ flags: "--yes",
743
+ description: "Accept defaults, skip prompts",
744
+ }, {
745
+ flags: "--output <format>",
746
+ description: "Output format (rich, md, json)",
747
+ }, {
748
+ flags: "-h, --help",
749
+ description: "Show help",
750
+ });
739
751
  if (showVersion) {
740
752
  rows.push({
741
753
  flags: "--version",
@@ -754,13 +766,13 @@ function buildUsageLine(breadcrumb, rootUsageName, suffix) {
754
766
  const subPath = breadcrumb.slice(1).join(" ");
755
767
  return subPath ? `${rootUsageName} ${subPath} ${suffix}` : `${rootUsageName} ${suffix}`;
756
768
  }
757
- function renderGroupHelp(group, breadcrumb, scope, showVersion, rootUsageName) {
769
+ function renderGroupHelp(group, breadcrumb, scope, showVersion, presetsEnabled, rootUsageName) {
758
770
  const sections = [];
759
771
  const commandRows = formatCommandRows(group, scope);
760
772
  if (commandRows.length > 0) {
761
773
  sections.push(`${text.section("Commands:")}\n${formatCommandList(commandRows)}`);
762
774
  }
763
- sections.push(`${text.section("Global options:")}\n${formatOptionList(formatGlobalOptionRows(showVersion))}`);
775
+ sections.push(`${text.section("Global options:")}\n${formatOptionList(formatGlobalOptionRows(showVersion, presetsEnabled))}`);
764
776
  return renderHelpDocument({
765
777
  breadcrumb,
766
778
  usageLine: buildUsageLine(breadcrumb, rootUsageName, "[options] [command]"),
@@ -769,18 +781,19 @@ function renderGroupHelp(group, breadcrumb, scope, showVersion, rootUsageName) {
769
781
  sections,
770
782
  });
771
783
  }
772
- function renderLeafHelp(command, breadcrumb, casing, rootUsageName) {
784
+ function renderLeafHelp(command, breadcrumb, casing, presetsEnabled, rootUsageName) {
773
785
  const sections = [];
774
- const collected = collectFields(command.params, casing);
786
+ const globalLongOptionFlags = getGlobalLongOptionFlags(presetsEnabled);
787
+ const collected = collectFields(command.params, casing, globalLongOptionFlags);
775
788
  const fields = assignPositionals(collected.fields, command.positional);
776
789
  const optionRows = fields.map((field) => ({
777
- flags: formatHelpFieldFlags(field),
790
+ flags: formatHelpFieldFlags(field, globalLongOptionFlags),
778
791
  description: formatHelpFieldDescription(field),
779
792
  })).concat(collected.dynamicFields.flatMap((field) => formatDynamicHelpFields(field, casing)));
780
793
  if (optionRows.length > 0) {
781
794
  sections.push(`${text.section("Options:")}\n${formatOptionList(optionRows)}`);
782
795
  }
783
- sections.push(`${text.section("Global options:")}\n${formatOptionList(formatGlobalOptionRows(false))}`);
796
+ sections.push(`${text.section("Global options:")}\n${formatOptionList(formatGlobalOptionRows(false, presetsEnabled))}`);
784
797
  const secretRows = formatSecretRows(command.secrets);
785
798
  if (secretRows.length > 0) {
786
799
  sections.push(`${text.section("Secrets (via environment):")}\n${formatOptionList(secretRows)}`);
@@ -820,26 +833,26 @@ async function renderGeneratedHelp(root, argv, options) {
820
833
  const casing = options.casing ?? "kebab";
821
834
  await withOutputFormat(output, async () => {
822
835
  const rendered = target.node.kind === "group"
823
- ? renderGroupHelp(target.node, target.breadcrumb, "cli", options.version !== undefined, options.rootUsageName)
824
- : renderLeafHelp(target.node, target.breadcrumb, casing, options.rootUsageName);
836
+ ? renderGroupHelp(target.node, target.breadcrumb, "cli", options.version !== undefined, options.presets === true, options.rootUsageName)
837
+ : renderLeafHelp(target.node, target.breadcrumb, casing, options.presets === true, options.rootUsageName);
825
838
  process.stdout.write(rendered);
826
839
  });
827
840
  }
828
- function createNodeCommand(node, casing, execute, pathSegments = []) {
841
+ function createNodeCommand(node, casing, globalLongOptionFlags, execute, presetsEnabled, pathSegments = []) {
829
842
  const nextPathSegments = [...pathSegments, node.name];
830
843
  if (node.kind === "command") {
831
844
  if (!node.scope.includes("cli")) {
832
845
  return null;
833
846
  }
834
847
  const command = new CommanderCommand(node.name);
835
- const collected = collectFields(node.params, casing);
848
+ const collected = collectFields(node.params, casing, globalLongOptionFlags);
836
849
  const fields = assignPositionals(collected.fields, node.positional);
837
850
  if (node.description !== undefined) {
838
851
  command.description(node.description);
839
852
  }
840
853
  node.aliases.forEach((alias) => command.alias(alias));
841
854
  command.addHelpCommand(false);
842
- addGlobalOptions(command);
855
+ addGlobalOptions(command, presetsEnabled);
843
856
  command.allowExcessArguments(true);
844
857
  if (collected.dynamicFields.length > 0) {
845
858
  command.allowUnknownOption(true);
@@ -849,7 +862,7 @@ function createNodeCommand(node, casing, execute, pathSegments = []) {
849
862
  command.argument(formatPositionalToken(field));
850
863
  continue;
851
864
  }
852
- for (const option of createOption(field)) {
865
+ for (const option of createOption(field, globalLongOptionFlags)) {
853
866
  command.addOption(option);
854
867
  }
855
868
  }
@@ -863,6 +876,7 @@ function createNodeCommand(node, casing, execute, pathSegments = []) {
863
876
  dynamicFields: collected.dynamicFields,
864
877
  fields,
865
878
  positionalValues,
879
+ presetsEnabled,
866
880
  rawArgv: actionCommand.args,
867
881
  actionCommand,
868
882
  variants: collected.variants,
@@ -874,7 +888,7 @@ function createNodeCommand(node, casing, execute, pathSegments = []) {
874
888
  return null;
875
889
  }
876
890
  const visibleChildren = node.children
877
- .map((child) => createNodeCommand(child, casing, execute, nextPathSegments))
891
+ .map((child) => createNodeCommand(child, casing, globalLongOptionFlags, execute, presetsEnabled, nextPathSegments))
878
892
  .filter((child) => child !== null);
879
893
  const group = new CommanderCommand(node.name);
880
894
  if (node.description !== undefined) {
@@ -882,7 +896,7 @@ function createNodeCommand(node, casing, execute, pathSegments = []) {
882
896
  }
883
897
  node.aliases.forEach((alias) => group.alias(alias));
884
898
  group.addHelpCommand(false);
885
- addGlobalOptions(group);
899
+ addGlobalOptions(group, presetsEnabled);
886
900
  for (const child of visibleChildren) {
887
901
  const isDefaultChild = node.default !== undefined &&
888
902
  node.default.scope.includes("cli") &&
@@ -891,9 +905,11 @@ function createNodeCommand(node, casing, execute, pathSegments = []) {
891
905
  }
892
906
  return group;
893
907
  }
894
- function addGlobalOptions(command) {
908
+ function addGlobalOptions(command, presetsEnabled) {
909
+ if (presetsEnabled) {
910
+ command.option("--preset <path>", "Load parameter defaults from a JSON file.");
911
+ }
895
912
  command
896
- .option("--preset <path>", "Load parameter defaults from a JSON file.")
897
913
  .option("--yes", "Accept defaults and skip prompts.")
898
914
  .option("--output <format>", "Output format.", (value) => {
899
915
  if (value === "rich" || value === "md" || value === "json") {
@@ -1927,7 +1943,7 @@ async function executeCommand(state, services, requirementOptions, runtimeOption
1927
1943
  };
1928
1944
  await withOutputFormat(output, async () => {
1929
1945
  await assertCommandRequirements(state.command, preflightContext, runtime.requirementOptions);
1930
- const params = await resolveParams(state.fields, state.dynamicFields, state.variants, state.positionalValues, optionValues, state.rawArgv, state.casing, resolvedFlags.preset, shouldPrompt);
1946
+ const params = await resolveParams(state.fields, state.dynamicFields, state.variants, state.positionalValues, optionValues, state.rawArgv, state.casing, state.presetsEnabled ? resolvedFlags.preset : undefined, shouldPrompt);
1931
1947
  const context = {
1932
1948
  ...preflightContext,
1933
1949
  params,
@@ -1987,7 +2003,7 @@ function handleRunError(error, verbose) {
1987
2003
  }
1988
2004
  export async function runCLI(roots, options = {}) {
1989
2005
  const root = mergeApprovalsGroup(normalizeRoots(roots, process.argv));
1990
- await resolveMcpProxies(root);
2006
+ await resolveMcpProxies(root, { projectRoot: options.projectRoot });
1991
2007
  const casing = options.casing ?? "kebab";
1992
2008
  const services = (options.services ?? {});
1993
2009
  const runtimeOptions = options.humanInLoop ?? {};
@@ -2010,7 +2026,9 @@ export async function runCLI(roots, options = {}) {
2010
2026
  program.exitOverride();
2011
2027
  program.showHelpAfterError();
2012
2028
  program.addHelpCommand(false);
2013
- addGlobalOptions(program);
2029
+ const presetsEnabled = options.presets === true;
2030
+ const globalLongOptionFlags = getGlobalLongOptionFlags(presetsEnabled);
2031
+ addGlobalOptions(program, presetsEnabled);
2014
2032
  if (version !== undefined) {
2015
2033
  program.version(version, "--version");
2016
2034
  }
@@ -2020,7 +2038,7 @@ export async function runCLI(roots, options = {}) {
2020
2038
  await executeCommand(state, servicesWithBuiltIns, requirementOptions, runtimeOptions);
2021
2039
  };
2022
2040
  for (const child of root.children) {
2023
- const command = createNodeCommand(child, casing, execute);
2041
+ const command = createNodeCommand(child, casing, globalLongOptionFlags, execute, presetsEnabled);
2024
2042
  if (command === null) {
2025
2043
  continue;
2026
2044
  }
@@ -1,8 +1,11 @@
1
1
  import type { McpServerConfig } from "@poe-code/agent-mcp-config";
2
2
  import { McpClient } from "tiny-mcp-client";
3
3
  import type { Group } from "./index.js";
4
+ export interface ResolveMcpProxyOptions {
5
+ projectRoot?: string;
6
+ }
4
7
  export declare function hasMcpProxyGroups(root: Group<any>): boolean;
5
8
  export declare function resolveCachePath(name: string, projectRoot?: string): string;
6
9
  export declare function parseRefreshEnv(value: string | undefined): "all" | Set<string> | undefined;
7
10
  export declare function dialUpstream(name: string, config: McpServerConfig): Promise<McpClient>;
8
- export declare function resolveMcpProxies(root: Group<any>): Promise<void>;
11
+ export declare function resolveMcpProxies(root: Group<any>, options?: ResolveMcpProxyOptions): Promise<void>;
package/dist/mcp-proxy.js CHANGED
@@ -268,7 +268,7 @@ function isRefreshRequested(name, refresh) {
268
268
  }
269
269
  return refresh?.has(name) === true;
270
270
  }
271
- async function resolveSingleProxy(group) {
271
+ async function resolveSingleProxy(group, options) {
272
272
  const internal = getInternalGroupConfig(group);
273
273
  const config = internal.mcp;
274
274
  if (config === undefined) {
@@ -276,7 +276,7 @@ async function resolveSingleProxy(group) {
276
276
  }
277
277
  const name = group.name;
278
278
  try {
279
- const cachePath = resolveCachePath(name);
279
+ const cachePath = resolveCachePath(name, options.projectRoot);
280
280
  const refresh = parseRefreshEnv(process.env.TOOLCRAFT_MCP_REFRESH);
281
281
  let cache;
282
282
  if (isRefreshRequested(name, refresh)) {
@@ -377,7 +377,7 @@ export async function dialUpstream(name, config) {
377
377
  await client.connect(transport);
378
378
  return client;
379
379
  }
380
- export async function resolveMcpProxies(root) {
380
+ export async function resolveMcpProxies(root, options = {}) {
381
381
  const groups = collectProxyGroups(root);
382
- await Promise.all(groups.map((group) => resolveSingleProxy(group)));
382
+ await Promise.all(groups.map((group) => resolveSingleProxy(group, options)));
383
383
  }
package/dist/mcp.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface RunMCPOptions<TServices extends object = Record<string, unknown
9
9
  name: string;
10
10
  version?: string;
11
11
  humanInLoop?: HumanInLoopRuntimeOptions;
12
+ projectRoot?: string;
12
13
  /**
13
14
  * Optional allowlist of MCP tool names or group prefixes.
14
15
  *
package/dist/mcp.js CHANGED
@@ -419,7 +419,7 @@ function createDeferredMCPServer(root, options) {
419
419
  let serverPromise;
420
420
  const resolveServer = () => {
421
421
  serverPromise ??= (async () => {
422
- await resolveMcpProxies(root);
422
+ await resolveMcpProxies(root, { projectRoot: options.projectRoot });
423
423
  return createResolvedMCPServer(root, options);
424
424
  })();
425
425
  return serverPromise;
@@ -449,7 +449,7 @@ export function createMCPServer(roots, options) {
449
449
  }
450
450
  export async function runMCP(roots, options) {
451
451
  const root = mergeApprovalsGroup(normalizeRoots(roots));
452
- await resolveMcpProxies(root);
452
+ await resolveMcpProxies(root, { projectRoot: options.projectRoot });
453
453
  const server = createResolvedMCPServer(root, options);
454
454
  await server.listen();
455
455
  }
package/dist/sdk.d.ts CHANGED
@@ -63,6 +63,7 @@ export interface CreateSDKOptions<TServices extends object = Record<string, unkn
63
63
  services?: TServices;
64
64
  casing?: "camel";
65
65
  humanInLoop?: HumanInLoopRuntimeOptions;
66
+ projectRoot?: string;
66
67
  }
67
68
  export declare function createSDK<TRootInfo, TServices extends object = Record<string, unknown>>(root: Group<any> & {
68
69
  readonly __agentKitGroupTypeInfo: TRootInfo;
package/dist/sdk.js CHANGED
@@ -234,7 +234,7 @@ function createDeferredSDK(root, options) {
234
234
  let sdkPromise;
235
235
  const resolveSDK = () => {
236
236
  sdkPromise ??= (async () => {
237
- await resolveMcpProxies(root);
237
+ await resolveMcpProxies(root, { projectRoot: options.projectRoot });
238
238
  return createResolvedSDK(root, options);
239
239
  })();
240
240
  return sdkPromise;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "toolcraft",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -45,7 +45,7 @@
45
45
  "commander": "^14.0.3",
46
46
  "console-table-printer": "^2.15.0",
47
47
  "tiny-stdio-mcp-server": "^0.1.0",
48
- "toolcraft-schema": "^0.0.6"
48
+ "toolcraft-schema": "^0.0.8"
49
49
  },
50
50
  "files": [
51
51
  "dist"