fix(mcp): show the route's rejection reason on the Integrations form too

The route now answers 400 with a message naming the expected shape.
admin.js was taught to print `data.detail`; the Unified Integrations
form in settings.js still printed `Failed (400)` and dropped it.

That gap is exactly where the new validation bites. The client-side
JSON.parse guard added alongside it catches unparseable input, so the
only values that reach the route's 400 are ones that parse but are not
a list — `"npx"`, `{}`, `null` — and for those the status code alone
tells the user nothing about what is wrong with what they typed.

Adds source-level coverage for both forms; the PR changed two JS files
with no test on either.
This commit is contained in:
Léo
2026-09-30 17:15:52 +02:00
parent 01b8ac5fea
commit 5f18767528
2 changed files with 33 additions and 1 deletions
+6 -1
View File
@@ -5128,7 +5128,12 @@ async function initUnifiedIntegrations() {
} else if (r.ok) {
el('uf-mcp-msg').textContent = 'Saved'; formEl.style.display = 'none'; await renderList();
} else {
el('uf-mcp-msg').textContent = `Failed (${r.status})`;
// Surface the server's reason. The Args validation above rejects
// unparseable JSON, but `"x"` and `{}` parse and are refused by
// routes/mcp/mcp_routes.py with a message naming the expected
// shape; a bare status code sends the user looking in the wrong
// place. Matches what admin.js shows for the same endpoint.
el('uf-mcp-msg').textContent = data.detail || `Failed (${r.status})`;
}
} catch (_) { el('uf-mcp-msg').textContent = 'Failed'; }
finally { _setBtnLoading(saveBtn, false, _origLabel); if (cancelBtn) cancelBtn.disabled = false; }