diff --git a/backend/generate_mcp_endpoints_tools/generate_mcp_tools.py b/backend/generate_mcp_endpoints_tools/generate_mcp_tools.py index 7bcf125b8e..b120a00d39 100644 --- a/backend/generate_mcp_endpoints_tools/generate_mcp_tools.py +++ b/backend/generate_mcp_endpoints_tools/generate_mcp_tools.py @@ -384,6 +384,19 @@ def schema_to_rust_value(schema: Optional[Dict[str, Any]]) -> str: return "None" return f"Some(serde_json::json!({json.dumps(schema, indent=8)}))" +def build_tool_description(operation: Dict[str, Any], method: str, path: str) -> str: + """Build the MCP tool description from OpenAPI summary and description.""" + summary = operation.get('summary', '').strip() + description = operation.get('description', '').strip() + + if summary and description: + return f"{summary}: {description}".rstrip('.!? ') + if summary: + return summary + if description: + return description.rstrip('.!? ') + return f'{method.upper()} {path}' + def find_mcp_tools(spec: Dict[str, Any]) -> List[Dict[str, Any]]: """Find all endpoints marked with x-mcp-tool: true.""" tools = [] @@ -395,7 +408,7 @@ def find_mcp_tools(spec: Dict[str, Any]) -> List[Dict[str, Any]]: # Extract tool information tool = { 'name': operation.get('operationId', f"{method}_{path.replace('/', '_').replace('{', '').replace('}', '')}"), - 'description': operation.get('summary', operation.get('description', f'{method.upper()} {path}')), + 'description': build_tool_description(operation, method, path), 'instructions': operation.get('x-mcp-instructions', ''), 'path': path, 'method': method.upper(), @@ -607,4 +620,4 @@ def main(): print("Done!") if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 2f8567a9f6..17127ef3d6 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -7406,6 +7406,9 @@ paths: /w/{workspace}/scripts/create: post: summary: create script + description: | + Creates a new script when the path does not already exist. + Creates a new version of an existing script when called with the same path and the current `parent_hash`. operationId: createScript x-mcp-tool: true x-mcp-instructions: "To create a script, specify the path (e.g., 'f/my_folder/my_script'), the content (source code), and the language. For TypeScript, use 'bun' unless deno-specific APIs are needed." diff --git a/backend/windmill-api/src/mcp/auto_generated_endpoints.rs b/backend/windmill-api/src/mcp/auto_generated_endpoints.rs index c9295ea8e9..fc3b1164f5 100644 --- a/backend/windmill-api/src/mcp/auto_generated_endpoints.rs +++ b/backend/windmill-api/src/mcp/auto_generated_endpoints.rs @@ -78,6 +78,12 @@ pub fn all_tools() -> Vec { "type": "string", "description": "The expiration date of the variable", "format": "date-time" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -157,6 +163,12 @@ pub fn all_tools() -> Vec { "type": "string", "description": "The new description of the variable" }, + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, "path__body": { "type": "string", "description": "The path to the variable (body parameter)" @@ -244,6 +256,10 @@ pub fn all_tools() -> Vec { "per_page": { "type": "integer", "description": "number of items to return for a given page (default 30, max 100)" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] @@ -287,6 +303,12 @@ pub fn all_tools() -> Vec { "resource_type": { "type": "string", "description": "The resource_type associated with the resource" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -355,6 +377,12 @@ pub fn all_tools() -> Vec { "type": "string", "description": "The new resource_type to be associated with the resource" }, + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, "path__body": { "type": "string", "description": "The path to the resource (body parameter)" @@ -437,6 +465,10 @@ pub fn all_tools() -> Vec { "broad_filter": { "type": "string", "description": "broad search across multiple fields (case-insensitive substring match)" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] @@ -544,6 +576,10 @@ pub fn all_tools() -> Vec { "dedicated_worker": { "type": "boolean", "description": "(default regardless)\nIf true, show only scripts with dedicated_worker enabled.\nIf false, show only scripts with dedicated_worker disabled.\n" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] @@ -555,7 +591,8 @@ pub fn all_tools() -> Vec { }, EndpointTool { name: Cow::Borrowed("createScript"), - description: Cow::Borrowed("create script"), + description: Cow::Borrowed("create script: Creates a new script when the path does not already exist. +Creates a new version of an existing script when called with the same path and the current `parent_hash`"), instructions: Cow::Borrowed("To create a script, specify the path (e.g., 'f/my_folder/my_script'), the content (source code), and the language. For TypeScript, use 'bun' unless deno-specific APIs are needed."), path: Cow::Borrowed("/w/{workspace}/scripts/create"), method: Cow::Borrowed("POST"), @@ -578,7 +615,7 @@ pub fn all_tools() -> Vec { }, "language": { "type": "string", - "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, duckdb, bunnative" + "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, rlang, duckdb, bunnative" }, "kind": { "type": "string", @@ -772,6 +809,10 @@ pub fn all_tools() -> Vec { "dedicated_worker": { "type": "boolean", "description": "(default regardless)\nIf true, show only flows with dedicated_worker enabled.\nIf false, show only flows with dedicated_worker disabled.\n" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] @@ -1095,7 +1136,7 @@ pub fn all_tools() -> Vec { }, "language": { "type": "string", - "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, duckdb, bunnative" + "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, rlang, duckdb, bunnative" }, "tag": { "type": "string" @@ -1127,7 +1168,7 @@ pub fn all_tools() -> Vec { }, "language": { "type": "string", - "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, duckdb, bunnative" + "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, rlang, duckdb, bunnative" }, "lock": { "type": "string", @@ -1691,6 +1732,12 @@ You should get the schema of the script or flow before creating the schedule to "preserve_permissioned_as": { "type": "boolean", "description": "When true and the caller is a member of the 'wm_deployers' group, preserves the original permissioned_as value instead of overwriting it." + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -1894,6 +1941,12 @@ You should get the schema of the script or flow before updating the schedule to "type": "boolean", "nullable": true, "description": "If true and user is admin/wm_deployers, preserve the provided permissioned_as instead of using the deploying user's identity" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -2001,6 +2054,10 @@ You should get the schema of the script or flow before updating the schedule to "broad_filter": { "type": "string", "description": "broad search across multiple fields (case-insensitive substring match)" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] diff --git a/frontend/src/lib/mcpEndpointTools.ts b/frontend/src/lib/mcpEndpointTools.ts index e60103a65a..b86119477e 100644 --- a/frontend/src/lib/mcpEndpointTools.ts +++ b/frontend/src/lib/mcpEndpointTools.ts @@ -88,6 +88,12 @@ export const mcpEndpointTools: EndpointTool[] = [ "type": "string", "description": "The expiration date of the variable", "format": "date-time" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -167,6 +173,12 @@ export const mcpEndpointTools: EndpointTool[] = [ "type": "string", "description": "The new description of the variable" }, + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, "path__body": { "type": "string", "description": "The path to the variable (body parameter)" @@ -254,6 +266,10 @@ export const mcpEndpointTools: EndpointTool[] = [ "per_page": { "type": "integer", "description": "number of items to return for a given page (default 30, max 100)" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] @@ -297,6 +313,12 @@ export const mcpEndpointTools: EndpointTool[] = [ "resource_type": { "type": "string", "description": "The resource_type associated with the resource" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -365,6 +387,12 @@ export const mcpEndpointTools: EndpointTool[] = [ "type": "string", "description": "The new resource_type to be associated with the resource" }, + "labels": { + "type": "array", + "items": { + "type": "string" + } + }, "path__body": { "type": "string", "description": "The path to the resource (body parameter)" @@ -447,6 +475,10 @@ export const mcpEndpointTools: EndpointTool[] = [ "broad_filter": { "type": "string", "description": "broad search across multiple fields (case-insensitive substring match)" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] @@ -554,6 +586,10 @@ export const mcpEndpointTools: EndpointTool[] = [ "dedicated_worker": { "type": "boolean", "description": "(default regardless)\nIf true, show only scripts with dedicated_worker enabled.\nIf false, show only scripts with dedicated_worker disabled.\n" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] @@ -565,7 +601,7 @@ export const mcpEndpointTools: EndpointTool[] = [ }, { name: "createScript", - description: "create script", + description: "create script: Creates a new script when the path does not already exist.\nCreates a new version of an existing script when called with the same path and the current `parent_hash`", instructions: "To create a script, specify the path (e.g., 'f/my_folder/my_script'), the content (source code), and the language. For TypeScript, use 'bun' unless deno-specific APIs are needed.", path: "/w/{workspace}/scripts/create", method: "POST", @@ -588,7 +624,7 @@ export const mcpEndpointTools: EndpointTool[] = [ }, "language": { "type": "string", - "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, duckdb, bunnative" + "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, rlang, duckdb, bunnative" }, "kind": { "type": "string", @@ -782,6 +818,10 @@ export const mcpEndpointTools: EndpointTool[] = [ "dedicated_worker": { "type": "boolean", "description": "(default regardless)\nIf true, show only flows with dedicated_worker enabled.\nIf false, show only flows with dedicated_worker disabled.\n" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": [] @@ -1105,7 +1145,7 @@ export const mcpEndpointTools: EndpointTool[] = [ }, "language": { "type": "string", - "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, duckdb, bunnative" + "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, rlang, duckdb, bunnative" }, "tag": { "type": "string" @@ -1137,7 +1177,7 @@ export const mcpEndpointTools: EndpointTool[] = [ }, "language": { "type": "string", - "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, duckdb, bunnative" + "description": "Possible values: python3, deno, go, bash, powershell, postgresql, mysql, bigquery, snowflake, mssql, oracledb, graphql, nativets, bun, php, rust, ansible, csharp, nu, java, ruby, rlang, duckdb, bunnative" }, "lock": { "type": "string", @@ -1698,6 +1738,12 @@ export const mcpEndpointTools: EndpointTool[] = [ "preserve_permissioned_as": { "type": "boolean", "description": "When true and the caller is a member of the 'wm_deployers' group, preserves the original permissioned_as value instead of overwriting it." + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -1898,6 +1944,12 @@ export const mcpEndpointTools: EndpointTool[] = [ "type": "boolean", "nullable": true, "description": "If true and user is admin/wm_deployers, preserve the provided permissioned_as instead of using the deploying user's identity" + }, + "labels": { + "type": "array", + "items": { + "type": "string" + } } }, "required": [ @@ -2005,6 +2057,10 @@ export const mcpEndpointTools: EndpointTool[] = [ "broad_filter": { "type": "string", "description": "broad search across multiple fields (case-insensitive substring match)" + }, + "label": { + "type": "string", + "description": "Filter by label" } }, "required": []