Skip to content

Commit 0d045de

Browse files
MCP ToolTrigger Fulent Property and IsArray support (#377)
* MCP ToolTrigger Fulent Property and IsArray support * Improvement in the Error mesage * Code review comments * Code review comments * Making Stricter
1 parent 8826b61 commit 0d045de

File tree

11 files changed

+1162
-350
lines changed

11 files changed

+1162
-350
lines changed

package-lock.json

Lines changed: 318 additions & 227 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/converters/toMcpToolTriggerOptionsToRpc.ts

Lines changed: 21 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
import { McpToolProperty, McpToolTriggerOptions, McpToolTriggerOptionsToRpc } from '../../types';
5+
import { normalizeToolProperties } from '../utils/toolProperties';
56

67
// Copyright (c) .NET Foundation. All rights reserved.
78
// Licensed under the MIT License.
@@ -21,129 +22,33 @@ export function converToMcpToolTriggerOptionsToRpc(
2122
description: mcpToolTriggerOptions.description,
2223
};
2324

24-
// Check for null or undefined toolProperties
25-
if (!mcpToolTriggerOptions?.toolProperties) {
26-
return {
27-
...baseResult,
28-
toolProperties: JSON.stringify([]), // Default to an empty array
29-
};
30-
}
31-
32-
// Check if toolProperties is an array of McpToolProperty objects
33-
if (Array.isArray(mcpToolTriggerOptions.toolProperties)) {
34-
const isValid = mcpToolTriggerOptions.toolProperties.every(isMcpToolProperty);
35-
if (isValid) {
36-
return {
37-
...baseResult,
38-
toolProperties: JSON.stringify(mcpToolTriggerOptions.toolProperties),
39-
};
40-
} else {
41-
throw new Error(
42-
'Invalid toolProperties: Array contains invalid McpToolProperty, please validate the parameters.'
43-
);
25+
// Try to normalize tool properties first (handles both array and fluent formats)
26+
let normalizedProperties: McpToolProperty[] | undefined;
27+
try {
28+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
29+
normalizedProperties = normalizeToolProperties(mcpToolTriggerOptions.toolProperties);
30+
} catch (error) {
31+
// Re-throw validation errors from normalizeToolProperties
32+
if (
33+
error instanceof Error &&
34+
(error.message.includes('Property type is required') ||
35+
error.message.includes('Property type must be specified'))
36+
) {
37+
throw error;
4438
}
39+
normalizedProperties = undefined;
4540
}
4641

47-
// Handle cases where toolProperties is an object (e.g., Zod schema)
48-
if (typeof mcpToolTriggerOptions.toolProperties === 'object') {
49-
// Define the type of the ZodObject shape and ZodPropertyDef
50-
type ZodPropertyDef = {
51-
description?: string;
52-
typeName: string;
53-
};
54-
type ZodObjectShape = Record<string, { _def: ZodPropertyDef }>;
55-
56-
// Define the type of the toolProperties object
57-
type ToolProperties =
58-
| {
59-
_def?: {
60-
typeName?: string;
61-
};
62-
shape?: ZodObjectShape;
63-
}
64-
| Record<string, unknown>;
65-
66-
let isZodObject = false;
67-
68-
const toolProperties = mcpToolTriggerOptions.toolProperties as ToolProperties;
69-
70-
// Check if the object is a ZodObject
71-
if ((toolProperties?._def as { typeName?: string })?.typeName === 'ZodObject') {
72-
isZodObject = true;
73-
}
74-
75-
// Check if shape is a valid ZodObject shape
76-
const shape: ZodObjectShape | Record<string, unknown> = isZodObject
77-
? (toolProperties as { shape: ZodObjectShape }).shape
78-
: toolProperties;
79-
80-
// Extract properties from the ZodObject shape
81-
const result = Object.keys(shape).map((propertyName) => {
82-
const property = shape[propertyName] as { _def: ZodPropertyDef };
83-
const description = property?._def?.description || '';
84-
const propertyType = getPropertyType(property?._def?.typeName?.toLowerCase() || 'unknown'); // Extract type name or default to "unknown"
85-
86-
return {
87-
propertyName,
88-
propertyType,
89-
description,
90-
};
91-
});
92-
42+
// If we successfully normalized the properties, use them
43+
if (normalizedProperties !== undefined) {
9344
return {
9445
...baseResult,
95-
toolProperties: JSON.stringify(result),
46+
toolProperties: JSON.stringify(normalizedProperties),
9647
};
9748
}
98-
// Handle cases where toolProperties is not an array
99-
throw new Error('Invalid toolProperties: Expected an array of McpToolProperty objects or zod objects.');
100-
}
101-
102-
// Helper function to infer property type from zod schema
103-
function getPropertyType(zodType: string): string {
104-
switch (zodType) {
105-
case 'zodnumber':
106-
return 'number';
107-
case 'zodstring':
108-
return 'string';
109-
case 'zodboolean':
110-
return 'boolean';
111-
case 'zodarray':
112-
return 'array';
113-
case 'zodobject':
114-
return 'object';
115-
case 'zodbigint':
116-
return 'long';
117-
case 'zoddate':
118-
return 'DateTime';
119-
case 'zodtuple':
120-
return 'Tuple';
121-
default:
122-
console.warn(`Unknown zod type: ${zodType}`);
123-
return 'unknown';
124-
}
125-
}
12649

127-
/**
128-
* Type guard to check if a given object is of type McpToolProperty.
129-
*
130-
* @param property - The object to check.
131-
* @returns True if the object is of type McpToolProperty, otherwise false.
132-
*
133-
* This function ensures that the object:
134-
* - Is not null and is of type 'object'.
135-
* - Contains the required properties: 'propertyName', 'propertyValue', and 'description'.
136-
* - Each of these properties is of the correct type (string).
137-
*/
138-
function isMcpToolProperty(property: unknown): property is McpToolProperty {
139-
return (
140-
typeof property === 'object' &&
141-
property !== null &&
142-
'propertyName' in property &&
143-
'propertyType' in property &&
144-
'description' in property &&
145-
typeof (property as McpToolProperty).propertyName === 'string' &&
146-
typeof (property as McpToolProperty).propertyType === 'string' &&
147-
typeof (property as McpToolProperty).description === 'string'
50+
// Handle cases where toolProperties is not an array
51+
throw new Error(
52+
`Invalid toolProperties for tool '${mcpToolTriggerOptions.toolName}': Expected an array of McpToolProperty or ToolProps objects or ToolProps need a type defined.`
14853
);
14954
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export { InvocationContext } from './InvocationContext';
1616
export * as output from './output';
1717
export * as trigger from './trigger';
1818
export { Disposable } from './utils/Disposable';
19+
export { arg } from './utils/toolProperties';
1920

2021
export enum SqlChangeOperation {
2122
Insert = 0,

0 commit comments

Comments
 (0)