@sendinel/mcp-server 1.0.178 → 1.0.180
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -117,6 +117,7 @@ type ToolResult = {
|
|
|
117
117
|
type: 'text';
|
|
118
118
|
text: string;
|
|
119
119
|
}>;
|
|
120
|
+
isError?: boolean;
|
|
120
121
|
};
|
|
121
122
|
export declare function approvalSatisfied(action: string): boolean;
|
|
122
123
|
/** Catch preview/draft branches that historically returned before their hand-written gate.
|
|
@@ -17,6 +17,7 @@ import { captureApprovalSnapshot, withoutApprovalSnapshot, withoutApprovalDispla
|
|
|
17
17
|
import { fireWebhookEvent } from './webhook-events.js';
|
|
18
18
|
import { offerApprovalApp } from './approval-app.js';
|
|
19
19
|
import { elicitApproval } from './approval-elicitation.js';
|
|
20
|
+
import { toolError } from './db-error.js';
|
|
20
21
|
export function getApprovalTier(action, params) {
|
|
21
22
|
// #4308 / #4214: a request-only connection cannot bypass approval via autonomous/preview modes.
|
|
22
23
|
const scopes = requestContext()?.scopes;
|
|
@@ -291,8 +292,13 @@ export function approvalRetryTool(action, config, handler, nativeReplay = native
|
|
|
291
292
|
if (typeof approval_id === 'string' && Object.values(supplied).every(value => value === undefined)) {
|
|
292
293
|
const { data, error } = await approvalStore().schema('email').from('action_approvals')
|
|
293
294
|
.select('action, params, payload_hash').eq('id', approval_id).eq('project_id', getProjectId()).eq('action', action).maybeSingle();
|
|
294
|
-
if (error || !data)
|
|
295
|
-
return
|
|
295
|
+
if (error || !data) {
|
|
296
|
+
return toolError({
|
|
297
|
+
code: 'not_found',
|
|
298
|
+
error: 'Approval not found for this action and project. Request a new approval.',
|
|
299
|
+
next: 'Call again without approval_id to request a new approval.',
|
|
300
|
+
});
|
|
301
|
+
}
|
|
296
302
|
if (data.payload_hash && approvalPayloadHash(action, data.params) !== data.payload_hash) {
|
|
297
303
|
return toolText(JSON.stringify({ code: 'validation_failed', error: 'payload_changed_after_approval' }));
|
|
298
304
|
}
|
|
@@ -670,7 +676,16 @@ export function withApproval(action, handler, options = {}) {
|
|
|
670
676
|
consumedAt = check.consumed_at;
|
|
671
677
|
decisionChannel = check.decision_channel === 'sandbox' ? 'sandbox' : undefined;
|
|
672
678
|
if (!check.approved) {
|
|
673
|
-
|
|
679
|
+
const code = check.status === 'rejected' || check.status === 'human_decision_required' ? 'forbidden'
|
|
680
|
+
: check.status === 'not_found' || check.status === 'action_mismatch' ? 'not_found'
|
|
681
|
+
: 'conflict';
|
|
682
|
+
return toolError({
|
|
683
|
+
code,
|
|
684
|
+
error: `Approval ${approval_id} is ${check.status}. ${check.status === 'pending' ? 'Waiting for human approval via dashboard.' : 'Request a new approval.'}`,
|
|
685
|
+
next: check.status === 'pending'
|
|
686
|
+
? 'Wait for a person to approve it, then call again with only approval_id.'
|
|
687
|
+
: 'Call again without approval_id to request a new approval.',
|
|
688
|
+
});
|
|
674
689
|
}
|
|
675
690
|
}
|
|
676
691
|
if (options.registeredRequestOnly) {
|
package/build/tools/approvals.js
CHANGED
|
@@ -91,6 +91,11 @@ export function registerApprovalTools(server, options) {
|
|
|
91
91
|
.limit(25);
|
|
92
92
|
if (error)
|
|
93
93
|
return toolError(dbToolError(error));
|
|
94
|
-
|
|
94
|
+
const rows = (data ?? []).map((row) => ({ ...row, ...(row.decided_via === 'sandbox' ? { decision_channel: 'sandbox' } : {}) }));
|
|
95
|
+
return j({
|
|
96
|
+
pending: rows,
|
|
97
|
+
...(status === 'approved' ? { approvals: rows } : {}),
|
|
98
|
+
count: data?.length ?? 0,
|
|
99
|
+
});
|
|
95
100
|
});
|
|
96
101
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendinel/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.180",
|
|
4
4
|
"description": "AI-controlled email operations control plane for campaigns, contacts, segments, analytics, and multi-provider sending via MCP.",
|
|
5
5
|
"mcpName": "ai.sendinel/mcp-server",
|
|
6
6
|
"type": "module",
|