@firfi/huly-mcp 0.43.0 → 0.44.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/README.md +25 -56
- package/dist/index.cjs +1208 -271
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -116881,10 +116881,10 @@ var require_code3 = __commonJS({
|
|
|
116881
116881
|
return schemaMap ? Object.keys(schemaMap).filter((p) => p !== "__proto__") : [];
|
|
116882
116882
|
}
|
|
116883
116883
|
exports2.allSchemaProperties = allSchemaProperties;
|
|
116884
|
-
function
|
|
116884
|
+
function schemaProperties2(it, schemaMap) {
|
|
116885
116885
|
return allSchemaProperties(schemaMap).filter((p) => !(0, util_1.alwaysValidSchema)(it, schemaMap[p]));
|
|
116886
116886
|
}
|
|
116887
|
-
exports2.schemaProperties =
|
|
116887
|
+
exports2.schemaProperties = schemaProperties2;
|
|
116888
116888
|
function callValidateCode({ schemaCode, data, it: { gen: gen6, topSchemaRef, schemaPath, errorPath }, it }, func2, context6, passSchema) {
|
|
116889
116889
|
const dataAndSchema = passSchema ? (0, codegen_1._)`${schemaCode}, ${data}, ${topSchemaRef}${schemaPath}` : data;
|
|
116890
116890
|
const valCxt = [
|
|
@@ -171243,6 +171243,38 @@ var ToolsetsContextSchema = Schema_exports.Struct({
|
|
|
171243
171243
|
totalRegisteredToolCount: Count,
|
|
171244
171244
|
builtinTools: Schema_exports.Array(Schema_exports.Literal("get_version", "get_huly_context"))
|
|
171245
171245
|
});
|
|
171246
|
+
var ToolScopeContextSchema = Schema_exports.Struct({
|
|
171247
|
+
active: Schema_exports.Boolean,
|
|
171248
|
+
requestedToolsets: Schema_exports.Array(NonEmptyTrimmedString2),
|
|
171249
|
+
enabledToolsets: Schema_exports.Array(NonEmptyTrimmedString2),
|
|
171250
|
+
ignoredToolsets: Schema_exports.Array(NonEmptyTrimmedString2),
|
|
171251
|
+
requestedTools: Schema_exports.Array(NonEmptyTrimmedString2),
|
|
171252
|
+
enabledTools: Schema_exports.Array(NonEmptyTrimmedString2),
|
|
171253
|
+
ignoredTools: Schema_exports.Array(NonEmptyTrimmedString2),
|
|
171254
|
+
availableCategories: Schema_exports.Array(NonEmptyTrimmedString2),
|
|
171255
|
+
visibleRegisteredToolCount: Count,
|
|
171256
|
+
totalRegisteredToolCount: Count,
|
|
171257
|
+
builtinTools: Schema_exports.Array(Schema_exports.Literal("get_version", "get_huly_context"))
|
|
171258
|
+
});
|
|
171259
|
+
var ToolExposureContextSchema = Schema_exports.Struct({
|
|
171260
|
+
configuredMode: Schema_exports.Literal("auto", "native", "proxy"),
|
|
171261
|
+
resolvedMode: Schema_exports.Literal("native", "proxy"),
|
|
171262
|
+
clientKind: Schema_exports.Literal(
|
|
171263
|
+
"claude-code",
|
|
171264
|
+
"claude-ai",
|
|
171265
|
+
"cursor",
|
|
171266
|
+
"windsurf",
|
|
171267
|
+
"github-copilot",
|
|
171268
|
+
"codex",
|
|
171269
|
+
"opencode",
|
|
171270
|
+
"unknown"
|
|
171271
|
+
),
|
|
171272
|
+
proxyOutputStrict: Schema_exports.Boolean,
|
|
171273
|
+
visibleToolCount: Count,
|
|
171274
|
+
nativeVisibleToolCount: Count,
|
|
171275
|
+
proxyCandidateToolCount: Count,
|
|
171276
|
+
proxyToolNames: Schema_exports.Array(NonEmptyTrimmedString2)
|
|
171277
|
+
});
|
|
171246
171278
|
var GetHulyContextResultSchema = Schema_exports.Struct({
|
|
171247
171279
|
package: Schema_exports.Struct({
|
|
171248
171280
|
name: Schema_exports.Literal("@firfi/huly-mcp"),
|
|
@@ -171258,7 +171290,9 @@ var GetHulyContextResultSchema = Schema_exports.Struct({
|
|
|
171258
171290
|
huly: HulyRuntimeContextSchema,
|
|
171259
171291
|
auth: AuthContextSchema,
|
|
171260
171292
|
configSources: ConfigSourcesSchema,
|
|
171261
|
-
toolsets: ToolsetsContextSchema
|
|
171293
|
+
toolsets: ToolsetsContextSchema,
|
|
171294
|
+
toolScope: ToolScopeContextSchema,
|
|
171295
|
+
toolExposure: ToolExposureContextSchema
|
|
171262
171296
|
});
|
|
171263
171297
|
var getHulyContextResultJsonSchema = JSONSchema_exports.make(GetHulyContextResultSchema);
|
|
171264
171298
|
|
|
@@ -181591,25 +181625,8 @@ var parseUpdateDriveFileCommentParams = Schema_exports.decodeUnknown(UpdateDrive
|
|
|
181591
181625
|
var parseDeleteDriveFileCommentParams = Schema_exports.decodeUnknown(DeleteDriveFileCommentParamsSchema);
|
|
181592
181626
|
var parseListDriveFileActivityParams = Schema_exports.decodeUnknown(ListDriveFileActivityParamsSchema);
|
|
181593
181627
|
|
|
181594
|
-
// src/huly/diagnostics.ts
|
|
181595
|
-
var Diagnostics = class extends Context_exports.Tag("@hulymcp/Diagnostics")() {
|
|
181596
|
-
};
|
|
181597
|
-
var warningLogText = (warning) => `Agent-visible tool warning [${warning.code}]: ${warning.message}`;
|
|
181598
|
-
var makeDiagnosticsScope = Effect_exports.gen(function* () {
|
|
181599
|
-
const warningsRef = yield* Ref_exports.make([]);
|
|
181600
|
-
return {
|
|
181601
|
-
service: {
|
|
181602
|
-
warnAgent: (warning) => Ref_exports.update(warningsRef, (warnings) => [...warnings, warning]).pipe(
|
|
181603
|
-
Effect_exports.zipRight(Effect_exports.logWarning(warningLogText(warning)))
|
|
181604
|
-
),
|
|
181605
|
-
trail: (message) => Effect_exports.logInfo(`Diagnostic trail: ${message}`)
|
|
181606
|
-
},
|
|
181607
|
-
drainWarnings: Ref_exports.get(warningsRef)
|
|
181608
|
-
};
|
|
181609
|
-
});
|
|
181610
|
-
|
|
181611
181628
|
// src/version.ts
|
|
181612
|
-
var VERSION = true ? "0.
|
|
181629
|
+
var VERSION = true ? "0.44.0" : "0.0.0-dev";
|
|
181613
181630
|
|
|
181614
181631
|
// src/mcp/json-schema-refs.ts
|
|
181615
181632
|
var isJsonObject = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
@@ -181630,6 +181647,25 @@ var collectJsonSchemaDefinitions = (value3) => {
|
|
|
181630
181647
|
return mergeDefinitionRecords([...nestedDefinitions, ownDefinitions]);
|
|
181631
181648
|
};
|
|
181632
181649
|
var omitJsonSchemaDocumentMetadata = (schema) => Object.fromEntries(Object.entries(schema).filter(([key]) => key !== "$defs" && key !== "$schema"));
|
|
181650
|
+
var EFFECT_PSEUDO_ID_PREFIX = "/schemas/";
|
|
181651
|
+
var isCollidingSchemaId = (key, value3) => key === "$id" && typeof value3 === "string" && value3.startsWith(EFFECT_PSEUDO_ID_PREFIX);
|
|
181652
|
+
var stripCollidingSchemaIds = (value3) => {
|
|
181653
|
+
if (Array.isArray(value3)) return value3.map(stripCollidingSchemaIds);
|
|
181654
|
+
if (!isJsonObject(value3)) return value3;
|
|
181655
|
+
return Object.fromEntries(
|
|
181656
|
+
Object.entries(value3).filter(([key, nested6]) => !isCollidingSchemaId(key, nested6)).map(([key, nested6]) => [key, stripCollidingSchemaIds(nested6)])
|
|
181657
|
+
);
|
|
181658
|
+
};
|
|
181659
|
+
var stripCollidingSchemaIdsRecord = (record4) => {
|
|
181660
|
+
const stripped = stripCollidingSchemaIds(record4);
|
|
181661
|
+
return isJsonObject(stripped) ? stripped : record4;
|
|
181662
|
+
};
|
|
181663
|
+
var stripCollidingSchemaIdsProperties = (properties) => Object.fromEntries(
|
|
181664
|
+
Object.entries(properties).map(([key, value3]) => {
|
|
181665
|
+
const stripped = stripCollidingSchemaIds(value3);
|
|
181666
|
+
return [key, isJsonObject(stripped) ? stripped : value3];
|
|
181667
|
+
})
|
|
181668
|
+
);
|
|
181633
181669
|
|
|
181634
181670
|
// src/mcp/tool-output-schema.ts
|
|
181635
181671
|
var toolWarningCodeEnum = [...ToolWarningCodeSchema.literals];
|
|
@@ -181669,6 +181705,70 @@ var wrapResultOutputSchema = (resultSchema) => {
|
|
|
181669
181705
|
var createToolOutputSchema = (resultSchema) => wrapResultOutputSchema(JSONSchema_exports.make(resultSchema));
|
|
181670
181706
|
var hulyContextToolOutputSchema = wrapResultOutputSchema(getHulyContextResultJsonSchema);
|
|
181671
181707
|
|
|
181708
|
+
// src/mcp/tool-scope.ts
|
|
181709
|
+
var normalizeCsv = (raw) => {
|
|
181710
|
+
const normalized = raw.split(",").map((part) => part.trim().toLowerCase()).filter((part) => part !== "");
|
|
181711
|
+
return [...new Set(normalized)];
|
|
181712
|
+
};
|
|
181713
|
+
var orderedCategories = (definitions) => [...new Set(definitions.map((definition) => definition.category))];
|
|
181714
|
+
var knownValueMap = (values4) => new Map(values4.map((value3) => [value3, value3]));
|
|
181715
|
+
var resolveRequested = (requested, known, unknownMessage, writeError2) => requested.reduce((acc, name) => {
|
|
181716
|
+
const knownValue = known.get(name);
|
|
181717
|
+
if (knownValue !== void 0) {
|
|
181718
|
+
return {
|
|
181719
|
+
...acc,
|
|
181720
|
+
enabled: [...acc.enabled, knownValue]
|
|
181721
|
+
};
|
|
181722
|
+
}
|
|
181723
|
+
writeError2(unknownMessage(name));
|
|
181724
|
+
return {
|
|
181725
|
+
...acc,
|
|
181726
|
+
ignored: [...acc.ignored, name]
|
|
181727
|
+
};
|
|
181728
|
+
}, {
|
|
181729
|
+
enabled: [],
|
|
181730
|
+
ignored: []
|
|
181731
|
+
});
|
|
181732
|
+
var resolveToolScope = (rawEnv, definitions, writeError2) => {
|
|
181733
|
+
const requestedToolsets = normalizeCsv(rawEnv.toolsets);
|
|
181734
|
+
const requestedTools = normalizeCsv(rawEnv.tools);
|
|
181735
|
+
const availableCategories = orderedCategories(definitions);
|
|
181736
|
+
const knownCategories = knownValueMap(availableCategories);
|
|
181737
|
+
const knownToolNames = knownValueMap(definitions.map((definition) => definition.name));
|
|
181738
|
+
const toolsets = resolveRequested(
|
|
181739
|
+
requestedToolsets,
|
|
181740
|
+
knownCategories,
|
|
181741
|
+
(category) => `Warning: unknown toolset category "${category}", ignoring. Valid categories: ${availableCategories.join(", ")}`,
|
|
181742
|
+
writeError2
|
|
181743
|
+
);
|
|
181744
|
+
const tools = resolveRequested(
|
|
181745
|
+
requestedTools,
|
|
181746
|
+
knownToolNames,
|
|
181747
|
+
(tool) => `Warning: unknown tool name "${tool}", ignoring.`,
|
|
181748
|
+
writeError2
|
|
181749
|
+
);
|
|
181750
|
+
const filteringActive = requestedToolsets.length > 0 || requestedTools.length > 0;
|
|
181751
|
+
const enabledCategories = new Set(toolsets.enabled);
|
|
181752
|
+
const enabledToolNames = new Set(tools.enabled);
|
|
181753
|
+
const visibleRegisteredToolCount = filteringActive ? definitions.filter(
|
|
181754
|
+
(definition) => enabledCategories.has(definition.category) || enabledToolNames.has(definition.name)
|
|
181755
|
+
).length : definitions.length;
|
|
181756
|
+
return {
|
|
181757
|
+
filteringActive,
|
|
181758
|
+
requestedToolsets,
|
|
181759
|
+
enabledToolsets: toolsets.enabled,
|
|
181760
|
+
ignoredToolsets: toolsets.ignored,
|
|
181761
|
+
requestedTools,
|
|
181762
|
+
enabledTools: tools.enabled,
|
|
181763
|
+
ignoredTools: tools.ignored,
|
|
181764
|
+
enabledCategories,
|
|
181765
|
+
enabledToolNames,
|
|
181766
|
+
availableCategories,
|
|
181767
|
+
visibleRegisteredToolCount,
|
|
181768
|
+
totalRegisteredToolCount: definitions.length
|
|
181769
|
+
};
|
|
181770
|
+
};
|
|
181771
|
+
|
|
181672
181772
|
// src/huly/operations/activity-messages.ts
|
|
181673
181773
|
var import_core11 = __toESM(require_lib5(), 1);
|
|
181674
181774
|
|
|
@@ -183410,6 +183510,25 @@ var deleteDocument = (params) => Effect_exports.gen(function* () {
|
|
|
183410
183510
|
|
|
183411
183511
|
// src/huly/operations/issues-shared.ts
|
|
183412
183512
|
var import_tracker = __toESM(require_lib41(), 1);
|
|
183513
|
+
|
|
183514
|
+
// src/huly/diagnostics.ts
|
|
183515
|
+
var Diagnostics = class extends Context_exports.Tag("@hulymcp/Diagnostics")() {
|
|
183516
|
+
};
|
|
183517
|
+
var warningLogText = (warning) => `Agent-visible tool warning [${warning.code}]: ${warning.message}`;
|
|
183518
|
+
var makeDiagnosticsScope = Effect_exports.gen(function* () {
|
|
183519
|
+
const warningsRef = yield* Ref_exports.make([]);
|
|
183520
|
+
return {
|
|
183521
|
+
service: {
|
|
183522
|
+
warnAgent: (warning) => Ref_exports.update(warningsRef, (warnings) => [...warnings, warning]).pipe(
|
|
183523
|
+
Effect_exports.zipRight(Effect_exports.logWarning(warningLogText(warning)))
|
|
183524
|
+
),
|
|
183525
|
+
trail: (message) => Effect_exports.logInfo(`Diagnostic trail: ${message}`)
|
|
183526
|
+
},
|
|
183527
|
+
drainWarnings: Ref_exports.get(warningsRef)
|
|
183528
|
+
};
|
|
183529
|
+
});
|
|
183530
|
+
|
|
183531
|
+
// src/huly/operations/issues-shared.ts
|
|
183413
183532
|
var zeroAsUnset = (value3) => value3 > 0 ? PositiveNumber.make(value3) : void 0;
|
|
183414
183533
|
var findProject = (projectIdentifier) => Effect_exports.gen(function* () {
|
|
183415
183534
|
const client = yield* HulyClient;
|
|
@@ -183795,6 +183914,36 @@ var listMentions = (params) => Effect_exports.gen(function* () {
|
|
|
183795
183914
|
});
|
|
183796
183915
|
|
|
183797
183916
|
// src/mcp/tools/registry.ts
|
|
183917
|
+
var ToolName = Schema_exports.NonEmptyTrimmedString.pipe(Schema_exports.brand("ToolName")).annotations({
|
|
183918
|
+
identifier: "ToolName",
|
|
183919
|
+
title: "ToolName",
|
|
183920
|
+
description: "Exact MCP tool name registered by this server."
|
|
183921
|
+
});
|
|
183922
|
+
var ToolDescription = Schema_exports.NonEmptyTrimmedString.pipe(Schema_exports.brand("ToolDescription")).annotations({
|
|
183923
|
+
identifier: "ToolDescription",
|
|
183924
|
+
title: "ToolDescription",
|
|
183925
|
+
description: "Human-readable MCP tool description."
|
|
183926
|
+
});
|
|
183927
|
+
var ToolCategory = Schema_exports.NonEmptyTrimmedString.pipe(Schema_exports.brand("ToolCategory")).annotations({
|
|
183928
|
+
identifier: "ToolCategory",
|
|
183929
|
+
title: "ToolCategory",
|
|
183930
|
+
description: "MCP tool category used for toolset filtering and proxy discovery."
|
|
183931
|
+
});
|
|
183932
|
+
var makeToolName = (value3) => ToolName.make(value3);
|
|
183933
|
+
var makeToolDescription = (value3) => ToolDescription.make(value3);
|
|
183934
|
+
var makeToolCategory = (value3) => ToolCategory.make(value3);
|
|
183935
|
+
var parseToolName = (input) => {
|
|
183936
|
+
const decoded = Schema_exports.decodeUnknownEither(ToolName)(input);
|
|
183937
|
+
return Either_exports.isRight(decoded) ? decoded.right : void 0;
|
|
183938
|
+
};
|
|
183939
|
+
var createToolDefinition = (spec) => ({
|
|
183940
|
+
name: makeToolName(spec.name),
|
|
183941
|
+
description: makeToolDescription(spec.description),
|
|
183942
|
+
inputSchema: spec.inputSchema,
|
|
183943
|
+
outputSchema: spec.outputSchema,
|
|
183944
|
+
category: makeToolCategory(spec.category),
|
|
183945
|
+
...spec.annotations === void 0 ? {} : { annotations: spec.annotations }
|
|
183946
|
+
});
|
|
183798
183947
|
var deriveTitle = (name) => name.split("_").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
183799
183948
|
var READ_PREFIXES = ["list_", "get_", "describe_", "search_", "fulltext_", "download_", "preview_"];
|
|
183800
183949
|
var CREATE_PREFIXES = ["create_", "add_", "upload_", "send_", "log_"];
|
|
@@ -183864,7 +184013,7 @@ var isEmptyStructUnionSchema = (schema) => {
|
|
|
183864
184013
|
var requiresArgumentsObject = (tool) => isToolInputSchema(tool.inputSchema) && (hasRequiredFields(tool.inputSchema) || unionVariants(tool.inputSchema).some(hasRequiredFields));
|
|
183865
184014
|
var isNoArgumentTool = (tool) => isToolInputSchema(tool.inputSchema) && !requiresArgumentsObject(tool) && (!hasDeclaredProperties(tool.inputSchema) && tool.inputSchema.additionalProperties === false || isEmptyStructUnionSchema(tool.inputSchema));
|
|
183866
184015
|
var encodeOutput = (schema, result) => Schema_exports.encodeUnknownSync(schema)(result);
|
|
183867
|
-
var stripResultSchema = (spec) => ({
|
|
184016
|
+
var stripResultSchema = (spec) => createToolDefinition({
|
|
183868
184017
|
name: spec.name,
|
|
183869
184018
|
description: spec.description,
|
|
183870
184019
|
inputSchema: spec.inputSchema,
|
|
@@ -207218,14 +207367,20 @@ var buildRegistry = (tools) => {
|
|
|
207218
207367
|
}
|
|
207219
207368
|
};
|
|
207220
207369
|
};
|
|
207221
|
-
var createFilteredRegistry = (categories) => buildRegistry(allTools.filter((t) => categories.has(t.category)));
|
|
207222
207370
|
var toolRegistry = buildRegistry(allTools);
|
|
207371
|
+
var createScopedRegistry = (scope5) => {
|
|
207372
|
+
if (!scope5.filteringActive) return toolRegistry;
|
|
207373
|
+
return buildRegistry(
|
|
207374
|
+
allTools.filter((t) => scope5.categories.has(t.category) || scope5.toolNames.has(t.name))
|
|
207375
|
+
);
|
|
207376
|
+
};
|
|
207223
207377
|
var TOOL_DEFINITIONS = Object.fromEntries(toolRegistry.tools);
|
|
207224
207378
|
|
|
207225
207379
|
// src/mcp/huly-context-tool.ts
|
|
207226
207380
|
var NPM_PACKAGE_NAME = "@firfi/huly-mcp";
|
|
207227
|
-
var
|
|
207228
|
-
var
|
|
207381
|
+
var BUILTIN_TOOL_NAME_LITERALS = ["get_version", "get_huly_context"];
|
|
207382
|
+
var VERSION_TOOL_NAME = makeToolName(BUILTIN_TOOL_NAME_LITERALS[0]);
|
|
207383
|
+
var GET_HULY_CONTEXT_TOOL_NAME = makeToolName(BUILTIN_TOOL_NAME_LITERALS[1]);
|
|
207229
207384
|
var emptyInputSchema = { type: "object", properties: {}, additionalProperties: false };
|
|
207230
207385
|
var VersionToolResultSchema = Schema_exports.Struct({
|
|
207231
207386
|
current: NonEmptyString2,
|
|
@@ -207233,7 +207388,9 @@ var VersionToolResultSchema = Schema_exports.Struct({
|
|
|
207233
207388
|
});
|
|
207234
207389
|
var versionToolDefinition = {
|
|
207235
207390
|
name: VERSION_TOOL_NAME,
|
|
207236
|
-
description:
|
|
207391
|
+
description: makeToolDescription(
|
|
207392
|
+
"Returns the current version of this Huly MCP server and the latest version available on npm."
|
|
207393
|
+
),
|
|
207237
207394
|
inputSchema: emptyInputSchema,
|
|
207238
207395
|
outputSchema: createToolOutputSchema(VersionToolResultSchema),
|
|
207239
207396
|
annotations: {
|
|
@@ -207246,7 +207403,9 @@ var versionToolDefinition = {
|
|
|
207246
207403
|
};
|
|
207247
207404
|
var getHulyContextToolDefinition = {
|
|
207248
207405
|
name: GET_HULY_CONTEXT_TOOL_NAME,
|
|
207249
|
-
description:
|
|
207406
|
+
description: makeToolDescription(
|
|
207407
|
+
"Returns sanitized runtime and configuration context for this Huly MCP session, including package version, transport, auth mode, Huly URL origin/host, workspace, timeout, native tool scope filtering, and resolved native/proxy tool exposure. Does not connect to Huly. Secret values such as tokens, passwords, and credential headers are never returned."
|
|
207408
|
+
),
|
|
207250
207409
|
inputSchema: emptyInputSchema,
|
|
207251
207410
|
outputSchema: hulyContextToolOutputSchema,
|
|
207252
207411
|
annotations: {
|
|
@@ -207257,104 +207416,73 @@ var getHulyContextToolDefinition = {
|
|
|
207257
207416
|
openWorldHint: false
|
|
207258
207417
|
}
|
|
207259
207418
|
};
|
|
207260
|
-
var
|
|
207261
|
-
if (raw === void 0 || raw.trim() === "") {
|
|
207262
|
-
return {
|
|
207263
|
-
enabledCategories: void 0,
|
|
207264
|
-
requestedCategories: [],
|
|
207265
|
-
ignoredCategories: []
|
|
207266
|
-
};
|
|
207267
|
-
}
|
|
207268
|
-
const requested = raw.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
207269
|
-
const parsed = requested.reduce((acc, category) => {
|
|
207270
|
-
if (CATEGORY_NAMES.has(category)) {
|
|
207271
|
-
return {
|
|
207272
|
-
...acc,
|
|
207273
|
-
enabledCategories: [...acc.enabledCategories, category]
|
|
207274
|
-
};
|
|
207275
|
-
}
|
|
207276
|
-
writeError2(
|
|
207277
|
-
`Warning: unknown toolset category "${category}", ignoring. Valid categories: ${[...CATEGORY_NAMES].join(", ")}`
|
|
207278
|
-
);
|
|
207279
|
-
return {
|
|
207280
|
-
...acc,
|
|
207281
|
-
ignoredCategories: [...acc.ignoredCategories, category]
|
|
207282
|
-
};
|
|
207283
|
-
}, {
|
|
207284
|
-
enabledCategories: [],
|
|
207285
|
-
ignoredCategories: []
|
|
207286
|
-
});
|
|
207287
|
-
const enabled2 = new Set(parsed.enabledCategories);
|
|
207288
|
-
return {
|
|
207289
|
-
enabledCategories: enabled2.size > 0 ? enabled2 : void 0,
|
|
207290
|
-
requestedCategories: requested,
|
|
207291
|
-
ignoredCategories: parsed.ignoredCategories
|
|
207292
|
-
};
|
|
207293
|
-
};
|
|
207294
|
-
var builtinToolNames = [VERSION_TOOL_NAME, GET_HULY_CONTEXT_TOOL_NAME];
|
|
207419
|
+
var builtinToolNames = BUILTIN_TOOL_NAME_LITERALS;
|
|
207295
207420
|
var nonEmptyOrDefault = (value3, fallback) => {
|
|
207296
207421
|
const trimmed2 = value3?.trim();
|
|
207297
207422
|
return trimmed2 === void 0 || trimmed2 === "" ? fallback : trimmed2;
|
|
207298
207423
|
};
|
|
207299
|
-
var
|
|
207300
|
-
|
|
207301
|
-
|
|
207302
|
-
|
|
207303
|
-
|
|
207304
|
-
|
|
207305
|
-
|
|
207306
|
-
|
|
207307
|
-
|
|
207308
|
-
|
|
207309
|
-
|
|
207310
|
-
|
|
207311
|
-
|
|
207312
|
-
|
|
207313
|
-
|
|
207314
|
-
|
|
207315
|
-
|
|
207316
|
-
|
|
207317
|
-
|
|
207318
|
-
|
|
207319
|
-
|
|
207320
|
-
ignoredCategories: toolsetSummary.ignoredCategories,
|
|
207321
|
-
availableCategories: [...CATEGORY_NAMES],
|
|
207322
|
-
visibleRegisteredToolCount: Count.make(registry2.definitions.length),
|
|
207323
|
-
totalRegisteredToolCount: Count.make(toolRegistry.definitions.length),
|
|
207324
|
-
builtinTools: builtinToolNames
|
|
207325
|
-
}
|
|
207326
|
-
});
|
|
207327
|
-
|
|
207328
|
-
// src/mcp/input-schema-compat.ts
|
|
207329
|
-
var ROOT_COMPOSITION_KEYS = /* @__PURE__ */ new Set(["anyOf", "oneOf", "allOf"]);
|
|
207330
|
-
var isRecord3 = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
207331
|
-
var mergeObjectFields = (sources) => {
|
|
207332
|
-
const merged = sources.reduce(
|
|
207333
|
-
(acc, source) => isRecord3(source) ? { ...source, ...acc } : acc,
|
|
207334
|
-
{}
|
|
207335
|
-
);
|
|
207336
|
-
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
207337
|
-
};
|
|
207338
|
-
var rootCompositionBranches = (schema) => [...ROOT_COMPOSITION_KEYS].flatMap((key) => {
|
|
207339
|
-
const branches = Reflect.get(schema, key);
|
|
207340
|
-
return Array.isArray(branches) ? branches.filter(isRecord3) : [];
|
|
207341
|
-
});
|
|
207342
|
-
var schemaAndCompositionDescendants = (schema) => [
|
|
207343
|
-
schema,
|
|
207344
|
-
...rootCompositionBranches(schema).flatMap(schemaAndCompositionDescendants)
|
|
207345
|
-
];
|
|
207346
|
-
var mergedSchemaField = (schema, field) => mergeObjectFields(schemaAndCompositionDescendants(schema).map((branch) => Reflect.get(branch, field)));
|
|
207347
|
-
var toClientCompatibleInputSchema = (schema) => {
|
|
207348
|
-
const rootFields = Object.fromEntries(
|
|
207349
|
-
Object.entries(schema).filter(([key]) => key !== "type" && !ROOT_COMPOSITION_KEYS.has(key))
|
|
207350
|
-
);
|
|
207351
|
-
const properties = mergedSchemaField(schema, "properties");
|
|
207352
|
-
const defs = collectJsonSchemaDefinitions(schema);
|
|
207424
|
+
var defaultToolExposureContext = (registry2) => ({
|
|
207425
|
+
configuredMode: "auto",
|
|
207426
|
+
resolvedMode: "native",
|
|
207427
|
+
clientKind: "unknown",
|
|
207428
|
+
proxyOutputStrict: false,
|
|
207429
|
+
visibleToolCount: builtinToolNames.length + registry2.definitions.length,
|
|
207430
|
+
nativeVisibleToolCount: registry2.definitions.length,
|
|
207431
|
+
proxyCandidateToolCount: toolRegistry.definitions.length,
|
|
207432
|
+
proxyToolNames: []
|
|
207433
|
+
});
|
|
207434
|
+
var buildHulyContext = (config3, registry2, toolScope, runtimeConfig, exposureContext = defaultToolExposureContext(registry2)) => {
|
|
207435
|
+
const toolExposure = {
|
|
207436
|
+
configuredMode: exposureContext.configuredMode,
|
|
207437
|
+
resolvedMode: exposureContext.resolvedMode,
|
|
207438
|
+
clientKind: exposureContext.clientKind,
|
|
207439
|
+
proxyOutputStrict: exposureContext.proxyOutputStrict,
|
|
207440
|
+
visibleToolCount: Count.make(exposureContext.visibleToolCount),
|
|
207441
|
+
nativeVisibleToolCount: Count.make(exposureContext.nativeVisibleToolCount),
|
|
207442
|
+
proxyCandidateToolCount: Count.make(exposureContext.proxyCandidateToolCount),
|
|
207443
|
+
proxyToolNames: exposureContext.proxyToolNames
|
|
207444
|
+
};
|
|
207353
207445
|
return {
|
|
207354
|
-
|
|
207355
|
-
|
|
207356
|
-
|
|
207357
|
-
|
|
207446
|
+
package: {
|
|
207447
|
+
name: NPM_PACKAGE_NAME,
|
|
207448
|
+
version: nonEmptyOrDefault(VERSION, "0.0.0-dev")
|
|
207449
|
+
},
|
|
207450
|
+
transport: {
|
|
207451
|
+
type: config3.transport,
|
|
207452
|
+
...config3.transport === "http" ? {
|
|
207453
|
+
http: {
|
|
207454
|
+
host: nonEmptyOrDefault(config3.httpHost, "127.0.0.1"),
|
|
207455
|
+
port: config3.httpPort ?? DEFAULT_HTTP_PORT
|
|
207456
|
+
}
|
|
207457
|
+
} : {}
|
|
207458
|
+
},
|
|
207459
|
+
huly: runtimeConfig.huly,
|
|
207460
|
+
auth: runtimeConfig.auth,
|
|
207461
|
+
configSources: runtimeConfig.configSources,
|
|
207462
|
+
toolsets: {
|
|
207463
|
+
filteringActive: toolScope.filteringActive,
|
|
207464
|
+
requestedCategories: toolScope.requestedToolsets,
|
|
207465
|
+
enabledCategories: toolScope.enabledToolsets,
|
|
207466
|
+
ignoredCategories: toolScope.ignoredToolsets,
|
|
207467
|
+
availableCategories: toolScope.availableCategories,
|
|
207468
|
+
visibleRegisteredToolCount: Count.make(registry2.definitions.length),
|
|
207469
|
+
totalRegisteredToolCount: Count.make(toolScope.totalRegisteredToolCount),
|
|
207470
|
+
builtinTools: builtinToolNames
|
|
207471
|
+
},
|
|
207472
|
+
toolScope: {
|
|
207473
|
+
active: toolScope.filteringActive,
|
|
207474
|
+
requestedToolsets: toolScope.requestedToolsets,
|
|
207475
|
+
enabledToolsets: toolScope.enabledToolsets,
|
|
207476
|
+
ignoredToolsets: toolScope.ignoredToolsets,
|
|
207477
|
+
requestedTools: toolScope.requestedTools,
|
|
207478
|
+
enabledTools: toolScope.enabledTools,
|
|
207479
|
+
ignoredTools: toolScope.ignoredTools,
|
|
207480
|
+
availableCategories: toolScope.availableCategories,
|
|
207481
|
+
visibleRegisteredToolCount: Count.make(registry2.definitions.length),
|
|
207482
|
+
totalRegisteredToolCount: Count.make(toolScope.totalRegisteredToolCount),
|
|
207483
|
+
builtinTools: builtinToolNames
|
|
207484
|
+
},
|
|
207485
|
+
toolExposure
|
|
207358
207486
|
};
|
|
207359
207487
|
};
|
|
207360
207488
|
|
|
@@ -207617,12 +207745,7 @@ var readHulyResource = (uri) => Effect_exports.try({
|
|
|
207617
207745
|
Effect_exports.flatMap(readParsedHulyResource)
|
|
207618
207746
|
);
|
|
207619
207747
|
|
|
207620
|
-
// src/mcp/protocol-handlers.ts
|
|
207621
|
-
var DRAIN_POLL_MS = 50;
|
|
207622
|
-
var DRAIN_TIMEOUT_MS2 = 3e4;
|
|
207623
|
-
var NPM_FETCH_TIMEOUT_MS = 5e3;
|
|
207624
|
-
var NPM_PACKAGE_NAME2 = "@firfi/huly-mcp";
|
|
207625
|
-
var computeOutputBytes = (response) => response.content.reduce((sum2, c) => sum2 + c.text.length, 0);
|
|
207748
|
+
// src/mcp/protocol-resource-handlers.ts
|
|
207626
207749
|
var withResourceWarnings = (result, warnings) => warnings.length === 0 ? result : {
|
|
207627
207750
|
...result,
|
|
207628
207751
|
_meta: {
|
|
@@ -207630,6 +207753,777 @@ var withResourceWarnings = (result, warnings) => warnings.length === 0 ? result
|
|
|
207630
207753
|
warnings
|
|
207631
207754
|
}
|
|
207632
207755
|
};
|
|
207756
|
+
var createResourceClientResolutionError = (uri, _error) => new McpError(
|
|
207757
|
+
ErrorCode.InternalError,
|
|
207758
|
+
`Failed to initialize Huly clients while reading resource "${uri}". Verify Huly URL, workspace, and authentication configuration.`
|
|
207759
|
+
);
|
|
207760
|
+
var createResourceListClientResolutionError = (_error) => new McpError(
|
|
207761
|
+
ErrorCode.InternalError,
|
|
207762
|
+
"Failed to initialize Huly clients while listing resources. Verify Huly URL, workspace, and authentication configuration."
|
|
207763
|
+
);
|
|
207764
|
+
var isConfigValidationFailure = (error2) => {
|
|
207765
|
+
if (error2 instanceof ConfigValidationError) return true;
|
|
207766
|
+
if (!Runtime_exports.isFiberFailure(error2)) return false;
|
|
207767
|
+
return Chunk_exports.toArray(Cause_exports.failures(error2[Runtime_exports.FiberFailureCauseId])).some(
|
|
207768
|
+
(failure) => failure instanceof ConfigValidationError
|
|
207769
|
+
);
|
|
207770
|
+
};
|
|
207771
|
+
var resolveResourceClientsOrThrow = async (resolveClients, mapError7) => {
|
|
207772
|
+
try {
|
|
207773
|
+
return await resolveClients();
|
|
207774
|
+
} catch (e) {
|
|
207775
|
+
throw mapError7(e);
|
|
207776
|
+
}
|
|
207777
|
+
};
|
|
207778
|
+
var throwResourceReadError = (uri, cause3) => {
|
|
207779
|
+
const failures3 = Chunk_exports.toArray(Cause_exports.failures(cause3));
|
|
207780
|
+
const failure = failures3[0];
|
|
207781
|
+
if (failure instanceof McpError) throw failure;
|
|
207782
|
+
throw new McpError(ErrorCode.InternalError, `Failed to read Huly resource "${uri}"`);
|
|
207783
|
+
};
|
|
207784
|
+
var throwResourceListError = (cause3) => {
|
|
207785
|
+
const failures3 = Chunk_exports.toArray(Cause_exports.failures(cause3));
|
|
207786
|
+
const failure = failures3[0];
|
|
207787
|
+
if (failure instanceof McpError) throw failure;
|
|
207788
|
+
throw new McpError(ErrorCode.InternalError, "Failed to list Huly resources");
|
|
207789
|
+
};
|
|
207790
|
+
var createResourceProtocolHandlers = (input) => {
|
|
207791
|
+
const listResourcesHandler = async () => {
|
|
207792
|
+
input.enter();
|
|
207793
|
+
try {
|
|
207794
|
+
let clients;
|
|
207795
|
+
try {
|
|
207796
|
+
clients = await input.resolveClients();
|
|
207797
|
+
} catch (e) {
|
|
207798
|
+
if (isConfigValidationFailure(e)) return { resources: [] };
|
|
207799
|
+
throw createResourceListClientResolutionError(e);
|
|
207800
|
+
}
|
|
207801
|
+
const resourceList = await Effect_exports.runPromiseExit(
|
|
207802
|
+
listResources().pipe(
|
|
207803
|
+
Effect_exports.provideService(HulyClient, clients.hulyClient)
|
|
207804
|
+
)
|
|
207805
|
+
);
|
|
207806
|
+
if (Exit_exports.isSuccess(resourceList)) return resourceList.value;
|
|
207807
|
+
return throwResourceListError(resourceList.cause);
|
|
207808
|
+
} finally {
|
|
207809
|
+
input.leave();
|
|
207810
|
+
}
|
|
207811
|
+
};
|
|
207812
|
+
const readResource = async (request3) => {
|
|
207813
|
+
input.enter();
|
|
207814
|
+
try {
|
|
207815
|
+
const { uri } = request3.params;
|
|
207816
|
+
const clients = await resolveResourceClientsOrThrow(
|
|
207817
|
+
input.resolveClients,
|
|
207818
|
+
(error2) => createResourceClientResolutionError(uri, error2)
|
|
207819
|
+
);
|
|
207820
|
+
const diagnosticsScope = await Effect_exports.runPromise(makeDiagnosticsScope);
|
|
207821
|
+
const resourceRead = await Effect_exports.runPromiseExit(
|
|
207822
|
+
readHulyResource(uri).pipe(
|
|
207823
|
+
Effect_exports.provideService(HulyClient, clients.hulyClient),
|
|
207824
|
+
Effect_exports.provideService(Diagnostics, diagnosticsScope.service)
|
|
207825
|
+
)
|
|
207826
|
+
);
|
|
207827
|
+
const warnings = await Effect_exports.runPromise(diagnosticsScope.drainWarnings);
|
|
207828
|
+
if (Exit_exports.isSuccess(resourceRead)) return withResourceWarnings(resourceRead.value, warnings);
|
|
207829
|
+
return throwResourceReadError(uri, resourceRead.cause);
|
|
207830
|
+
} finally {
|
|
207831
|
+
input.leave();
|
|
207832
|
+
}
|
|
207833
|
+
};
|
|
207834
|
+
return {
|
|
207835
|
+
listResources: listResourcesHandler,
|
|
207836
|
+
readResource
|
|
207837
|
+
};
|
|
207838
|
+
};
|
|
207839
|
+
|
|
207840
|
+
// src/mcp/input-schema-compat.ts
|
|
207841
|
+
var ROOT_COMPOSITION_KEYS = /* @__PURE__ */ new Set(["anyOf", "oneOf", "allOf"]);
|
|
207842
|
+
var isRecord3 = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
207843
|
+
var mergeObjectFields = (sources) => {
|
|
207844
|
+
const merged = sources.reduce(
|
|
207845
|
+
(acc, source) => isRecord3(source) ? { ...source, ...acc } : acc,
|
|
207846
|
+
{}
|
|
207847
|
+
);
|
|
207848
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
207849
|
+
};
|
|
207850
|
+
var rootCompositionBranches = (schema) => [...ROOT_COMPOSITION_KEYS].flatMap((key) => {
|
|
207851
|
+
const branches = Reflect.get(schema, key);
|
|
207852
|
+
return Array.isArray(branches) ? branches.filter(isRecord3) : [];
|
|
207853
|
+
});
|
|
207854
|
+
var schemaAndCompositionDescendants = (schema) => [
|
|
207855
|
+
schema,
|
|
207856
|
+
...rootCompositionBranches(schema).flatMap(schemaAndCompositionDescendants)
|
|
207857
|
+
];
|
|
207858
|
+
var mergedSchemaField = (schema, field) => mergeObjectFields(schemaAndCompositionDescendants(schema).map((branch) => Reflect.get(branch, field)));
|
|
207859
|
+
var toClientCompatibleInputSchema = (schema) => {
|
|
207860
|
+
const rootFields = Object.fromEntries(
|
|
207861
|
+
Object.entries(schema).filter(([key]) => key !== "type" && !ROOT_COMPOSITION_KEYS.has(key))
|
|
207862
|
+
);
|
|
207863
|
+
const properties = mergedSchemaField(schema, "properties");
|
|
207864
|
+
const defs = collectJsonSchemaDefinitions(schema);
|
|
207865
|
+
return {
|
|
207866
|
+
...rootFields,
|
|
207867
|
+
type: "object",
|
|
207868
|
+
...properties === void 0 ? {} : { properties },
|
|
207869
|
+
...defs === void 0 ? {} : { $defs: defs }
|
|
207870
|
+
};
|
|
207871
|
+
};
|
|
207872
|
+
|
|
207873
|
+
// src/mcp/proxy-tool-catalog.ts
|
|
207874
|
+
var SEARCH_DEFAULT_LIMIT = 10;
|
|
207875
|
+
var SEARCH_MAX_LIMIT = 50;
|
|
207876
|
+
var ToolSearchQuery = Schema_exports.NonEmptyTrimmedString.pipe(Schema_exports.brand("ToolSearchQuery"));
|
|
207877
|
+
var ToolParameterName = Schema_exports.NonEmptyTrimmedString.pipe(Schema_exports.brand("ToolParameterName"));
|
|
207878
|
+
var SearchToolLimit = Schema_exports.Number.pipe(
|
|
207879
|
+
Schema_exports.int(),
|
|
207880
|
+
Schema_exports.positive(),
|
|
207881
|
+
Schema_exports.lessThanOrEqualTo(SEARCH_MAX_LIMIT),
|
|
207882
|
+
Schema_exports.brand("SearchToolLimit")
|
|
207883
|
+
);
|
|
207884
|
+
var makeSearchToolLimit = (value3) => SearchToolLimit.make(value3);
|
|
207885
|
+
var SEARCH_DEFAULT_LIMIT_VALUE = makeSearchToolLimit(SEARCH_DEFAULT_LIMIT);
|
|
207886
|
+
var isRecord4 = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
207887
|
+
var stringArray = (value3) => Array.isArray(value3) && value3.every((item) => typeof item === "string") ? value3 : [];
|
|
207888
|
+
var parseToolParameterName = (value3) => {
|
|
207889
|
+
const decoded = Schema_exports.decodeUnknownEither(ToolParameterName)(value3);
|
|
207890
|
+
return Either_exports.isRight(decoded) ? decoded.right : void 0;
|
|
207891
|
+
};
|
|
207892
|
+
var schemaProperties = (schema) => {
|
|
207893
|
+
const properties = isRecord4(schema) ? schema.properties : void 0;
|
|
207894
|
+
return isRecord4(properties) ? Object.keys(properties).map(parseToolParameterName).filter((name) => name !== void 0) : [];
|
|
207895
|
+
};
|
|
207896
|
+
var schemaRequired = (schema) => isRecord4(schema) ? stringArray(schema.required) : [];
|
|
207897
|
+
var toolParamSummary = (tool) => {
|
|
207898
|
+
const required4 = new Set(schemaRequired(tool.inputSchema));
|
|
207899
|
+
const properties = schemaProperties(tool.inputSchema);
|
|
207900
|
+
return {
|
|
207901
|
+
requiredParams: properties.filter((name) => required4.has(name)),
|
|
207902
|
+
optionalParams: properties.filter((name) => !required4.has(name))
|
|
207903
|
+
};
|
|
207904
|
+
};
|
|
207905
|
+
var categoryDescriptionEntry = (category, description) => [
|
|
207906
|
+
makeToolCategory(category),
|
|
207907
|
+
makeToolDescription(description)
|
|
207908
|
+
];
|
|
207909
|
+
var CATEGORY_DESCRIPTIONS = new Map([
|
|
207910
|
+
categoryDescriptionEntry(
|
|
207911
|
+
"projects",
|
|
207912
|
+
"Project discovery, project metadata, project target preferences, and project-level settings."
|
|
207913
|
+
),
|
|
207914
|
+
categoryDescriptionEntry(
|
|
207915
|
+
"issues",
|
|
207916
|
+
"Issue tracking: create, read, update, move, delete, relate, label, and organize Huly issues."
|
|
207917
|
+
),
|
|
207918
|
+
categoryDescriptionEntry("labels", "Issue and workspace labels for classification and filtering."),
|
|
207919
|
+
categoryDescriptionEntry("tags", "Generic tags that can be created, updated, attached, detached, and listed."),
|
|
207920
|
+
categoryDescriptionEntry("tag-categories", "Tag category administration and tag grouping metadata."),
|
|
207921
|
+
categoryDescriptionEntry(
|
|
207922
|
+
"templates",
|
|
207923
|
+
"Issue and message templates, including template fields, categories, children, and rendering."
|
|
207924
|
+
),
|
|
207925
|
+
categoryDescriptionEntry("comments", "Comments and discussion content attached to Huly objects."),
|
|
207926
|
+
categoryDescriptionEntry(
|
|
207927
|
+
"collaborators",
|
|
207928
|
+
"Collaborator discovery and participation metadata for documents and other shared objects."
|
|
207929
|
+
),
|
|
207930
|
+
categoryDescriptionEntry("milestones", "Issue milestone lifecycle and milestone assignment."),
|
|
207931
|
+
categoryDescriptionEntry(
|
|
207932
|
+
"documents",
|
|
207933
|
+
"Teamspaces and documents: create, read, edit, snapshot, inline comment, and delete document content."
|
|
207934
|
+
),
|
|
207935
|
+
categoryDescriptionEntry(
|
|
207936
|
+
"drive",
|
|
207937
|
+
"Drive spaces, folders, files, versions, comments, and drive membership administration."
|
|
207938
|
+
),
|
|
207939
|
+
categoryDescriptionEntry(
|
|
207940
|
+
"associations",
|
|
207941
|
+
"Generic associations and relations between Huly documents, issues, cards, and raw objects."
|
|
207942
|
+
),
|
|
207943
|
+
categoryDescriptionEntry(
|
|
207944
|
+
"inventory",
|
|
207945
|
+
"Inventory products, categories, variants, product media, comments, and attachments."
|
|
207946
|
+
),
|
|
207947
|
+
categoryDescriptionEntry(
|
|
207948
|
+
"spaces",
|
|
207949
|
+
"Generic Huly spaces, space types, space permissions, members, owners, roles, and preferences."
|
|
207950
|
+
),
|
|
207951
|
+
categoryDescriptionEntry(
|
|
207952
|
+
"sdk-discovery",
|
|
207953
|
+
"SDK and model discovery helpers for Huly platform classes, attributes, mixins, and enums."
|
|
207954
|
+
),
|
|
207955
|
+
categoryDescriptionEntry("storage", "Storage diagnostics and storage-backed object helpers."),
|
|
207956
|
+
categoryDescriptionEntry(
|
|
207957
|
+
"attachments",
|
|
207958
|
+
"Issue, document, and generic attachment upload, download, pinning, updating, and deletion."
|
|
207959
|
+
),
|
|
207960
|
+
categoryDescriptionEntry(
|
|
207961
|
+
"contacts",
|
|
207962
|
+
"People, employees, organizations, contact channels, channel providers, and contact ownership."
|
|
207963
|
+
),
|
|
207964
|
+
categoryDescriptionEntry(
|
|
207965
|
+
"channels",
|
|
207966
|
+
"Messaging: channels, direct messages, group messages, thread replies, reactions, and saved messages."
|
|
207967
|
+
),
|
|
207968
|
+
categoryDescriptionEntry(
|
|
207969
|
+
"boards",
|
|
207970
|
+
"Board administration, board labels, board cards, board views, menus, and archive workflows."
|
|
207971
|
+
),
|
|
207972
|
+
categoryDescriptionEntry("views", "Saved and filtered views across boards and other view-capable Huly modules."),
|
|
207973
|
+
categoryDescriptionEntry("cards", "Generic cards, card spaces, card relations, master tags, and card metadata."),
|
|
207974
|
+
categoryDescriptionEntry("leads", "CRM funnels and leads discovery."),
|
|
207975
|
+
categoryDescriptionEntry(
|
|
207976
|
+
"recruiting",
|
|
207977
|
+
"Recruiting vacancies, applicants, reviews, opinions, candidate skills, and recruiting media."
|
|
207978
|
+
),
|
|
207979
|
+
categoryDescriptionEntry("custom-fields", "Custom field definitions and custom field values on Huly documents."),
|
|
207980
|
+
categoryDescriptionEntry(
|
|
207981
|
+
"calendar",
|
|
207982
|
+
"Calendar events, recurring events, schedules, meeting rooms, and availability."
|
|
207983
|
+
),
|
|
207984
|
+
categoryDescriptionEntry(
|
|
207985
|
+
"time tracking",
|
|
207986
|
+
"Time tracking, work logs, time reports, detailed time summaries, and estimates."
|
|
207987
|
+
),
|
|
207988
|
+
categoryDescriptionEntry("planner", "Planner todos, schedules, work slots, priorities, and completion workflows."),
|
|
207989
|
+
categoryDescriptionEntry(
|
|
207990
|
+
"preferences",
|
|
207991
|
+
"User and project preferences, notification preferences, and preference diagnostics."
|
|
207992
|
+
),
|
|
207993
|
+
categoryDescriptionEntry(
|
|
207994
|
+
"approvals",
|
|
207995
|
+
"Approval request lifecycle, approval comments, approve/reject/cancel actions, and approval status."
|
|
207996
|
+
),
|
|
207997
|
+
categoryDescriptionEntry("search", "Workspace-wide full-text and structured search across Huly content."),
|
|
207998
|
+
categoryDescriptionEntry("activity", "Activity timelines and activity messages for Huly objects."),
|
|
207999
|
+
categoryDescriptionEntry(
|
|
208000
|
+
"notifications",
|
|
208001
|
+
"Inbox notifications, notification counts, read state, and notification actions."
|
|
208002
|
+
),
|
|
208003
|
+
categoryDescriptionEntry("user-statuses", "User status and online/presence status discovery."),
|
|
208004
|
+
categoryDescriptionEntry("virtual-office", "Virtual office rooms, members, presence, and office room state."),
|
|
208005
|
+
categoryDescriptionEntry(
|
|
208006
|
+
"processes",
|
|
208007
|
+
"Huly process definitions, executions, process cards, and process state transitions."
|
|
208008
|
+
),
|
|
208009
|
+
categoryDescriptionEntry(
|
|
208010
|
+
"workspace",
|
|
208011
|
+
"Workspace metadata, members, settings, access links, invites, and administrative context."
|
|
208012
|
+
),
|
|
208013
|
+
categoryDescriptionEntry(
|
|
208014
|
+
"task-management",
|
|
208015
|
+
"Task management project types, task types, issue statuses, workflow references, and process setup."
|
|
208016
|
+
),
|
|
208017
|
+
categoryDescriptionEntry(
|
|
208018
|
+
"test-management",
|
|
208019
|
+
"Test management projects, suites, cases, plans, runs, results, and plan execution."
|
|
208020
|
+
)
|
|
208021
|
+
]);
|
|
208022
|
+
var categoryDescription = (category) => CATEGORY_DESCRIPTIONS.get(category) ?? ToolDescription.make(`Huly ${category} tools.`);
|
|
208023
|
+
var listCategories = (registry2) => {
|
|
208024
|
+
const counts = /* @__PURE__ */ new Map();
|
|
208025
|
+
for (const tool of registry2.definitions) {
|
|
208026
|
+
counts.set(tool.category, (counts.get(tool.category) ?? 0) + 1);
|
|
208027
|
+
}
|
|
208028
|
+
return createSuccessResponse({
|
|
208029
|
+
categories: [...counts.entries()].map(([name, toolCount]) => ({
|
|
208030
|
+
name,
|
|
208031
|
+
description: categoryDescription(name),
|
|
208032
|
+
toolCount: Count.make(toolCount)
|
|
208033
|
+
}))
|
|
208034
|
+
});
|
|
208035
|
+
};
|
|
208036
|
+
var queryTokens = (query) => query.toLowerCase().split(/[^a-z0-9]+/u).filter((token) => token !== "");
|
|
208037
|
+
var tokenHitCount = (tokens, text) => {
|
|
208038
|
+
const lower = text.toLowerCase();
|
|
208039
|
+
return tokens.filter((token) => lower.includes(token)).length;
|
|
208040
|
+
};
|
|
208041
|
+
var toolScore = (tool, tokens, normalizedQuery) => {
|
|
208042
|
+
const params = toolParamSummary(tool);
|
|
208043
|
+
const paramText = [...params.requiredParams, ...params.optionalParams].join(" ");
|
|
208044
|
+
const categoryText = `${tool.category} ${categoryDescription(tool.category)}`;
|
|
208045
|
+
const exactScore = tool.name.toLowerCase() === normalizedQuery ? 1e4 : 0;
|
|
208046
|
+
return exactScore + tokenHitCount(tokens, tool.name) * 1e3 + tokenHitCount(tokens, categoryText) * 100 + tokenHitCount(tokens, tool.description) * 10 + tokenHitCount(tokens, paramText);
|
|
208047
|
+
};
|
|
208048
|
+
var searchToolDefinitions = (registry2, query, limit = SEARCH_DEFAULT_LIMIT_VALUE) => {
|
|
208049
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
208050
|
+
const tokens = queryTokens(normalizedQuery);
|
|
208051
|
+
if (tokens.length === 0) return [];
|
|
208052
|
+
return registry2.definitions.map((tool, index) => ({ index, score: toolScore(tool, tokens, normalizedQuery), tool })).filter((match16) => match16.score > 0).sort((a, b) => b.score - a.score || a.index - b.index).slice(0, limit).map((match16) => match16.tool);
|
|
208053
|
+
};
|
|
208054
|
+
|
|
208055
|
+
// src/mcp/proxy-tools.ts
|
|
208056
|
+
var LIST_TOOL_CATEGORIES_TOOL_NAME = ToolName.make("list_tool_categories");
|
|
208057
|
+
var SEARCH_TOOLS_TOOL_NAME = ToolName.make("search_tools");
|
|
208058
|
+
var GET_TOOL_SCHEMA_TOOL_NAME = ToolName.make("get_tool_schema");
|
|
208059
|
+
var INVOKE_TOOL_TOOL_NAME = ToolName.make("invoke_tool");
|
|
208060
|
+
var PROXY_TOOL_CATEGORY = makeToolCategory("proxy");
|
|
208061
|
+
var PROXY_TOOL_NAMES = [
|
|
208062
|
+
LIST_TOOL_CATEGORIES_TOOL_NAME,
|
|
208063
|
+
SEARCH_TOOLS_TOOL_NAME,
|
|
208064
|
+
GET_TOOL_SCHEMA_TOOL_NAME,
|
|
208065
|
+
INVOKE_TOOL_TOOL_NAME
|
|
208066
|
+
];
|
|
208067
|
+
var EmptyProxyParamsSchema = Schema_exports.Record({ key: Schema_exports.String, value: Schema_exports.Never });
|
|
208068
|
+
var SearchToolsParamsSchema = Schema_exports.Struct({
|
|
208069
|
+
query: ToolSearchQuery,
|
|
208070
|
+
limit: Schema_exports.optionalWith(SearchToolLimit, { exact: true })
|
|
208071
|
+
});
|
|
208072
|
+
var ToolNameParamsSchema = Schema_exports.Struct({
|
|
208073
|
+
toolName: ToolName
|
|
208074
|
+
});
|
|
208075
|
+
var InvokeToolParamsSchema = Schema_exports.Struct({
|
|
208076
|
+
toolName: ToolName,
|
|
208077
|
+
arguments: Schema_exports.optionalWith(Schema_exports.Unknown, { exact: true })
|
|
208078
|
+
});
|
|
208079
|
+
var ProxyToolCategorySchema = Schema_exports.Struct({
|
|
208080
|
+
name: ToolCategory,
|
|
208081
|
+
description: ToolDescription,
|
|
208082
|
+
toolCount: Count
|
|
208083
|
+
});
|
|
208084
|
+
var ListToolCategoriesResultSchema = Schema_exports.Struct({
|
|
208085
|
+
categories: Schema_exports.Array(ProxyToolCategorySchema)
|
|
208086
|
+
});
|
|
208087
|
+
var ToolSearchMatchSchema = Schema_exports.Struct({
|
|
208088
|
+
name: ToolName,
|
|
208089
|
+
category: ToolCategory,
|
|
208090
|
+
description: ToolDescription,
|
|
208091
|
+
requiredParams: Schema_exports.Array(ToolParameterName),
|
|
208092
|
+
optionalParams: Schema_exports.Array(ToolParameterName)
|
|
208093
|
+
});
|
|
208094
|
+
var SearchToolsResultSchema = Schema_exports.Struct({
|
|
208095
|
+
matches: Schema_exports.Array(ToolSearchMatchSchema)
|
|
208096
|
+
});
|
|
208097
|
+
var ToolAnnotationsSchema2 = Schema_exports.Struct({
|
|
208098
|
+
title: Schema_exports.optionalWith(Schema_exports.NonEmptyTrimmedString, { exact: true }),
|
|
208099
|
+
readOnlyHint: Schema_exports.optionalWith(Schema_exports.Boolean, { exact: true }),
|
|
208100
|
+
destructiveHint: Schema_exports.optionalWith(Schema_exports.Boolean, { exact: true }),
|
|
208101
|
+
idempotentHint: Schema_exports.optionalWith(Schema_exports.Boolean, { exact: true }),
|
|
208102
|
+
openWorldHint: Schema_exports.optionalWith(Schema_exports.Boolean, { exact: true })
|
|
208103
|
+
});
|
|
208104
|
+
var GetToolSchemaResultSchema = Schema_exports.Struct({
|
|
208105
|
+
name: ToolName,
|
|
208106
|
+
category: ToolCategory,
|
|
208107
|
+
description: ToolDescription,
|
|
208108
|
+
inputSchema: Schema_exports.Unknown,
|
|
208109
|
+
outputSchema: Schema_exports.Unknown,
|
|
208110
|
+
annotations: ToolAnnotationsSchema2
|
|
208111
|
+
});
|
|
208112
|
+
var InvokeToolResultSchema = Schema_exports.Struct({
|
|
208113
|
+
toolName: ToolName,
|
|
208114
|
+
result: Schema_exports.Unknown,
|
|
208115
|
+
warnings: Schema_exports.optionalWith(Schema_exports.Array(Schema_exports.Unknown), { exact: true })
|
|
208116
|
+
});
|
|
208117
|
+
var emptyInputSchema2 = {
|
|
208118
|
+
type: "object",
|
|
208119
|
+
properties: {},
|
|
208120
|
+
additionalProperties: false
|
|
208121
|
+
};
|
|
208122
|
+
var searchToolsInputSchema = {
|
|
208123
|
+
type: "object",
|
|
208124
|
+
properties: {
|
|
208125
|
+
query: {
|
|
208126
|
+
type: "string",
|
|
208127
|
+
minLength: 1,
|
|
208128
|
+
description: "Search text matched against Huly tool names, categories, descriptions, and parameter names."
|
|
208129
|
+
},
|
|
208130
|
+
limit: {
|
|
208131
|
+
type: "integer",
|
|
208132
|
+
minimum: 1,
|
|
208133
|
+
maximum: SEARCH_MAX_LIMIT,
|
|
208134
|
+
description: "Maximum number of matches to return. Defaults to 10 and cannot exceed 50."
|
|
208135
|
+
}
|
|
208136
|
+
},
|
|
208137
|
+
required: ["query"],
|
|
208138
|
+
additionalProperties: false
|
|
208139
|
+
};
|
|
208140
|
+
var toolNameInputSchema = {
|
|
208141
|
+
type: "object",
|
|
208142
|
+
properties: {
|
|
208143
|
+
toolName: {
|
|
208144
|
+
type: "string",
|
|
208145
|
+
minLength: 1,
|
|
208146
|
+
description: "Exact Huly tool name from search_tools or list_tool_categories results."
|
|
208147
|
+
}
|
|
208148
|
+
},
|
|
208149
|
+
required: ["toolName"],
|
|
208150
|
+
additionalProperties: false
|
|
208151
|
+
};
|
|
208152
|
+
var invokeToolInputSchema = {
|
|
208153
|
+
type: "object",
|
|
208154
|
+
properties: {
|
|
208155
|
+
toolName: {
|
|
208156
|
+
type: "string",
|
|
208157
|
+
minLength: 1,
|
|
208158
|
+
description: "Exact Huly tool name to invoke through the proxy."
|
|
208159
|
+
},
|
|
208160
|
+
arguments: {
|
|
208161
|
+
description: "Arguments object for the target Huly tool. Use {} when the target tool accepts no parameters."
|
|
208162
|
+
}
|
|
208163
|
+
},
|
|
208164
|
+
required: ["toolName"],
|
|
208165
|
+
additionalProperties: false
|
|
208166
|
+
};
|
|
208167
|
+
var readOnlyProxyAnnotations = (title) => ({
|
|
208168
|
+
title,
|
|
208169
|
+
readOnlyHint: true,
|
|
208170
|
+
destructiveHint: false,
|
|
208171
|
+
idempotentHint: true,
|
|
208172
|
+
openWorldHint: false
|
|
208173
|
+
});
|
|
208174
|
+
var proxyToolDefinitions = [
|
|
208175
|
+
createToolDefinition({
|
|
208176
|
+
name: LIST_TOOL_CATEGORIES_TOOL_NAME,
|
|
208177
|
+
description: "Lists Huly tool categories available through this proxy. Use this first when you need a broad map of capabilities before searching for a specific Huly tool.",
|
|
208178
|
+
inputSchema: emptyInputSchema2,
|
|
208179
|
+
outputSchema: createToolOutputSchema(ListToolCategoriesResultSchema),
|
|
208180
|
+
category: PROXY_TOOL_CATEGORY,
|
|
208181
|
+
annotations: readOnlyProxyAnnotations("List Tool Categories")
|
|
208182
|
+
}),
|
|
208183
|
+
createToolDefinition({
|
|
208184
|
+
name: SEARCH_TOOLS_TOOL_NAME,
|
|
208185
|
+
description: "Searches the current proxy-visible Huly tool catalog by tool name, category, description, and parameter names. Returns exact tool names plus required and optional parameter names for single-call follow-up with get_tool_schema or invoke_tool.",
|
|
208186
|
+
inputSchema: searchToolsInputSchema,
|
|
208187
|
+
outputSchema: createToolOutputSchema(SearchToolsResultSchema),
|
|
208188
|
+
category: PROXY_TOOL_CATEGORY,
|
|
208189
|
+
annotations: readOnlyProxyAnnotations("Search Tools")
|
|
208190
|
+
}),
|
|
208191
|
+
createToolDefinition({
|
|
208192
|
+
name: GET_TOOL_SCHEMA_TOOL_NAME,
|
|
208193
|
+
description: "Returns the exact input and output schema for one proxy-visible Huly tool. Use this before invoke_tool when you are not certain about required argument names or result shape.",
|
|
208194
|
+
inputSchema: toolNameInputSchema,
|
|
208195
|
+
outputSchema: createToolOutputSchema(GetToolSchemaResultSchema),
|
|
208196
|
+
category: PROXY_TOOL_CATEGORY,
|
|
208197
|
+
annotations: readOnlyProxyAnnotations("Get Tool Schema")
|
|
208198
|
+
}),
|
|
208199
|
+
createToolDefinition({
|
|
208200
|
+
name: INVOKE_TOOL_TOOL_NAME,
|
|
208201
|
+
description: "Invokes one proxy-visible Huly tool by exact name with its arguments. This tool can call read or write Huly operations; check get_tool_schema and the target tool annotations when safety matters.",
|
|
208202
|
+
inputSchema: invokeToolInputSchema,
|
|
208203
|
+
outputSchema: createToolOutputSchema(InvokeToolResultSchema),
|
|
208204
|
+
category: PROXY_TOOL_CATEGORY,
|
|
208205
|
+
annotations: {
|
|
208206
|
+
title: "Invoke Tool",
|
|
208207
|
+
readOnlyHint: false,
|
|
208208
|
+
destructiveHint: true,
|
|
208209
|
+
idempotentHint: false,
|
|
208210
|
+
openWorldHint: false
|
|
208211
|
+
}
|
|
208212
|
+
})
|
|
208213
|
+
];
|
|
208214
|
+
var isProxyToolName = (name) => PROXY_TOOL_NAMES.some((toolName) => toolName === name);
|
|
208215
|
+
var decodeOrError = (schema, input, toolName) => {
|
|
208216
|
+
const decoded = Schema_exports.decodeUnknownEither(schema)(input ?? {});
|
|
208217
|
+
if (Either_exports.isRight(decoded)) return decoded.right;
|
|
208218
|
+
return mapParseErrorToMcp(decoded.left, toolName);
|
|
208219
|
+
};
|
|
208220
|
+
var isRecord5 = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
208221
|
+
var isMcpToolResponse = (value3) => isRecord5(value3) && Array.isArray(value3.content);
|
|
208222
|
+
var searchTools2 = (registry2, args2) => {
|
|
208223
|
+
const params = decodeOrError(SearchToolsParamsSchema, args2, SEARCH_TOOLS_TOOL_NAME);
|
|
208224
|
+
if (isMcpToolResponse(params)) return params;
|
|
208225
|
+
const limit = params.limit ?? SEARCH_DEFAULT_LIMIT_VALUE;
|
|
208226
|
+
const matches = searchToolDefinitions(registry2, params.query, limit).map((tool) => {
|
|
208227
|
+
const paramSummary = toolParamSummary(tool);
|
|
208228
|
+
return {
|
|
208229
|
+
name: tool.name,
|
|
208230
|
+
category: tool.category,
|
|
208231
|
+
description: tool.description,
|
|
208232
|
+
requiredParams: paramSummary.requiredParams,
|
|
208233
|
+
optionalParams: paramSummary.optionalParams
|
|
208234
|
+
};
|
|
208235
|
+
});
|
|
208236
|
+
return createSuccessResponse({ matches });
|
|
208237
|
+
};
|
|
208238
|
+
var getToolSchema = (registry2, args2) => {
|
|
208239
|
+
const params = decodeOrError(ToolNameParamsSchema, args2, GET_TOOL_SCHEMA_TOOL_NAME);
|
|
208240
|
+
if (isMcpToolResponse(params)) return params;
|
|
208241
|
+
const tool = registry2.tools.get(params.toolName);
|
|
208242
|
+
if (tool === void 0) return createUnknownToolError(params.toolName);
|
|
208243
|
+
return createSuccessResponse({
|
|
208244
|
+
name: tool.name,
|
|
208245
|
+
category: tool.category,
|
|
208246
|
+
description: tool.description,
|
|
208247
|
+
inputSchema: tool.inputSchema,
|
|
208248
|
+
outputSchema: tool.outputSchema,
|
|
208249
|
+
annotations: resolveAnnotations(tool)
|
|
208250
|
+
});
|
|
208251
|
+
};
|
|
208252
|
+
var invokeTool = async (registry2, args2, clients) => {
|
|
208253
|
+
const params = decodeOrError(InvokeToolParamsSchema, args2, INVOKE_TOOL_TOOL_NAME);
|
|
208254
|
+
if (isMcpToolResponse(params)) return params;
|
|
208255
|
+
if (!registry2.tools.has(params.toolName)) return createUnknownToolError(params.toolName);
|
|
208256
|
+
const response = await registry2.handleToolCall(
|
|
208257
|
+
params.toolName,
|
|
208258
|
+
params.arguments,
|
|
208259
|
+
clients.hulyClient,
|
|
208260
|
+
clients.storageClient,
|
|
208261
|
+
clients.workspaceClient
|
|
208262
|
+
);
|
|
208263
|
+
if (response === null) return createUnknownToolError(params.toolName);
|
|
208264
|
+
if (response.isError === true) return response;
|
|
208265
|
+
const warnings = response.structuredContent?.warnings ?? [];
|
|
208266
|
+
return createSuccessResponse(
|
|
208267
|
+
{
|
|
208268
|
+
toolName: params.toolName,
|
|
208269
|
+
result: response.structuredContent?.result ?? response.content,
|
|
208270
|
+
...warnings.length === 0 ? {} : { warnings }
|
|
208271
|
+
},
|
|
208272
|
+
warnings
|
|
208273
|
+
);
|
|
208274
|
+
};
|
|
208275
|
+
var handleProxyToolCall = async (input) => {
|
|
208276
|
+
switch (input.toolName) {
|
|
208277
|
+
case LIST_TOOL_CATEGORIES_TOOL_NAME: {
|
|
208278
|
+
const params = decodeOrError(EmptyProxyParamsSchema, input.args, LIST_TOOL_CATEGORIES_TOOL_NAME);
|
|
208279
|
+
if (isMcpToolResponse(params)) return params;
|
|
208280
|
+
return listCategories(input.proxyCandidateRegistry);
|
|
208281
|
+
}
|
|
208282
|
+
case SEARCH_TOOLS_TOOL_NAME:
|
|
208283
|
+
return searchTools2(input.proxyCandidateRegistry, input.args);
|
|
208284
|
+
case GET_TOOL_SCHEMA_TOOL_NAME:
|
|
208285
|
+
return getToolSchema(input.proxyCandidateRegistry, input.args);
|
|
208286
|
+
case INVOKE_TOOL_TOOL_NAME:
|
|
208287
|
+
if (input.clients === void 0) {
|
|
208288
|
+
return createInvalidParamsError("invoke_tool requires initialized Huly clients.", "ProxyClientsMissing");
|
|
208289
|
+
}
|
|
208290
|
+
return invokeTool(input.proxyCandidateRegistry, input.args, input.clients);
|
|
208291
|
+
default:
|
|
208292
|
+
return createUnknownToolError(input.toolName);
|
|
208293
|
+
}
|
|
208294
|
+
};
|
|
208295
|
+
|
|
208296
|
+
// src/mcp/tool-mode.ts
|
|
208297
|
+
var ToolExposureModeSchema = Schema_exports.Literal("native", "proxy");
|
|
208298
|
+
var ToolModeConfigSchema = Schema_exports.Literal("auto", "native", "proxy");
|
|
208299
|
+
var ProxyOutputStrictEnvSchema = Schema_exports.Literal("true", "false");
|
|
208300
|
+
var decodeToolExposureMode = Schema_exports.decodeUnknownSync(ToolExposureModeSchema);
|
|
208301
|
+
var NATIVE_TOOL_EXPOSURE_MODE = decodeToolExposureMode("native");
|
|
208302
|
+
var PROXY_TOOL_EXPOSURE_MODE = decodeToolExposureMode("proxy");
|
|
208303
|
+
var ToolExposureConfigSchema = Schema_exports.Struct({
|
|
208304
|
+
configuredMode: ToolModeConfigSchema,
|
|
208305
|
+
proxyOutputStrict: Schema_exports.Boolean
|
|
208306
|
+
});
|
|
208307
|
+
var ToolExposureEnvSchema = Schema_exports.Struct({
|
|
208308
|
+
hulyToolMode: Schema_exports.optionalWith(Schema_exports.String, { exact: true }),
|
|
208309
|
+
proxyOutputStrict: Schema_exports.optionalWith(Schema_exports.String, { exact: true })
|
|
208310
|
+
});
|
|
208311
|
+
var DEFAULT_TOOL_EXPOSURE_CONFIG = ToolExposureConfigSchema.make({
|
|
208312
|
+
configuredMode: "auto",
|
|
208313
|
+
proxyOutputStrict: false
|
|
208314
|
+
});
|
|
208315
|
+
var isUnknownRecord = (input) => typeof input === "object" && input !== null && !Array.isArray(input);
|
|
208316
|
+
var envShapeFailure = (input) => {
|
|
208317
|
+
if (isUnknownRecord(input)) {
|
|
208318
|
+
if ("hulyToolMode" in input && input.hulyToolMode !== void 0 && typeof input.hulyToolMode !== "string") {
|
|
208319
|
+
return {
|
|
208320
|
+
_tag: "Failure",
|
|
208321
|
+
field: "HULY_TOOL_MODE",
|
|
208322
|
+
message: "Configuration error: HULY_TOOL_MODE must be a string when set."
|
|
208323
|
+
};
|
|
208324
|
+
}
|
|
208325
|
+
if ("proxyOutputStrict" in input && input.proxyOutputStrict !== void 0 && typeof input.proxyOutputStrict !== "string") {
|
|
208326
|
+
return {
|
|
208327
|
+
_tag: "Failure",
|
|
208328
|
+
field: "PROXY_OUTPUT_STRICT",
|
|
208329
|
+
message: "Configuration error: PROXY_OUTPUT_STRICT must be a string when set."
|
|
208330
|
+
};
|
|
208331
|
+
}
|
|
208332
|
+
}
|
|
208333
|
+
return {
|
|
208334
|
+
_tag: "Failure",
|
|
208335
|
+
field: "HULY_TOOL_MODE",
|
|
208336
|
+
message: "Configuration error: HULY_TOOL_MODE and PROXY_OUTPUT_STRICT must be string environment values."
|
|
208337
|
+
};
|
|
208338
|
+
};
|
|
208339
|
+
var ClientKindSchema = Schema_exports.Literal(
|
|
208340
|
+
"claude-code",
|
|
208341
|
+
"claude-ai",
|
|
208342
|
+
"cursor",
|
|
208343
|
+
"windsurf",
|
|
208344
|
+
"github-copilot",
|
|
208345
|
+
"codex",
|
|
208346
|
+
"opencode",
|
|
208347
|
+
"unknown"
|
|
208348
|
+
);
|
|
208349
|
+
var DEFAULT_MODE_BY_CLIENT_KIND = {
|
|
208350
|
+
"claude-code": NATIVE_TOOL_EXPOSURE_MODE,
|
|
208351
|
+
"claude-ai": PROXY_TOOL_EXPOSURE_MODE,
|
|
208352
|
+
cursor: PROXY_TOOL_EXPOSURE_MODE,
|
|
208353
|
+
windsurf: PROXY_TOOL_EXPOSURE_MODE,
|
|
208354
|
+
"github-copilot": PROXY_TOOL_EXPOSURE_MODE,
|
|
208355
|
+
codex: PROXY_TOOL_EXPOSURE_MODE,
|
|
208356
|
+
opencode: PROXY_TOOL_EXPOSURE_MODE,
|
|
208357
|
+
unknown: PROXY_TOOL_EXPOSURE_MODE
|
|
208358
|
+
};
|
|
208359
|
+
var McpClientName = Schema_exports.Trim.pipe(Schema_exports.nonEmptyString(), Schema_exports.brand("McpClientName")).annotations({
|
|
208360
|
+
identifier: "McpClientName",
|
|
208361
|
+
title: "McpClientName",
|
|
208362
|
+
description: "Trimmed MCP client name from initialize or request metadata."
|
|
208363
|
+
});
|
|
208364
|
+
var McpClientInfoLikeSchema = Schema_exports.Struct({
|
|
208365
|
+
name: Schema_exports.optionalWith(McpClientName, { exact: true })
|
|
208366
|
+
});
|
|
208367
|
+
var trimmedLower = (value3) => value3.trim().toLowerCase();
|
|
208368
|
+
var parseConfiguredMode = (raw) => {
|
|
208369
|
+
if (raw === void 0) {
|
|
208370
|
+
return { _tag: "Success", value: DEFAULT_TOOL_EXPOSURE_CONFIG.configuredMode };
|
|
208371
|
+
}
|
|
208372
|
+
const normalized = trimmedLower(raw);
|
|
208373
|
+
const decoded = Schema_exports.decodeUnknownEither(ToolModeConfigSchema)(normalized);
|
|
208374
|
+
if (Either_exports.isRight(decoded)) return { _tag: "Success", value: decoded.right };
|
|
208375
|
+
return {
|
|
208376
|
+
_tag: "Failure",
|
|
208377
|
+
field: "HULY_TOOL_MODE",
|
|
208378
|
+
message: `Configuration error: HULY_TOOL_MODE must be one of auto, native, or proxy; received "${raw}".`
|
|
208379
|
+
};
|
|
208380
|
+
};
|
|
208381
|
+
var parseProxyOutputStrict = (raw) => {
|
|
208382
|
+
if (raw === void 0) return { _tag: "Success", value: false };
|
|
208383
|
+
const normalized = trimmedLower(raw);
|
|
208384
|
+
const decoded = Schema_exports.decodeUnknownEither(ProxyOutputStrictEnvSchema)(normalized);
|
|
208385
|
+
if (Either_exports.isRight(decoded)) return { _tag: "Success", value: decoded.right === "true" };
|
|
208386
|
+
return {
|
|
208387
|
+
_tag: "Failure",
|
|
208388
|
+
field: "PROXY_OUTPUT_STRICT",
|
|
208389
|
+
message: `Configuration error: PROXY_OUTPUT_STRICT must be true or false; received "${raw}".`
|
|
208390
|
+
};
|
|
208391
|
+
};
|
|
208392
|
+
var parseToolExposureConfig = (input) => {
|
|
208393
|
+
const decodedEnv = Schema_exports.decodeUnknownEither(ToolExposureEnvSchema)(input);
|
|
208394
|
+
if (Either_exports.isLeft(decodedEnv)) return envShapeFailure(input);
|
|
208395
|
+
const env = decodedEnv.right;
|
|
208396
|
+
const configuredMode = parseConfiguredMode(env.hulyToolMode);
|
|
208397
|
+
if (configuredMode._tag === "Failure") return configuredMode;
|
|
208398
|
+
const proxyOutputStrict = parseProxyOutputStrict(env.proxyOutputStrict);
|
|
208399
|
+
if (proxyOutputStrict._tag === "Failure") return proxyOutputStrict;
|
|
208400
|
+
return {
|
|
208401
|
+
_tag: "Success",
|
|
208402
|
+
value: ToolExposureConfigSchema.make({
|
|
208403
|
+
configuredMode: configuredMode.value,
|
|
208404
|
+
proxyOutputStrict: proxyOutputStrict.value
|
|
208405
|
+
})
|
|
208406
|
+
};
|
|
208407
|
+
};
|
|
208408
|
+
var parseMcpClientInfo = (input) => {
|
|
208409
|
+
const decoded = Schema_exports.decodeUnknownEither(McpClientInfoLikeSchema)(input);
|
|
208410
|
+
return Either_exports.isRight(decoded) ? decoded.right : void 0;
|
|
208411
|
+
};
|
|
208412
|
+
var rawClientName = (clientInfo) => {
|
|
208413
|
+
const name = clientInfo?.name?.toLowerCase();
|
|
208414
|
+
if (name === void 0 || name === "") return "";
|
|
208415
|
+
return name;
|
|
208416
|
+
};
|
|
208417
|
+
var withoutRemoteSuffix = (name) => name.replace(/\s*\([^)]*\)\s*$/, "").trim();
|
|
208418
|
+
var makeClientKind = Schema_exports.decodeUnknownSync(ClientKindSchema);
|
|
208419
|
+
var classifyMcpClient = (clientInfo) => {
|
|
208420
|
+
const rawName = rawClientName(clientInfo);
|
|
208421
|
+
if (rawName === "claude-code") return makeClientKind("claude-code");
|
|
208422
|
+
const name = withoutRemoteSuffix(rawName);
|
|
208423
|
+
if (name === "claude-code") return makeClientKind("unknown");
|
|
208424
|
+
if (name === "claude-ai") return makeClientKind("claude-ai");
|
|
208425
|
+
if (name === "cursor-vscode" || name.startsWith("cursor")) return makeClientKind("cursor");
|
|
208426
|
+
if (name.startsWith("windsurf") || name.startsWith("cascade")) return makeClientKind("windsurf");
|
|
208427
|
+
if (name.startsWith("github-copilot") || name.startsWith("copilot") || name.startsWith("visual studio code") || name.startsWith("visual-studio-code")) {
|
|
208428
|
+
return makeClientKind("github-copilot");
|
|
208429
|
+
}
|
|
208430
|
+
if (name.startsWith("codex") || name.startsWith("openai-codex")) return makeClientKind("codex");
|
|
208431
|
+
if (name.startsWith("opencode")) return makeClientKind("opencode");
|
|
208432
|
+
return makeClientKind("unknown");
|
|
208433
|
+
};
|
|
208434
|
+
var resolveToolExposureMode = (input) => {
|
|
208435
|
+
if (input.configuredMode !== "auto") return input.configuredMode;
|
|
208436
|
+
return DEFAULT_MODE_BY_CLIENT_KIND[classifyMcpClient(input.clientInfo)];
|
|
208437
|
+
};
|
|
208438
|
+
|
|
208439
|
+
// src/mcp/protocol-tool-exposure.ts
|
|
208440
|
+
var BUILTIN_TOOL_COUNT = 2;
|
|
208441
|
+
var DEFAULT_HANDLER_EXPOSURE_CONFIG = {
|
|
208442
|
+
configuredMode: "native",
|
|
208443
|
+
proxyOutputStrict: false
|
|
208444
|
+
};
|
|
208445
|
+
var emptyToolRegistry = {
|
|
208446
|
+
tools: /* @__PURE__ */ new Map(),
|
|
208447
|
+
definitions: [],
|
|
208448
|
+
handleToolCall: async () => null
|
|
208449
|
+
};
|
|
208450
|
+
var isObjectPropertyEntry = (entry) => {
|
|
208451
|
+
const value3 = entry[1];
|
|
208452
|
+
return typeof value3 === "object" && value3 !== null;
|
|
208453
|
+
};
|
|
208454
|
+
var objectProperties = (properties) => {
|
|
208455
|
+
if (properties === void 0) return void 0;
|
|
208456
|
+
return Object.entries(properties).filter(isObjectPropertyEntry).reduce(
|
|
208457
|
+
(acc, [key, value3]) => ({ ...acc, [key]: value3 }),
|
|
208458
|
+
{}
|
|
208459
|
+
);
|
|
208460
|
+
};
|
|
208461
|
+
var toProtocolObjectSchema = (schema) => {
|
|
208462
|
+
const { properties, required: required4, ...rest } = schema;
|
|
208463
|
+
const convertedProperties = objectProperties(properties);
|
|
208464
|
+
return {
|
|
208465
|
+
...stripCollidingSchemaIdsRecord(rest),
|
|
208466
|
+
type: "object",
|
|
208467
|
+
...convertedProperties === void 0 ? {} : { properties: stripCollidingSchemaIdsProperties(convertedProperties) },
|
|
208468
|
+
...required4 === void 0 ? {} : { required: [...required4] }
|
|
208469
|
+
};
|
|
208470
|
+
};
|
|
208471
|
+
var normalizeRegistries = (registry2) => "fullRegistry" in registry2 ? registry2 : { fullRegistry: registry2, scopedNativeRegistry: registry2 };
|
|
208472
|
+
var defaultExposureOptions = () => ({
|
|
208473
|
+
exposureConfig: DEFAULT_HANDLER_EXPOSURE_CONFIG,
|
|
208474
|
+
toolScopeFilteringActive: false,
|
|
208475
|
+
currentClientInfo: () => void 0
|
|
208476
|
+
});
|
|
208477
|
+
var resolveProxyCandidateRegistry = (registries, options) => {
|
|
208478
|
+
if (!options.exposureConfig.proxyOutputStrict) return registries.fullRegistry;
|
|
208479
|
+
return options.toolScopeFilteringActive ? registries.scopedNativeRegistry : registries.fullRegistry;
|
|
208480
|
+
};
|
|
208481
|
+
var resolveProtocolExposure = (registries, options) => {
|
|
208482
|
+
const clientInfo = options.currentClientInfo();
|
|
208483
|
+
const clientKind = classifyMcpClient(clientInfo);
|
|
208484
|
+
const resolvedMode = resolveToolExposureMode({
|
|
208485
|
+
configuredMode: options.exposureConfig.configuredMode,
|
|
208486
|
+
...clientInfo === void 0 ? {} : { clientInfo }
|
|
208487
|
+
});
|
|
208488
|
+
const proxyCandidateRegistry = resolveProxyCandidateRegistry(registries, options);
|
|
208489
|
+
const visibleNativeRegistry = resolvedMode === "native" ? registries.scopedNativeRegistry : options.toolScopeFilteringActive && !options.exposureConfig.proxyOutputStrict ? registries.scopedNativeRegistry : emptyToolRegistry;
|
|
208490
|
+
const visibleToolCount = BUILTIN_TOOL_COUNT + visibleNativeRegistry.definitions.length + (resolvedMode === "proxy" ? proxyToolDefinitions.length : 0);
|
|
208491
|
+
return {
|
|
208492
|
+
context: {
|
|
208493
|
+
configuredMode: options.exposureConfig.configuredMode,
|
|
208494
|
+
resolvedMode,
|
|
208495
|
+
clientKind,
|
|
208496
|
+
proxyOutputStrict: options.exposureConfig.proxyOutputStrict,
|
|
208497
|
+
visibleToolCount,
|
|
208498
|
+
nativeVisibleToolCount: visibleNativeRegistry.definitions.length,
|
|
208499
|
+
proxyCandidateToolCount: proxyCandidateRegistry.definitions.length,
|
|
208500
|
+
proxyToolNames: resolvedMode === "proxy" ? PROXY_TOOL_NAMES : []
|
|
208501
|
+
},
|
|
208502
|
+
visibleNativeRegistry,
|
|
208503
|
+
proxyCandidateRegistry
|
|
208504
|
+
};
|
|
208505
|
+
};
|
|
208506
|
+
var toListedTool = (tool) => ({
|
|
208507
|
+
name: tool.name,
|
|
208508
|
+
description: tool.description,
|
|
208509
|
+
inputSchema: toProtocolObjectSchema(tool.inputSchema),
|
|
208510
|
+
...tool.outputSchema === void 0 ? {} : { outputSchema: toProtocolObjectSchema(tool.outputSchema) },
|
|
208511
|
+
...tool.annotations === void 0 ? {} : { annotations: tool.annotations }
|
|
208512
|
+
});
|
|
208513
|
+
var toListedHulyTool = (tool) => toListedTool({
|
|
208514
|
+
name: tool.name,
|
|
208515
|
+
description: tool.description,
|
|
208516
|
+
inputSchema: toClientCompatibleInputSchema(tool.inputSchema),
|
|
208517
|
+
outputSchema: tool.outputSchema,
|
|
208518
|
+
annotations: resolveAnnotations(tool)
|
|
208519
|
+
});
|
|
208520
|
+
|
|
208521
|
+
// src/mcp/protocol-handlers.ts
|
|
208522
|
+
var DRAIN_POLL_MS = 50;
|
|
208523
|
+
var DRAIN_TIMEOUT_MS2 = 3e4;
|
|
208524
|
+
var NPM_FETCH_TIMEOUT_MS = 5e3;
|
|
208525
|
+
var NPM_PACKAGE_NAME2 = "@firfi/huly-mcp";
|
|
208526
|
+
var computeOutputBytes = (response) => response.content.reduce((sum2, c) => sum2 + c.text.length, 0);
|
|
207633
208527
|
var deriveEditMode = (name, args2) => {
|
|
207634
208528
|
if (name !== "edit_document" || args2 === void 0) return void 0;
|
|
207635
208529
|
if (typeof args2 !== "object" || args2 === null || Array.isArray(args2)) return void 0;
|
|
@@ -207671,63 +208565,15 @@ var fetchLatestNpmVersion = async (fetchImpl = fetch) => {
|
|
|
207671
208565
|
return "unknown";
|
|
207672
208566
|
}
|
|
207673
208567
|
};
|
|
207674
|
-
var
|
|
207675
|
-
|
|
207676
|
-
|
|
207677
|
-
|
|
207678
|
-
|
|
207679
|
-
|
|
207680
|
-
|
|
207681
|
-
|
|
207682
|
-
{}
|
|
207683
|
-
);
|
|
207684
|
-
};
|
|
207685
|
-
var toProtocolObjectSchema = (schema) => {
|
|
207686
|
-
const { properties, required: required4, ...rest } = schema;
|
|
207687
|
-
const convertedProperties = objectProperties(properties);
|
|
207688
|
-
return {
|
|
207689
|
-
...rest,
|
|
207690
|
-
type: "object",
|
|
207691
|
-
...convertedProperties === void 0 ? {} : { properties: convertedProperties },
|
|
207692
|
-
...required4 === void 0 ? {} : { required: [...required4] }
|
|
208568
|
+
var isRecord6 = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
208569
|
+
var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyContext, clock3 = liveNowClock, fetchLatestVersion = fetchLatestNpmVersion, exposureOptions = {}) => {
|
|
208570
|
+
const registries = normalizeRegistries(registry2);
|
|
208571
|
+
const defaults = defaultExposureOptions();
|
|
208572
|
+
const protocolExposureOptions = {
|
|
208573
|
+
exposureConfig: exposureOptions.exposureConfig ?? defaults.exposureConfig,
|
|
208574
|
+
currentClientInfo: exposureOptions.currentClientInfo ?? defaults.currentClientInfo,
|
|
208575
|
+
toolScopeFilteringActive: exposureOptions.toolScopeFilteringActive ?? defaults.toolScopeFilteringActive
|
|
207693
208576
|
};
|
|
207694
|
-
};
|
|
207695
|
-
var createResourceClientResolutionError = (uri, _error) => new McpError(
|
|
207696
|
-
ErrorCode.InternalError,
|
|
207697
|
-
`Failed to initialize Huly clients while reading resource "${uri}". Verify Huly URL, workspace, and authentication configuration.`
|
|
207698
|
-
);
|
|
207699
|
-
var createResourceListClientResolutionError = (_error) => new McpError(
|
|
207700
|
-
ErrorCode.InternalError,
|
|
207701
|
-
"Failed to initialize Huly clients while listing resources. Verify Huly URL, workspace, and authentication configuration."
|
|
207702
|
-
);
|
|
207703
|
-
var isConfigValidationFailure = (error2) => {
|
|
207704
|
-
if (error2 instanceof ConfigValidationError) return true;
|
|
207705
|
-
if (!Runtime_exports.isFiberFailure(error2)) return false;
|
|
207706
|
-
return Chunk_exports.toArray(Cause_exports.failures(error2[Runtime_exports.FiberFailureCauseId])).some(
|
|
207707
|
-
(failure) => failure instanceof ConfigValidationError
|
|
207708
|
-
);
|
|
207709
|
-
};
|
|
207710
|
-
var shouldReturnEmptyResourceListOnClientResolutionFailure = (error2, _getHulyContext) => isConfigValidationFailure(error2);
|
|
207711
|
-
var resolveResourceClientsOrThrow = async (resolveClients, mapError7) => {
|
|
207712
|
-
try {
|
|
207713
|
-
return await resolveClients();
|
|
207714
|
-
} catch (e) {
|
|
207715
|
-
throw mapError7(e);
|
|
207716
|
-
}
|
|
207717
|
-
};
|
|
207718
|
-
var throwResourceReadError = (uri, cause3) => {
|
|
207719
|
-
const failures3 = Chunk_exports.toArray(Cause_exports.failures(cause3));
|
|
207720
|
-
const failure = failures3[0];
|
|
207721
|
-
if (failure instanceof McpError) throw failure;
|
|
207722
|
-
throw new McpError(ErrorCode.InternalError, `Failed to read Huly resource "${uri}"`);
|
|
207723
|
-
};
|
|
207724
|
-
var throwResourceListError = (cause3) => {
|
|
207725
|
-
const failures3 = Chunk_exports.toArray(Cause_exports.failures(cause3));
|
|
207726
|
-
const failure = failures3[0];
|
|
207727
|
-
if (failure instanceof McpError) throw failure;
|
|
207728
|
-
throw new McpError(ErrorCode.InternalError, "Failed to list Huly resources");
|
|
207729
|
-
};
|
|
207730
|
-
var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyContext, clock3 = liveNowClock, fetchLatestVersion = fetchLatestNpmVersion) => {
|
|
207731
208577
|
let inflight = 0;
|
|
207732
208578
|
const drainInflight = createDrainInflight(() => inflight, clock3);
|
|
207733
208579
|
const enter = () => {
|
|
@@ -207737,29 +208583,24 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207737
208583
|
inflight--;
|
|
207738
208584
|
};
|
|
207739
208585
|
const listTools = async () => {
|
|
207740
|
-
|
|
208586
|
+
const exposure = resolveProtocolExposure(registries, protocolExposureOptions);
|
|
208587
|
+
telemetry.firstListTools({
|
|
208588
|
+
clientKind: exposure.context.clientKind,
|
|
208589
|
+
resolvedMode: exposure.context.resolvedMode
|
|
208590
|
+
});
|
|
207741
208591
|
return {
|
|
207742
208592
|
tools: [
|
|
207743
|
-
versionToolDefinition,
|
|
207744
|
-
|
|
207745
|
-
...
|
|
207746
|
-
|
|
207747
|
-
description: tool.description,
|
|
207748
|
-
inputSchema: toClientCompatibleInputSchema(tool.inputSchema),
|
|
207749
|
-
outputSchema: tool.outputSchema,
|
|
207750
|
-
annotations: resolveAnnotations(tool)
|
|
207751
|
-
}))
|
|
207752
|
-
].map((tool) => ({
|
|
207753
|
-
...tool,
|
|
207754
|
-
inputSchema: toProtocolObjectSchema(tool.inputSchema),
|
|
207755
|
-
outputSchema: toProtocolObjectSchema(tool.outputSchema)
|
|
207756
|
-
}))
|
|
208593
|
+
...[versionToolDefinition, getHulyContextToolDefinition].map(toListedTool),
|
|
208594
|
+
...exposure.context.resolvedMode === "proxy" ? proxyToolDefinitions.map(toListedHulyTool) : [],
|
|
208595
|
+
...exposure.visibleNativeRegistry.definitions.map(toListedHulyTool)
|
|
208596
|
+
]
|
|
207757
208597
|
};
|
|
207758
208598
|
};
|
|
207759
208599
|
const callTool = async (request3) => {
|
|
207760
208600
|
enter();
|
|
207761
208601
|
try {
|
|
207762
208602
|
const { arguments: args2, name } = request3.params;
|
|
208603
|
+
const exposure = resolveProtocolExposure(registries, protocolExposureOptions);
|
|
207763
208604
|
const start3 = clock3.currentTimeMillis();
|
|
207764
208605
|
const inputBytes = JSON.stringify(args2 ?? {}).length;
|
|
207765
208606
|
const returnError = (errorResponse, editMode2) => {
|
|
@@ -207767,6 +208608,8 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207767
208608
|
telemetry.toolCalled({
|
|
207768
208609
|
toolName: name,
|
|
207769
208610
|
status: "error",
|
|
208611
|
+
clientKind: exposure.context.clientKind,
|
|
208612
|
+
resolvedMode: exposure.context.resolvedMode,
|
|
207770
208613
|
errorTag: errorResponse._meta?.errorTag,
|
|
207771
208614
|
durationMs: durationMs2,
|
|
207772
208615
|
inputBytes,
|
|
@@ -207776,7 +208619,7 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207776
208619
|
return toMcpResponse(errorResponse);
|
|
207777
208620
|
};
|
|
207778
208621
|
if (name === VERSION_TOOL_NAME) {
|
|
207779
|
-
if (!isEmptyArgumentsObject(args2)) return returnError(createUnexpectedArgumentsError(
|
|
208622
|
+
if (!isEmptyArgumentsObject(args2)) return returnError(createUnexpectedArgumentsError(VERSION_TOOL_NAME));
|
|
207780
208623
|
const latest = await fetchLatestVersion();
|
|
207781
208624
|
let versionResult;
|
|
207782
208625
|
try {
|
|
@@ -207789,6 +208632,8 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207789
208632
|
telemetry.toolCalled({
|
|
207790
208633
|
toolName: name,
|
|
207791
208634
|
status: "success",
|
|
208635
|
+
clientKind: exposure.context.clientKind,
|
|
208636
|
+
resolvedMode: exposure.context.resolvedMode,
|
|
207792
208637
|
durationMs: durationMs2,
|
|
207793
208638
|
inputBytes,
|
|
207794
208639
|
outputBytes: computeOutputBytes(versionResponse)
|
|
@@ -207796,10 +208641,12 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207796
208641
|
return toMcpResponse(versionResponse);
|
|
207797
208642
|
}
|
|
207798
208643
|
if (name === GET_HULY_CONTEXT_TOOL_NAME) {
|
|
207799
|
-
if (!isEmptyArgumentsObject(args2))
|
|
208644
|
+
if (!isEmptyArgumentsObject(args2)) {
|
|
208645
|
+
return returnError(createUnexpectedArgumentsError(GET_HULY_CONTEXT_TOOL_NAME));
|
|
208646
|
+
}
|
|
207800
208647
|
let context6;
|
|
207801
208648
|
try {
|
|
207802
|
-
context6 = validateHulyContextResult(getHulyContext());
|
|
208649
|
+
context6 = validateHulyContextResult(getHulyContext(exposure.context));
|
|
207803
208650
|
} catch {
|
|
207804
208651
|
return returnError(mapDomainErrorToMcp(new HulyError({ message: "Failed to build Huly context" })));
|
|
207805
208652
|
}
|
|
@@ -207808,21 +208655,68 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207808
208655
|
telemetry.toolCalled({
|
|
207809
208656
|
toolName: name,
|
|
207810
208657
|
status: "success",
|
|
208658
|
+
clientKind: exposure.context.clientKind,
|
|
208659
|
+
resolvedMode: exposure.context.resolvedMode,
|
|
207811
208660
|
durationMs: durationMs2,
|
|
207812
208661
|
inputBytes,
|
|
207813
208662
|
outputBytes: computeOutputBytes(contextResponse)
|
|
207814
208663
|
});
|
|
207815
208664
|
return toMcpResponse(contextResponse);
|
|
207816
208665
|
}
|
|
207817
|
-
|
|
208666
|
+
if (isProxyToolName(name)) {
|
|
208667
|
+
if (exposure.context.resolvedMode !== "proxy") return returnError(createUnknownToolError(name));
|
|
208668
|
+
const editMode2 = name === INVOKE_TOOL_TOOL_NAME && isRecord6(args2) && typeof args2.toolName === "string" ? deriveEditMode(args2.toolName, args2.arguments) : void 0;
|
|
208669
|
+
let clients2;
|
|
208670
|
+
if (name === INVOKE_TOOL_TOOL_NAME) {
|
|
208671
|
+
try {
|
|
208672
|
+
clients2 = await resolveClients();
|
|
208673
|
+
} catch (e) {
|
|
208674
|
+
const errorResponse = mapDomainErrorToMcp(
|
|
208675
|
+
new HulyError({
|
|
208676
|
+
message: `Failed to initialize Huly clients: ${e instanceof Error ? e.message : String(e)}`
|
|
208677
|
+
})
|
|
208678
|
+
);
|
|
208679
|
+
return returnError(errorResponse, editMode2);
|
|
208680
|
+
}
|
|
208681
|
+
}
|
|
208682
|
+
const response2 = await handleProxyToolCall({
|
|
208683
|
+
toolName: name,
|
|
208684
|
+
args: args2,
|
|
208685
|
+
proxyCandidateRegistry: exposure.proxyCandidateRegistry,
|
|
208686
|
+
...clients2 === void 0 ? {} : {
|
|
208687
|
+
clients: {
|
|
208688
|
+
hulyClient: clients2.hulyClient,
|
|
208689
|
+
storageClient: clients2.storageClient,
|
|
208690
|
+
...clients2.workspaceClient === void 0 ? {} : { workspaceClient: clients2.workspaceClient }
|
|
208691
|
+
}
|
|
208692
|
+
}
|
|
208693
|
+
});
|
|
208694
|
+
const durationMs2 = clock3.currentTimeMillis() - start3;
|
|
208695
|
+
telemetry.toolCalled({
|
|
208696
|
+
toolName: name,
|
|
208697
|
+
status: response2.isError === true ? "error" : "success",
|
|
208698
|
+
clientKind: exposure.context.clientKind,
|
|
208699
|
+
resolvedMode: exposure.context.resolvedMode,
|
|
208700
|
+
errorTag: response2._meta?.errorTag,
|
|
208701
|
+
durationMs: durationMs2,
|
|
208702
|
+
inputBytes,
|
|
208703
|
+
outputBytes: computeOutputBytes(response2),
|
|
208704
|
+
editMode: editMode2
|
|
208705
|
+
});
|
|
208706
|
+
return toMcpResponse(response2);
|
|
208707
|
+
}
|
|
208708
|
+
const hulyToolName = parseToolName(name);
|
|
208709
|
+
if (hulyToolName === void 0) return returnError(createUnknownToolError(name));
|
|
208710
|
+
const nativeCallRegistry = exposure.visibleNativeRegistry.tools.has(hulyToolName) ? exposure.visibleNativeRegistry : exposure.context.resolvedMode === "proxy" ? exposure.proxyCandidateRegistry : exposure.visibleNativeRegistry;
|
|
208711
|
+
const tool = nativeCallRegistry.tools.get(hulyToolName);
|
|
207818
208712
|
if (tool === void 0) return returnError(createUnknownToolError(name));
|
|
207819
208713
|
if (isNoArgumentTool(tool) && !isEmptyArgumentsObject(args2)) {
|
|
207820
|
-
return returnError(createUnexpectedArgumentsError(
|
|
208714
|
+
return returnError(createUnexpectedArgumentsError(hulyToolName));
|
|
207821
208715
|
}
|
|
207822
208716
|
if (args2 === void 0 && requiresArgumentsObject(tool)) {
|
|
207823
|
-
return returnError(createMissingArgumentsError(
|
|
208717
|
+
return returnError(createMissingArgumentsError(hulyToolName));
|
|
207824
208718
|
}
|
|
207825
|
-
const editMode = deriveEditMode(
|
|
208719
|
+
const editMode = deriveEditMode(hulyToolName, args2);
|
|
207826
208720
|
let clients;
|
|
207827
208721
|
try {
|
|
207828
208722
|
clients = await resolveClients();
|
|
@@ -207832,8 +208726,8 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207832
208726
|
);
|
|
207833
208727
|
return returnError(errorResponse, editMode);
|
|
207834
208728
|
}
|
|
207835
|
-
const response = await
|
|
207836
|
-
|
|
208729
|
+
const response = await nativeCallRegistry.handleToolCall(
|
|
208730
|
+
hulyToolName,
|
|
207837
208731
|
args2,
|
|
207838
208732
|
clients.hulyClient,
|
|
207839
208733
|
clients.storageClient,
|
|
@@ -207842,8 +208736,10 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207842
208736
|
const durationMs = clock3.currentTimeMillis() - start3;
|
|
207843
208737
|
if (response === null) return returnError(createUnknownToolError(name), editMode);
|
|
207844
208738
|
telemetry.toolCalled({
|
|
207845
|
-
toolName:
|
|
208739
|
+
toolName: hulyToolName,
|
|
207846
208740
|
status: response.isError === true ? "error" : "success",
|
|
208741
|
+
clientKind: exposure.context.clientKind,
|
|
208742
|
+
resolvedMode: exposure.context.resolvedMode,
|
|
207847
208743
|
errorTag: response._meta?.errorTag,
|
|
207848
208744
|
durationMs,
|
|
207849
208745
|
inputBytes,
|
|
@@ -207855,55 +208751,13 @@ var createMcpProtocolHandlers = (resolveClients, telemetry, registry2, getHulyCo
|
|
|
207855
208751
|
leave();
|
|
207856
208752
|
}
|
|
207857
208753
|
};
|
|
207858
|
-
const
|
|
207859
|
-
enter();
|
|
207860
|
-
try {
|
|
207861
|
-
let clients;
|
|
207862
|
-
try {
|
|
207863
|
-
clients = await resolveClients();
|
|
207864
|
-
} catch (e) {
|
|
207865
|
-
if (shouldReturnEmptyResourceListOnClientResolutionFailure(e, getHulyContext)) return { resources: [] };
|
|
207866
|
-
throw createResourceListClientResolutionError(e);
|
|
207867
|
-
}
|
|
207868
|
-
const resourceList = await Effect_exports.runPromiseExit(
|
|
207869
|
-
listResources().pipe(
|
|
207870
|
-
Effect_exports.provideService(HulyClient, clients.hulyClient)
|
|
207871
|
-
)
|
|
207872
|
-
);
|
|
207873
|
-
if (Exit_exports.isSuccess(resourceList)) return resourceList.value;
|
|
207874
|
-
return throwResourceListError(resourceList.cause);
|
|
207875
|
-
} finally {
|
|
207876
|
-
leave();
|
|
207877
|
-
}
|
|
207878
|
-
};
|
|
207879
|
-
const readResource = async (request3) => {
|
|
207880
|
-
enter();
|
|
207881
|
-
try {
|
|
207882
|
-
const { uri } = request3.params;
|
|
207883
|
-
const clients = await resolveResourceClientsOrThrow(
|
|
207884
|
-
resolveClients,
|
|
207885
|
-
(error2) => createResourceClientResolutionError(uri, error2)
|
|
207886
|
-
);
|
|
207887
|
-
const diagnosticsScope = await Effect_exports.runPromise(makeDiagnosticsScope);
|
|
207888
|
-
const resourceRead = await Effect_exports.runPromiseExit(
|
|
207889
|
-
readHulyResource(uri).pipe(
|
|
207890
|
-
Effect_exports.provideService(HulyClient, clients.hulyClient),
|
|
207891
|
-
Effect_exports.provideService(Diagnostics, diagnosticsScope.service)
|
|
207892
|
-
)
|
|
207893
|
-
);
|
|
207894
|
-
const warnings = await Effect_exports.runPromise(diagnosticsScope.drainWarnings);
|
|
207895
|
-
if (Exit_exports.isSuccess(resourceRead)) return withResourceWarnings(resourceRead.value, warnings);
|
|
207896
|
-
return throwResourceReadError(uri, resourceRead.cause);
|
|
207897
|
-
} finally {
|
|
207898
|
-
leave();
|
|
207899
|
-
}
|
|
207900
|
-
};
|
|
208754
|
+
const resourceHandlers = createResourceProtocolHandlers({ resolveClients, enter, leave });
|
|
207901
208755
|
return {
|
|
207902
208756
|
listTools,
|
|
207903
208757
|
callTool,
|
|
207904
|
-
listResources:
|
|
208758
|
+
listResources: resourceHandlers.listResources,
|
|
207905
208759
|
listResourceTemplates,
|
|
207906
|
-
readResource,
|
|
208760
|
+
readResource: resourceHandlers.readResource,
|
|
207907
208761
|
serverDiscover: () => ({
|
|
207908
208762
|
resultType: "complete",
|
|
207909
208763
|
supportedVersions: ["2026-07-28"],
|
|
@@ -213547,9 +214401,25 @@ var createDefaultMcpSdkServer = () => new Server(
|
|
|
213547
214401
|
);
|
|
213548
214402
|
|
|
213549
214403
|
// src/mcp/create-mcp-server.ts
|
|
213550
|
-
var
|
|
214404
|
+
var currentClientInfoFromServer = (server) => {
|
|
214405
|
+
const maybeServer = server;
|
|
214406
|
+
return parseMcpClientInfo(maybeServer.getClientVersion?.());
|
|
214407
|
+
};
|
|
214408
|
+
var createMcpServer = (resolveClients, telemetry, registry2, getHulyContext, createServer = createDefaultMcpSdkServer, exposureOptions = {}) => {
|
|
213551
214409
|
const server = createServer();
|
|
213552
|
-
const
|
|
214410
|
+
const currentClientInfo = () => exposureOptions.currentClientInfo?.() ?? currentClientInfoFromServer(server);
|
|
214411
|
+
const handlers = createMcpProtocolHandlers(
|
|
214412
|
+
resolveClients,
|
|
214413
|
+
telemetry,
|
|
214414
|
+
registry2,
|
|
214415
|
+
getHulyContext,
|
|
214416
|
+
void 0,
|
|
214417
|
+
void 0,
|
|
214418
|
+
{
|
|
214419
|
+
...exposureOptions,
|
|
214420
|
+
currentClientInfo
|
|
214421
|
+
}
|
|
214422
|
+
);
|
|
213553
214423
|
server.setRequestHandler(ListToolsRequestSchema, handlers.listTools);
|
|
213554
214424
|
server.setRequestHandler(CallToolRequestSchema, handlers.callTool);
|
|
213555
214425
|
server.setRequestHandler(ListResourcesRequestSchema, handlers.listResources);
|
|
@@ -217407,11 +218277,19 @@ var createPostHogTelemetry = (debug, dependencies = defaultDependencies) => {
|
|
|
217407
218277
|
}
|
|
217408
218278
|
});
|
|
217409
218279
|
},
|
|
217410
|
-
firstListTools: () => {
|
|
218280
|
+
firstListTools: (props) => {
|
|
217411
218281
|
if (listToolsSent) return;
|
|
217412
218282
|
listToolsSent = true;
|
|
217413
|
-
debugLog(
|
|
217414
|
-
capture2(
|
|
218283
|
+
debugLog(`[telemetry] first_list_tools: ${JSON.stringify(props ?? {})}`);
|
|
218284
|
+
capture2(
|
|
218285
|
+
props === void 0 ? { event: "first_list_tools" } : {
|
|
218286
|
+
event: "first_list_tools",
|
|
218287
|
+
properties: {
|
|
218288
|
+
client_kind: props.clientKind,
|
|
218289
|
+
resolved_mode: props.resolvedMode
|
|
218290
|
+
}
|
|
218291
|
+
}
|
|
218292
|
+
);
|
|
217415
218293
|
},
|
|
217416
218294
|
toolCalled: (props) => {
|
|
217417
218295
|
debugLog(`[telemetry] tool_called: ${JSON.stringify(props)}`);
|
|
@@ -217421,6 +218299,8 @@ var createPostHogTelemetry = (debug, dependencies = defaultDependencies) => {
|
|
|
217421
218299
|
tool_name: props.toolName,
|
|
217422
218300
|
status: props.status,
|
|
217423
218301
|
duration_ms: props.durationMs,
|
|
218302
|
+
...props.clientKind !== void 0 && { client_kind: props.clientKind },
|
|
218303
|
+
...props.resolvedMode !== void 0 && { resolved_mode: props.resolvedMode },
|
|
217424
218304
|
...props.errorTag !== void 0 && { error_tag: props.errorTag },
|
|
217425
218305
|
...props.inputBytes !== void 0 && { input_bytes: props.inputBytes },
|
|
217426
218306
|
...props.outputBytes !== void 0 && { output_bytes: props.outputBytes },
|
|
@@ -217479,6 +218359,23 @@ var McpServerError = class extends Schema_exports.TaggedError()(
|
|
|
217479
218359
|
var defaultWriteError = (message) => {
|
|
217480
218360
|
console.error(message);
|
|
217481
218361
|
};
|
|
218362
|
+
var parseToolExposureConfigEffect = (env) => {
|
|
218363
|
+
const parsed = parseToolExposureConfig(env);
|
|
218364
|
+
if (parsed._tag === "Success") return Effect_exports.succeed(parsed.value);
|
|
218365
|
+
return Effect_exports.fail(new McpServerError({ message: parsed.message }));
|
|
218366
|
+
};
|
|
218367
|
+
var isRecord7 = (value3) => typeof value3 === "object" && value3 !== null && !Array.isArray(value3);
|
|
218368
|
+
var clientInfoFromMcp2026Request = (req) => {
|
|
218369
|
+
const body = req.body;
|
|
218370
|
+
if (!isRecord7(body) || !isRecord7(body.params) || !isRecord7(body.params._meta)) return void 0;
|
|
218371
|
+
const clientInfo = body.params._meta["io.modelcontextprotocol/clientInfo"];
|
|
218372
|
+
return parseMcpClientInfo(clientInfo);
|
|
218373
|
+
};
|
|
218374
|
+
var clientInfoFromLegacyHttpRequest = (req) => {
|
|
218375
|
+
const body = req.body;
|
|
218376
|
+
if (!isRecord7(body) || !isRecord7(body.params)) return void 0;
|
|
218377
|
+
return parseMcpClientInfo(body.params.clientInfo) ?? clientInfoFromMcp2026Request(req);
|
|
218378
|
+
};
|
|
217482
218379
|
var McpServerService = class _McpServerService extends Context_exports.Tag("@hulymcp/McpServer")() {
|
|
217483
218380
|
static layer(config3) {
|
|
217484
218381
|
return Layer_exports.effect(
|
|
@@ -217487,16 +218384,51 @@ var McpServerService = class _McpServerService extends Context_exports.Tag("@hul
|
|
|
217487
218384
|
const telemetry = yield* TelemetryService;
|
|
217488
218385
|
const writeError2 = config3.writeError ?? defaultWriteError;
|
|
217489
218386
|
const toolsetsRaw = yield* Effect_exports.orElseSucceed(Config_exports.string("TOOLSETS"), () => "");
|
|
217490
|
-
const
|
|
217491
|
-
const
|
|
217492
|
-
|
|
217493
|
-
|
|
218387
|
+
const toolsRaw = yield* Effect_exports.orElseSucceed(Config_exports.string("TOOLS"), () => "");
|
|
218388
|
+
const hulyToolModeRaw = yield* Effect_exports.orElseSucceed(
|
|
218389
|
+
Config_exports.string("HULY_TOOL_MODE"),
|
|
218390
|
+
() => void 0
|
|
218391
|
+
);
|
|
218392
|
+
const proxyOutputStrictRaw = yield* Effect_exports.orElseSucceed(
|
|
218393
|
+
Config_exports.string("PROXY_OUTPUT_STRICT"),
|
|
218394
|
+
() => void 0
|
|
218395
|
+
);
|
|
218396
|
+
const exposureConfig = yield* parseToolExposureConfigEffect({
|
|
218397
|
+
...hulyToolModeRaw === void 0 ? {} : { hulyToolMode: hulyToolModeRaw },
|
|
218398
|
+
...proxyOutputStrictRaw === void 0 ? {} : { proxyOutputStrict: proxyOutputStrictRaw }
|
|
218399
|
+
});
|
|
218400
|
+
const toolScope = resolveToolScope(
|
|
218401
|
+
{
|
|
218402
|
+
toolsets: toolsetsRaw,
|
|
218403
|
+
tools: toolsRaw
|
|
218404
|
+
},
|
|
218405
|
+
toolRegistry.definitions,
|
|
218406
|
+
writeError2
|
|
218407
|
+
);
|
|
218408
|
+
const toolsets = toolScope.filteringActive ? toolScope.enabledToolsets : null;
|
|
218409
|
+
const scopedNativeRegistry = createScopedRegistry({
|
|
218410
|
+
filteringActive: toolScope.filteringActive,
|
|
218411
|
+
categories: toolScope.enabledCategories,
|
|
218412
|
+
toolNames: toolScope.enabledToolNames
|
|
218413
|
+
});
|
|
218414
|
+
const registries = {
|
|
218415
|
+
fullRegistry: toolRegistry,
|
|
218416
|
+
scopedNativeRegistry
|
|
218417
|
+
};
|
|
217494
218418
|
const getRuntimeConfigContext = config3.getRuntimeConfigContext ?? (() => sanitizeHulyRuntimeConfigFromEnv(process.env));
|
|
217495
|
-
const getHulyContext = (runtimeConfig) => buildHulyContext(config3,
|
|
218419
|
+
const getHulyContext = (runtimeConfig, toolExposure) => buildHulyContext(config3, scopedNativeRegistry, toolScope, runtimeConfig, toolExposure);
|
|
218420
|
+
const sdkExposureOptions = {
|
|
218421
|
+
exposureConfig,
|
|
218422
|
+
toolScopeFilteringActive: toolScope.filteringActive
|
|
218423
|
+
};
|
|
218424
|
+
const requestExposureOptions = (currentClientInfo) => ({
|
|
218425
|
+
...sdkExposureOptions,
|
|
218426
|
+
currentClientInfo
|
|
218427
|
+
});
|
|
217496
218428
|
telemetry.sessionStart({
|
|
217497
218429
|
transport: config3.transport,
|
|
217498
218430
|
authMethod: config3.authMethod ?? "password",
|
|
217499
|
-
toolCount:
|
|
218431
|
+
toolCount: scopedNativeRegistry.definitions.length,
|
|
217500
218432
|
toolsets
|
|
217501
218433
|
});
|
|
217502
218434
|
const flushTelemetry = Effect_exports.ignore(
|
|
@@ -217516,9 +218448,10 @@ var McpServerService = class _McpServerService extends Context_exports.Tag("@hul
|
|
|
217516
218448
|
const [stdioServer, drainInflight] = createMcpServer(
|
|
217517
218449
|
config3.resolveClients,
|
|
217518
218450
|
telemetry,
|
|
217519
|
-
|
|
217520
|
-
() => getHulyContext(getRuntimeConfigContext()),
|
|
217521
|
-
config3.createServer
|
|
218451
|
+
registries,
|
|
218452
|
+
(toolExposure) => getHulyContext(getRuntimeConfigContext(), toolExposure),
|
|
218453
|
+
config3.createServer,
|
|
218454
|
+
sdkExposureOptions
|
|
217522
218455
|
);
|
|
217523
218456
|
yield* Ref_exports.set(serverRef, stdioServer);
|
|
217524
218457
|
const transport = config3.createStdioTransport?.() ?? new StdioServerTransport();
|
|
@@ -217575,9 +218508,10 @@ var McpServerService = class _McpServerService extends Context_exports.Tag("@hul
|
|
|
217575
218508
|
return createMcpServer(
|
|
217576
218509
|
requestResolveClients,
|
|
217577
218510
|
telemetry,
|
|
217578
|
-
|
|
217579
|
-
() => getHulyContext(requestRuntimeConfig),
|
|
217580
|
-
config3.createServer
|
|
218511
|
+
registries,
|
|
218512
|
+
(toolExposure) => getHulyContext(requestRuntimeConfig, toolExposure),
|
|
218513
|
+
config3.createServer,
|
|
218514
|
+
requestExposureOptions(() => clientInfoFromLegacyHttpRequest(req))
|
|
217581
218515
|
)[0];
|
|
217582
218516
|
},
|
|
217583
218517
|
config3.httpTransportDependencies,
|
|
@@ -217586,8 +218520,11 @@ var McpServerService = class _McpServerService extends Context_exports.Tag("@hul
|
|
|
217586
218520
|
return createMcpProtocolHandlers(
|
|
217587
218521
|
requestResolveClients,
|
|
217588
218522
|
telemetry,
|
|
217589
|
-
|
|
217590
|
-
() => getHulyContext(requestRuntimeConfig)
|
|
218523
|
+
registries,
|
|
218524
|
+
(toolExposure) => getHulyContext(requestRuntimeConfig, toolExposure),
|
|
218525
|
+
void 0,
|
|
218526
|
+
void 0,
|
|
218527
|
+
requestExposureOptions(() => clientInfoFromMcp2026Request(req))
|
|
217591
218528
|
);
|
|
217592
218529
|
}
|
|
217593
218530
|
).pipe(
|