mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 08:01:26 +00:00
fix(flows): make updateFlow body path optional so AI can update flows (#10176)
* fix(mcp): default a body field to its same-named path param so updateFlow works Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs: trim mcp path-param fallback helper comment Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(mcp): keep path params un-mangled so update tools take plain `path` Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(flows): default update_flow body path from URL via EditFlow Harmonizes updateFlow with the EditVariable/EditResource/EditApp convention: the flow to update is identified by the URL, so the body path is optional and only needed to rename. Fixes the 422 at the API layer for every client (MCP, the in-app AI chat, raw HTTP), not just the MCP tool schema. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * refactor(mcp): drop redundant body-path fallback now that the server defaults it Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs: fix stale generator comment after removing mcp body-path fallback Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(flows): mark updateFlow body path optional in the openapi contract Adds an `EditFlow` schema (path optional) for the update route so the public contract matches the server; createFlow keeps `OpenFlowWPath` (path required). Also trims two test comments to record constraints rather than history. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -165,13 +165,14 @@ def extract_separate_schemas(parameters: List[Dict[str, Any]], request_body: Opt
|
||||
|
||||
conflicts = (path_keys & query_keys) | (path_keys & body_keys) | (query_keys & body_keys)
|
||||
|
||||
path_field_renames = {}
|
||||
query_field_renames = {}
|
||||
body_field_renames = {}
|
||||
|
||||
for field in conflicts:
|
||||
# The path parameter keeps the plain name: it identifies the item, is what a
|
||||
# caller reaches for first, and matches the non-colliding endpoints (`getFlowByPath`
|
||||
# takes `path`). Only the other locations carry a suffix.
|
||||
schemas_and_renames = [
|
||||
(path_params_schema, path_keys, '__path', path_field_renames),
|
||||
(query_params_schema, query_keys, '__query', query_field_renames),
|
||||
(body_schema, body_keys, '__body', body_field_renames),
|
||||
]
|
||||
@@ -197,11 +198,26 @@ def extract_separate_schemas(parameters: List[Dict[str, Any]], request_body: Opt
|
||||
# Store the reverse mapping: renamed -> original
|
||||
renames_map[new_name] = field
|
||||
|
||||
# A body field colliding with a same-named path parameter (`path` on the update
|
||||
# endpoints) holds the new value and differs only when moving the item, so it must
|
||||
# stay optional; the server defaults it from the URL path when the caller omits it.
|
||||
if field in path_keys and field in body_keys and body_schema:
|
||||
body_name = field + '__body'
|
||||
if 'required' in body_schema:
|
||||
body_schema['required'] = [r for r in body_schema['required'] if r != body_name]
|
||||
prop = body_schema['properties'].get(body_name)
|
||||
if isinstance(prop, dict):
|
||||
existing_desc = prop.get('description', '').rstrip('. ')
|
||||
prop['description'] = (
|
||||
f"{existing_desc}. Defaults to `{field}` when omitted; "
|
||||
f"set it only to change the {field}."
|
||||
).lstrip('. ')
|
||||
|
||||
# Return None for empty schemas
|
||||
path_params_schema = path_params_schema if path_params_schema and path_params_schema.get('properties') else None
|
||||
query_params_schema = query_params_schema if query_params_schema and query_params_schema.get('properties') else None
|
||||
|
||||
return (path_params_schema, query_params_schema, body_schema, path_field_renames, query_field_renames, body_field_renames)
|
||||
return (path_params_schema, query_params_schema, body_schema, query_field_renames, body_field_renames)
|
||||
|
||||
# Cache for loaded external files
|
||||
_external_file_cache: Dict[str, Dict[str, Any]] = {}
|
||||
@@ -453,7 +469,7 @@ export const mcpEndpointTools: EndpointTool[] = [];
|
||||
method = tool['method'].upper()
|
||||
|
||||
# Generate separate schemas
|
||||
path_params_schema, query_params_schema, body_schema, path_field_renames, query_field_renames, body_field_renames = extract_separate_schemas(
|
||||
path_params_schema, query_params_schema, body_schema, query_field_renames, body_field_renames = extract_separate_schemas(
|
||||
tool['parameters'], tool['requestBody'], spec, tool['required_fields'], base_path,
|
||||
tool.get('include_fields'), tool.get('opaque_fields'), tool.get('include_query_params')
|
||||
)
|
||||
@@ -462,7 +478,6 @@ export const mcpEndpointTools: EndpointTool[] = [];
|
||||
path_params_ts = json.dumps(path_params_schema, indent=8) if path_params_schema else "undefined"
|
||||
query_params_ts = json.dumps(query_params_schema, indent=8) if query_params_schema else "undefined"
|
||||
body_schema_ts = json.dumps(body_schema, indent=8) if body_schema else "undefined"
|
||||
path_field_renames_ts = json.dumps(path_field_renames, indent=8) if path_field_renames else "undefined"
|
||||
query_field_renames_ts = json.dumps(query_field_renames, indent=8) if query_field_renames else "undefined"
|
||||
body_field_renames_ts = json.dumps(body_field_renames, indent=8) if body_field_renames else "undefined"
|
||||
|
||||
@@ -476,7 +491,6 @@ export const mcpEndpointTools: EndpointTool[] = [];
|
||||
pathParamsSchema: {path_params_ts},
|
||||
queryParamsSchema: {query_params_ts},
|
||||
bodySchema: {body_schema_ts},
|
||||
pathFieldRenames: {path_field_renames_ts},
|
||||
queryFieldRenames: {query_field_renames_ts},
|
||||
bodyFieldRenames: {body_field_renames_ts}
|
||||
}}"""
|
||||
@@ -497,7 +511,6 @@ export interface EndpointTool {{
|
||||
pathParamsSchema?: object;
|
||||
queryParamsSchema?: object;
|
||||
bodySchema?: object;
|
||||
pathFieldRenames?: Record<string, string>;
|
||||
queryFieldRenames?: Record<string, string>;
|
||||
bodyFieldRenames?: Record<string, string>;
|
||||
}}
|
||||
@@ -529,7 +542,7 @@ pub fn all_tools() -> Vec<EndpointTool> {{
|
||||
method = tool['method'].upper()
|
||||
|
||||
# Generate separate schemas
|
||||
path_params_schema, query_params_schema, body_schema, path_field_renames, query_field_renames, body_field_renames = extract_separate_schemas(
|
||||
path_params_schema, query_params_schema, body_schema, query_field_renames, body_field_renames = extract_separate_schemas(
|
||||
tool['parameters'], tool['requestBody'], spec, tool['required_fields'], base_path,
|
||||
tool.get('include_fields'), tool.get('opaque_fields'), tool.get('include_query_params')
|
||||
)
|
||||
@@ -537,7 +550,6 @@ pub fn all_tools() -> Vec<EndpointTool> {{
|
||||
path_params_rust = schema_to_rust_value(path_params_schema)
|
||||
query_params_rust = schema_to_rust_value(query_params_schema)
|
||||
body_schema_rust = schema_to_rust_value(body_schema)
|
||||
path_field_renames_rust = schema_to_rust_value(path_field_renames if path_field_renames else None)
|
||||
query_field_renames_rust = schema_to_rust_value(query_field_renames if query_field_renames else None)
|
||||
body_field_renames_rust = schema_to_rust_value(body_field_renames if body_field_renames else None)
|
||||
|
||||
@@ -551,7 +563,6 @@ pub fn all_tools() -> Vec<EndpointTool> {{
|
||||
path_params_schema: {path_params_rust},
|
||||
query_params_schema: {query_params_rust},
|
||||
body_schema: {body_schema_rust},
|
||||
path_field_renames: {path_field_renames_rust},
|
||||
query_field_renames: {query_field_renames_rust},
|
||||
body_field_renames: {body_field_renames_rust},
|
||||
}}"""
|
||||
|
||||
@@ -47,7 +47,7 @@ use windmill_common::HUB_BASE_URL;
|
||||
use windmill_common::{
|
||||
db::UserDB,
|
||||
error::{self, to_anyhow, Error, JsonResult, Result},
|
||||
flows::{Flow, FlowWithStarred, ListFlowQuery, ListableFlow, NewFlow},
|
||||
flows::{EditFlow, Flow, FlowWithStarred, ListFlowQuery, ListableFlow, NewFlow},
|
||||
jobs::JobPayload,
|
||||
schedule::Schedule,
|
||||
utils::{http_get_from_hub, not_found_if_none, paginate, Pagination, RunnableKind, StripPath},
|
||||
@@ -1007,7 +1007,7 @@ async fn update_flow(
|
||||
Extension(db): Extension<DB>,
|
||||
Extension(webhook): Extension<WebhookShared>,
|
||||
Path((w_id, flow_path)): Path<(String, StripPath)>,
|
||||
Json(nf): Json<NewFlow>,
|
||||
Json(ef): Json<EditFlow>,
|
||||
) -> Result<String> {
|
||||
if authed.is_operator {
|
||||
return Err(Error::NotAuthorized(
|
||||
@@ -1015,6 +1015,8 @@ async fn update_flow(
|
||||
));
|
||||
}
|
||||
let flow_path = flow_path.to_path();
|
||||
// The URL identifies the flow being updated; the body path is only needed to rename.
|
||||
let nf = ef.into_new_flow(flow_path);
|
||||
check_scopes(&authed, || format!("flows:write:{}", flow_path))?;
|
||||
|
||||
if let RuleCheckResult::Blocked(msg) = check_deploy_rules(
|
||||
|
||||
@@ -10775,7 +10775,7 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: "#/components/schemas/OpenFlowWPath"
|
||||
- $ref: "#/components/schemas/EditFlow"
|
||||
- type: object
|
||||
properties:
|
||||
deployment_message:
|
||||
@@ -29097,6 +29097,37 @@ components:
|
||||
type: string
|
||||
required:
|
||||
- path
|
||||
# Like OpenFlowWPath but `path` is optional: on update the flow is identified by
|
||||
# the URL, so the body path is only needed to rename it. Kept as a separate schema
|
||||
# (rather than making OpenFlowWPath.path optional) so createFlow still requires path.
|
||||
EditFlow:
|
||||
allOf:
|
||||
- $ref: "../../openflow.openapi.yaml#/components/schemas/OpenFlow"
|
||||
- type: object
|
||||
properties:
|
||||
path:
|
||||
type: string
|
||||
tag:
|
||||
type: string
|
||||
ws_error_handler_muted:
|
||||
type: boolean
|
||||
priority:
|
||||
type: integer
|
||||
dedicated_worker:
|
||||
type: boolean
|
||||
timeout:
|
||||
type: number
|
||||
visible_to_runner_only:
|
||||
type: boolean
|
||||
on_behalf_of_email:
|
||||
type: string
|
||||
preserve_on_behalf_of:
|
||||
type: boolean
|
||||
description: "When true and the caller is a member of the 'wm_deployers' group, preserves the original on_behalf_of_email value instead of overwriting it."
|
||||
labels:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
|
||||
FlowPreview:
|
||||
type: object
|
||||
|
||||
@@ -26,7 +26,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
]
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -54,7 +53,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
]
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -124,7 +122,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
"description"
|
||||
]
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -147,7 +144,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
})),
|
||||
query_params_schema: None,
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -160,13 +156,12 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
path_params_schema: Some(serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path__path": {
|
||||
"type": "string",
|
||||
"description": "(path parameter)"
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path__path"
|
||||
"path"
|
||||
]
|
||||
})),
|
||||
query_params_schema: Some(serde_json::json!({
|
||||
@@ -205,12 +200,9 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
},
|
||||
"path__body": {
|
||||
"type": "string",
|
||||
"description": "The path to the variable (body parameter)"
|
||||
"description": "The path to the variable (body parameter). Defaults to `path` when omitted; set it only to change the path."
|
||||
}
|
||||
}
|
||||
})),
|
||||
path_field_renames: Some(serde_json::json!({
|
||||
"path__path": "path"
|
||||
})),
|
||||
query_field_renames: None,
|
||||
body_field_renames: Some(serde_json::json!({
|
||||
@@ -253,7 +245,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -307,7 +298,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -362,7 +352,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
"resource_type"
|
||||
]
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -385,7 +374,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
})),
|
||||
query_params_schema: None,
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -398,13 +386,12 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
path_params_schema: Some(serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path__path": {
|
||||
"type": "string",
|
||||
"description": "(path parameter)"
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path__path"
|
||||
"path"
|
||||
]
|
||||
})),
|
||||
query_params_schema: None,
|
||||
@@ -433,12 +420,9 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
},
|
||||
"path__body": {
|
||||
"type": "string",
|
||||
"description": "The path to the resource (body parameter)"
|
||||
"description": "The path to the resource (body parameter). Defaults to `path` when omitted; set it only to change the path."
|
||||
}
|
||||
}
|
||||
})),
|
||||
path_field_renames: Some(serde_json::json!({
|
||||
"path__path": "path"
|
||||
})),
|
||||
query_field_renames: None,
|
||||
body_field_renames: Some(serde_json::json!({
|
||||
@@ -473,7 +457,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -535,7 +518,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -548,7 +530,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
path_params_schema: None,
|
||||
query_params_schema: None,
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -646,7 +627,6 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -699,7 +679,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"language"
|
||||
]
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -722,7 +701,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
})),
|
||||
query_params_schema: None,
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -754,7 +732,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -789,7 +766,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -816,7 +792,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"description": "The arguments to pass to the script or flow",
|
||||
"additionalProperties": true
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -886,7 +861,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -921,7 +895,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -967,7 +940,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
],
|
||||
"description": "Top-level flow definition containing metadata, configuration, and the flow structure"
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -980,13 +952,12 @@ Creates a new version of an existing script when called with the same path and t
|
||||
path_params_schema: Some(serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path__path": {
|
||||
"type": "string",
|
||||
"description": "(path parameter)"
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path__path"
|
||||
"path"
|
||||
]
|
||||
})),
|
||||
query_params_schema: None,
|
||||
@@ -1015,18 +986,14 @@ Creates a new version of an existing script when called with the same path and t
|
||||
},
|
||||
"path__body": {
|
||||
"type": "string",
|
||||
"description": "(body parameter)"
|
||||
"description": "(body parameter). Defaults to `path` when omitted; set it only to change the path."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"summary",
|
||||
"value",
|
||||
"path__body"
|
||||
"value"
|
||||
],
|
||||
"description": "Top-level flow definition containing metadata, configuration, and the flow structure"
|
||||
})),
|
||||
path_field_renames: Some(serde_json::json!({
|
||||
"path__path": "path"
|
||||
})),
|
||||
query_field_renames: None,
|
||||
body_field_renames: Some(serde_json::json!({
|
||||
@@ -1061,7 +1028,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -1099,7 +1065,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"policy"
|
||||
]
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -1112,13 +1077,12 @@ Creates a new version of an existing script when called with the same path and t
|
||||
path_params_schema: Some(serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path__path": {
|
||||
"type": "string",
|
||||
"description": "(path parameter)"
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path__path"
|
||||
"path"
|
||||
]
|
||||
})),
|
||||
query_params_schema: None,
|
||||
@@ -1139,12 +1103,9 @@ Creates a new version of an existing script when called with the same path and t
|
||||
},
|
||||
"path__body": {
|
||||
"type": "string",
|
||||
"description": "(body parameter)"
|
||||
"description": "(body parameter). Defaults to `path` when omitted; set it only to change the path."
|
||||
}
|
||||
}
|
||||
})),
|
||||
path_field_renames: Some(serde_json::json!({
|
||||
"path__path": "path"
|
||||
})),
|
||||
query_field_renames: None,
|
||||
body_field_renames: Some(serde_json::json!({
|
||||
@@ -1174,7 +1135,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"description": "The arguments to pass to the script or flow",
|
||||
"additionalProperties": true
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -1269,7 +1229,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"language"
|
||||
]
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -1390,7 +1349,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -1557,7 +1515,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -1596,7 +1553,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -1628,7 +1584,6 @@ Creates a new version of an existing script when called with the same path and t
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -1841,7 +1796,6 @@ You should get the schema of the script or flow before creating the schedule to
|
||||
"args"
|
||||
]
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -2047,7 +2001,6 @@ You should get the schema of the script or flow before updating the schedule to
|
||||
"args"
|
||||
]
|
||||
})),
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -2070,7 +2023,6 @@ You should get the schema of the script or flow before updating the schedule to
|
||||
})),
|
||||
query_params_schema: None,
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -2102,7 +2054,6 @@ You should get the schema of the script or flow before updating the schedule to
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -2168,7 +2119,6 @@ You should get the schema of the script or flow before updating the schedule to
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
},
|
||||
@@ -2198,7 +2148,6 @@ You should get the schema of the script or flow before updating the schedule to
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
}
|
||||
|
||||
@@ -295,7 +295,6 @@ impl McpBackend for WindmillBackend {
|
||||
workspace_id,
|
||||
args_map,
|
||||
&endpoint_tool.path_params_schema,
|
||||
&endpoint_tool.path_field_renames,
|
||||
)?;
|
||||
let query_string = build_query_string(
|
||||
args_map,
|
||||
|
||||
@@ -295,7 +295,7 @@ pub async fn get_hub_script_schema(path: &str, db: &DB) -> Result<Option<Schema>
|
||||
// ============================================================================
|
||||
|
||||
/// Look up the original field name from a field_renames map.
|
||||
/// field_renames maps renamed_key -> original_key (e.g. {"path__path": "path"}).
|
||||
/// field_renames maps renamed_key -> original_key (e.g. {"path__body": "path"}).
|
||||
fn get_original_name(renamed_key: &str, field_renames: &Option<Value>) -> String {
|
||||
field_renames
|
||||
.as_ref()
|
||||
@@ -373,20 +373,17 @@ pub fn substitute_path_params(
|
||||
workspace_id: &str,
|
||||
args_map: &serde_json::Map<String, Value>,
|
||||
path_schema: &Option<Value>,
|
||||
path_field_renames: &Option<Value>,
|
||||
) -> BackendResult<String> {
|
||||
let mut path_template = path.replace("{workspace}", workspace_id);
|
||||
|
||||
if let Some(schema) = path_schema {
|
||||
if let Some(props) = schema.get("properties").and_then(|p| p.as_object()) {
|
||||
for (param_name, _) in props {
|
||||
// param_name may be renamed (e.g. "path__path"), get original for URL placeholder
|
||||
let original_name = get_original_name(param_name, path_field_renames);
|
||||
let placeholder = format!("{{{}}}", original_name);
|
||||
let placeholder = format!("{{{}}}", param_name);
|
||||
match args_map.get(param_name) {
|
||||
Some(param_value) => {
|
||||
if let Some(str_val) = param_value.as_str() {
|
||||
validate_path_param_value(&original_name, str_val)?;
|
||||
validate_path_param_value(param_name, str_val)?;
|
||||
path_template = path_template.replace(&placeholder, str_val);
|
||||
}
|
||||
}
|
||||
@@ -675,6 +672,60 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// updateFlow-shaped: `path` is both a path parameter and a body field. The path
|
||||
// parameter keeps the plain name; only the body side is mangled.
|
||||
fn update_flow_schemas() -> (Option<Value>, Option<Value>, Option<Value>) {
|
||||
(
|
||||
Some(json!({
|
||||
"type": "object",
|
||||
"properties": { "path": { "type": "string" } },
|
||||
"required": ["path"]
|
||||
})),
|
||||
Some(json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"summary": { "type": "string" },
|
||||
"value": { "type": "object" },
|
||||
"path__body": { "type": "string" }
|
||||
},
|
||||
"required": ["summary", "value"]
|
||||
})),
|
||||
Some(json!({ "path__body": "path" })),
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_request_body_maps_body_path_alias_for_rename() {
|
||||
// The mangled body field carries the *new* path when renaming; it must reach the
|
||||
// API under its original name `path`. (An omitted `path__body` is intentionally
|
||||
// absent from the body; the server defaults it from the URL path parameter.)
|
||||
let (path_schema, body_schema, body_renames) = update_flow_schemas();
|
||||
let args: serde_json::Map<String, Value> = json!({
|
||||
"path": "f/team/my_flow",
|
||||
"path__body": "f/team/renamed_flow",
|
||||
"summary": "s",
|
||||
"value": {}
|
||||
})
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
let body = build_request_body(
|
||||
"POST",
|
||||
&args,
|
||||
&body_schema,
|
||||
&body_renames,
|
||||
&path_schema,
|
||||
&None,
|
||||
)
|
||||
.expect("body should be built");
|
||||
assert_eq!(
|
||||
body.as_object().unwrap().get("path"),
|
||||
Some(&json!("f/team/renamed_flow")),
|
||||
"path__body must be sent as `path` so a rename takes effect"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_request_body_get_has_no_body() {
|
||||
let body_schema = Some(json!({ "type": "object", "additionalProperties": true }));
|
||||
@@ -745,7 +796,6 @@ mod tests {
|
||||
"dev",
|
||||
&args,
|
||||
&path_schema,
|
||||
&None,
|
||||
);
|
||||
assert!(
|
||||
result.is_err(),
|
||||
@@ -767,7 +817,6 @@ mod tests {
|
||||
"dev",
|
||||
&args,
|
||||
&path_schema,
|
||||
&None,
|
||||
)
|
||||
.expect("legitimate path should substitute");
|
||||
assert_eq!(result, "/w/dev/scripts/get/p/u/alice/my_script");
|
||||
|
||||
@@ -21,7 +21,6 @@ pub struct EndpointTool {
|
||||
pub path_params_schema: Option<serde_json::Value>,
|
||||
pub query_params_schema: Option<serde_json::Value>,
|
||||
pub body_schema: Option<serde_json::Value>,
|
||||
pub path_field_renames: Option<serde_json::Value>,
|
||||
pub query_field_renames: Option<serde_json::Value>,
|
||||
pub body_field_renames: Option<serde_json::Value>,
|
||||
}
|
||||
@@ -215,7 +214,6 @@ mod tests {
|
||||
"required": []
|
||||
})),
|
||||
body_schema: None,
|
||||
path_field_renames: None,
|
||||
query_field_renames: None,
|
||||
body_field_renames: None,
|
||||
}
|
||||
|
||||
@@ -145,6 +145,57 @@ impl NewFlow {
|
||||
}
|
||||
}
|
||||
|
||||
/// Body for updating an existing flow. Mirrors `NewFlow`, but `path` is optional: the
|
||||
/// flow to update is identified by the URL, so the body only needs `path` to rename it.
|
||||
/// This matches the `EditVariable` / `EditResource` / `EditApp` convention and lets a
|
||||
/// caller update in place without restating the path.
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct EditFlow {
|
||||
#[serde(default)]
|
||||
pub path: Option<String>,
|
||||
pub summary: String,
|
||||
pub description: Option<String>,
|
||||
#[serde(deserialize_with = "validate_flow_value")]
|
||||
pub value: Box<RawValue>,
|
||||
pub schema: Option<Schema>,
|
||||
pub tag: Option<String>,
|
||||
pub dedicated_worker: Option<bool>,
|
||||
pub timeout: Option<i32>,
|
||||
pub deployment_message: Option<String>,
|
||||
pub visible_to_runner_only: Option<bool>,
|
||||
pub on_behalf_of_email: Option<String>,
|
||||
pub preserve_on_behalf_of: Option<bool>,
|
||||
pub ws_error_handler_muted: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub labels: Option<Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub skip_draft_deletion: Option<bool>,
|
||||
}
|
||||
|
||||
impl EditFlow {
|
||||
/// Resolve into a `NewFlow`, defaulting the target path to `current_path` (the flow's
|
||||
/// URL path) when the body omits it. A body `path` that differs renames the flow.
|
||||
pub fn into_new_flow(self, current_path: &str) -> NewFlow {
|
||||
NewFlow {
|
||||
path: self.path.unwrap_or_else(|| current_path.to_string()),
|
||||
summary: self.summary,
|
||||
description: self.description,
|
||||
value: self.value,
|
||||
schema: self.schema,
|
||||
tag: self.tag,
|
||||
dedicated_worker: self.dedicated_worker,
|
||||
timeout: self.timeout,
|
||||
deployment_message: self.deployment_message,
|
||||
visible_to_runner_only: self.visible_to_runner_only,
|
||||
on_behalf_of_email: self.on_behalf_of_email,
|
||||
preserve_on_behalf_of: self.preserve_on_behalf_of,
|
||||
ws_error_handler_muted: self.ws_error_handler_muted,
|
||||
labels: self.labels,
|
||||
skip_draft_deletion: self.skip_draft_deletion,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_retry(retry: &Retry, module_id: &str) -> anyhow::Result<()> {
|
||||
if retry.exponential.attempts > 0 && retry.exponential.seconds == 0 {
|
||||
return Err(anyhow::anyhow!(
|
||||
@@ -1233,6 +1284,20 @@ mod tests {
|
||||
use super::*;
|
||||
use serde_json::json;
|
||||
|
||||
#[test]
|
||||
fn edit_flow_defaults_path_from_url_and_renames_when_given() {
|
||||
// An omitted body path resolves to the URL path; an explicit body path renames.
|
||||
let ef: EditFlow =
|
||||
serde_json::from_value(json!({ "summary": "s", "value": { "modules": [] } })).unwrap();
|
||||
assert_eq!(ef.into_new_flow("f/team/my_flow").path, "f/team/my_flow");
|
||||
|
||||
let ef: EditFlow = serde_json::from_value(
|
||||
json!({ "path": "f/team/renamed", "summary": "s", "value": { "modules": [] } }),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(ef.into_new_flow("f/team/my_flow").path, "f/team/renamed");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flow_value_ignores_notes_and_groups() {
|
||||
// FlowValue should parse successfully even when notes/groups are present —
|
||||
|
||||
@@ -10,7 +10,6 @@ export interface EndpointTool {
|
||||
pathParamsSchema?: object;
|
||||
queryParamsSchema?: object;
|
||||
bodySchema?: object;
|
||||
pathFieldRenames?: Record<string, string>;
|
||||
queryFieldRenames?: Record<string, string>;
|
||||
bodyFieldRenames?: Record<string, string>;
|
||||
}
|
||||
@@ -36,7 +35,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
]
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -64,7 +62,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
]
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -134,7 +131,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"description"
|
||||
]
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -157,7 +153,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
},
|
||||
queryParamsSchema: undefined,
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -170,13 +165,12 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
pathParamsSchema: {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path__path": {
|
||||
"type": "string",
|
||||
"description": "(path parameter)"
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path__path"
|
||||
"path"
|
||||
]
|
||||
},
|
||||
queryParamsSchema: {
|
||||
@@ -215,12 +209,9 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
},
|
||||
"path__body": {
|
||||
"type": "string",
|
||||
"description": "The path to the variable (body parameter)"
|
||||
"description": "The path to the variable (body parameter). Defaults to `path` when omitted; set it only to change the path."
|
||||
}
|
||||
}
|
||||
},
|
||||
pathFieldRenames: {
|
||||
"path__path": "path"
|
||||
},
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: {
|
||||
@@ -263,7 +254,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -317,7 +307,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -372,7 +361,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"resource_type"
|
||||
]
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -395,7 +383,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
},
|
||||
queryParamsSchema: undefined,
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -408,13 +395,12 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
pathParamsSchema: {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path__path": {
|
||||
"type": "string",
|
||||
"description": "(path parameter)"
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path__path"
|
||||
"path"
|
||||
]
|
||||
},
|
||||
queryParamsSchema: undefined,
|
||||
@@ -443,12 +429,9 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
},
|
||||
"path__body": {
|
||||
"type": "string",
|
||||
"description": "The path to the resource (body parameter)"
|
||||
"description": "The path to the resource (body parameter). Defaults to `path` when omitted; set it only to change the path."
|
||||
}
|
||||
}
|
||||
},
|
||||
pathFieldRenames: {
|
||||
"path__path": "path"
|
||||
},
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: {
|
||||
@@ -483,7 +466,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -545,7 +527,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -558,7 +539,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
pathParamsSchema: undefined,
|
||||
queryParamsSchema: undefined,
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -656,7 +636,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -708,7 +687,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"language"
|
||||
]
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -731,7 +709,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
},
|
||||
queryParamsSchema: undefined,
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -763,7 +740,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -798,7 +774,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -825,7 +800,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"description": "The arguments to pass to the script or flow",
|
||||
"additionalProperties": true
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -895,7 +869,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -930,7 +903,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -976,7 +948,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
],
|
||||
"description": "Top-level flow definition containing metadata, configuration, and the flow structure"
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -989,13 +960,12 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
pathParamsSchema: {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path__path": {
|
||||
"type": "string",
|
||||
"description": "(path parameter)"
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path__path"
|
||||
"path"
|
||||
]
|
||||
},
|
||||
queryParamsSchema: undefined,
|
||||
@@ -1024,18 +994,14 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
},
|
||||
"path__body": {
|
||||
"type": "string",
|
||||
"description": "(body parameter)"
|
||||
"description": "(body parameter). Defaults to `path` when omitted; set it only to change the path."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"summary",
|
||||
"value",
|
||||
"path__body"
|
||||
"value"
|
||||
],
|
||||
"description": "Top-level flow definition containing metadata, configuration, and the flow structure"
|
||||
},
|
||||
pathFieldRenames: {
|
||||
"path__path": "path"
|
||||
},
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: {
|
||||
@@ -1070,7 +1036,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -1108,7 +1073,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"policy"
|
||||
]
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -1121,13 +1085,12 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
pathParamsSchema: {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path__path": {
|
||||
"type": "string",
|
||||
"description": "(path parameter)"
|
||||
"path": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"path__path"
|
||||
"path"
|
||||
]
|
||||
},
|
||||
queryParamsSchema: undefined,
|
||||
@@ -1148,12 +1111,9 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
},
|
||||
"path__body": {
|
||||
"type": "string",
|
||||
"description": "(body parameter)"
|
||||
"description": "(body parameter). Defaults to `path` when omitted; set it only to change the path."
|
||||
}
|
||||
}
|
||||
},
|
||||
pathFieldRenames: {
|
||||
"path__path": "path"
|
||||
},
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: {
|
||||
@@ -1183,7 +1143,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"description": "The arguments to pass to the script or flow",
|
||||
"additionalProperties": true
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -1278,7 +1237,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"language"
|
||||
]
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -1399,7 +1357,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -1566,7 +1523,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -1605,7 +1561,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -1637,7 +1592,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -1847,7 +1801,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"args"
|
||||
]
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -2050,7 +2003,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"args"
|
||||
]
|
||||
},
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -2073,7 +2025,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
},
|
||||
queryParamsSchema: undefined,
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -2105,7 +2056,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -2171,7 +2121,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
},
|
||||
@@ -2201,7 +2150,6 @@ export const mcpEndpointTools: EndpointTool[] = [
|
||||
"required": []
|
||||
},
|
||||
bodySchema: undefined,
|
||||
pathFieldRenames: undefined,
|
||||
queryFieldRenames: undefined,
|
||||
bodyFieldRenames: undefined
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user