feat(mcp): add script preview testing tool (#6417)
* add endpoint to test script * add same for flow * better tool spec + remove flow preview from tools * fix * fix wrong required fields * feat(mcp): add warning for missing required fields in schema properties - Add stderr warning when x-mcp-required-fields contains fields not found in body schema properties - Prevents silent misconfigurations in MCP tool generation - Helps debug schema validation issues Co-authored-by: centdix <centdix@users.noreply.github.com> --------- Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> Co-authored-by: centdix <centdix@users.noreply.github.com>
This commit is contained in:
@@ -177,12 +177,14 @@ pub fn workspaced_service() -> Router {
|
||||
.layer(ce_headers.clone()),
|
||||
)
|
||||
.route("/run/preview", post(run_preview_script))
|
||||
.route("/run_wait_result/preview", post(run_wait_result_preview_script))
|
||||
.route(
|
||||
"/run/preview_bundle",
|
||||
post(run_bundle_preview_script).layer(axum::extract::DefaultBodyLimit::disable()),
|
||||
)
|
||||
.route("/add_batch_jobs/:n", post(add_batch_jobs))
|
||||
.route("/run/preview_flow", post(run_preview_flow_job))
|
||||
.route("/run_wait_result/preview_flow", post(run_wait_result_preview_flow))
|
||||
.route("/list", get(list_jobs))
|
||||
.route(
|
||||
"/list_selected_job_groups",
|
||||
@@ -5207,6 +5209,28 @@ async fn run_preview_script(
|
||||
Ok((StatusCode::CREATED, uuid.to_string()))
|
||||
}
|
||||
|
||||
async fn run_wait_result_preview_script(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path(w_id): Path<String>,
|
||||
Query(run_query): Query<RunJobQuery>,
|
||||
Json(preview): Json<Preview>,
|
||||
) -> error::Result<Response> {
|
||||
|
||||
let (_status_code, uuid) = run_preview_script(
|
||||
authed.clone(),
|
||||
Extension(db.clone()),
|
||||
Extension(user_db.clone()),
|
||||
Path(w_id.clone()),
|
||||
Query(run_query.clone()),
|
||||
Json(preview)
|
||||
).await?;
|
||||
let uuid = uuid.parse::<Uuid>().map_err(|_| Error::BadRequest("Invalid UUID".to_string()))?;
|
||||
let result = run_wait_result(&db, uuid, w_id, None, &authed.username).await;
|
||||
return result;
|
||||
}
|
||||
|
||||
async fn run_bundle_preview_script(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
@@ -5865,6 +5889,20 @@ async fn run_preview_flow_job(
|
||||
Ok((StatusCode::CREATED, uuid.to_string()))
|
||||
}
|
||||
|
||||
async fn run_wait_result_preview_flow(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Extension(user_db): Extension<UserDB>,
|
||||
Path(w_id): Path<String>,
|
||||
Query(run_query): Query<RunJobQuery>,
|
||||
Json(raw_flow): Json<PreviewFlow>,
|
||||
) -> error::Result<Response> {
|
||||
let (_status_code, uuid) = run_preview_flow_job(authed.clone(), Extension(db.clone()), Extension(user_db.clone()), Path(w_id.clone()), Query(run_query.clone()), Json(raw_flow)).await?;
|
||||
let uuid = uuid.parse::<Uuid>().map_err(|_| Error::BadRequest("Invalid UUID".to_string()))?;
|
||||
let result = run_wait_result(&db, uuid, w_id, None, &authed.username).await;
|
||||
return result;
|
||||
}
|
||||
|
||||
pub async fn run_job_by_hash(
|
||||
authed: ApiAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
|
||||
@@ -564,6 +564,86 @@ pub fn all_tools() -> Vec<EndpointTool> {
|
||||
})),
|
||||
body_schema: None,
|
||||
},
|
||||
EndpointTool {
|
||||
name: Cow::Borrowed("runScriptPreviewAndWaitResult"),
|
||||
description: Cow::Borrowed("run script preview and wait for result"),
|
||||
instructions: Cow::Borrowed("Allows testing a script before deploying it. For typescript code, the language to send is either bun or deno. By default, send bun if no deno specific code is detected."),
|
||||
path: Cow::Borrowed("/w/{workspace}/jobs/run_wait_result/preview"),
|
||||
method: Cow::Borrowed("POST"),
|
||||
path_params_schema: None,
|
||||
query_params_schema: None,
|
||||
body_schema: Some(serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string",
|
||||
"description": "The code to run"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "The path to the script"
|
||||
},
|
||||
"script_hash": {
|
||||
"type": "string",
|
||||
"description": "The hash of the script"
|
||||
},
|
||||
"args": {
|
||||
"type": "object",
|
||||
"description": "The arguments to pass to the script or flow",
|
||||
"additionalProperties": {}
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"python3",
|
||||
"deno",
|
||||
"go",
|
||||
"bash",
|
||||
"powershell",
|
||||
"postgresql",
|
||||
"mysql",
|
||||
"bigquery",
|
||||
"snowflake",
|
||||
"mssql",
|
||||
"oracledb",
|
||||
"graphql",
|
||||
"nativets",
|
||||
"bun",
|
||||
"php",
|
||||
"rust",
|
||||
"ansible",
|
||||
"csharp",
|
||||
"nu",
|
||||
"java",
|
||||
"ruby",
|
||||
"duckdb"
|
||||
]
|
||||
},
|
||||
"tag": {
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"code",
|
||||
"identity",
|
||||
"http"
|
||||
]
|
||||
},
|
||||
"dedicated_worker": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"lock": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"args",
|
||||
"content",
|
||||
"language"
|
||||
]
|
||||
})),
|
||||
},
|
||||
EndpointTool {
|
||||
name: Cow::Borrowed("listQueue"),
|
||||
description: Cow::Borrowed("list all queued jobs"),
|
||||
|
||||
Reference in New Issue
Block a user