@sendinel/mcp-server 1.0.161 → 1.0.162

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.
@@ -2,7 +2,7 @@ import { withApproval } from '../lib/action-approvals.js';
2
2
  import { z } from 'zod';
3
3
  import { adminDb, db } from '../db.js';
4
4
  import { getProjectId } from '../project.js';
5
- import { stripActiveEmailContent, validateUnsubscribeFooterTemplate } from '@sendinel/domain';
5
+ import { refuseActiveTextFields, stripActiveEmailContent, validateUnsubscribeFooterTemplate } from '@sendinel/domain';
6
6
  import { dbToolError, toolError } from '../lib/db-error.js';
7
7
  import { logAudit } from '../audit.js';
8
8
  import { assertHttpUrl } from '../lib/url-validation.js';
@@ -110,6 +110,11 @@ export function registerContentTools(server) {
110
110
  gate_body: z.string().max(1000).optional(),
111
111
  },
112
112
  }, async ({ title, slug, asset_url, asset_type = 'page', site_id, source_attribution, gate_headline, gate_body }) => {
113
+ for (const [field, value] of Object.entries({ title, source_attribution, gate_headline, gate_body })) {
114
+ const error = refuseActiveTextFields(field, value);
115
+ if (error)
116
+ return j({ error, code: 'validation_failed' });
117
+ }
113
118
  try {
114
119
  assertHttpUrl(asset_url);
115
120
  }
@@ -1,3 +1,4 @@
1
+ import { refuseActiveText, refuseActiveTextFields } from '@sendinel/domain';
1
2
  import { z } from 'zod';
2
3
  import { db } from '../db.js';
3
4
  import { getProjectId } from '../project.js';
@@ -28,6 +29,9 @@ function normalizeQuestions(questions) {
28
29
  });
29
30
  }
30
31
  function validateQuestions(questions) {
32
+ const activeTextError = refuseActiveTextFields('questions', questions);
33
+ if (activeTextError)
34
+ return activeTextError;
31
35
  const ids = new Set();
32
36
  for (const question of questions) {
33
37
  if (!question.label.trim())
@@ -85,6 +89,9 @@ export function registerSurveyTools(server) {
85
89
  status: z.enum(['draft', 'active', 'closed']).optional().default('draft'),
86
90
  },
87
91
  }, async ({ title, questions, site_id, status }) => {
92
+ const activeTextError = refuseActiveText('title', title) ?? refuseActiveTextFields('questions', questions);
93
+ if (activeTextError)
94
+ return j({ error: activeTextError, code: 'validation_failed' });
88
95
  const normalized = normalizeQuestions(questions);
89
96
  const validationError = validateQuestions(normalized);
90
97
  if (validationError)
@@ -217,6 +224,9 @@ export function registerSurveyTools(server) {
217
224
  },
218
225
  }, async ({ survey_id, title, questions, status }) => {
219
226
  const projectId = getProjectId();
227
+ const activeTextError = refuseActiveText('title', title) ?? refuseActiveTextFields('questions', questions);
228
+ if (activeTextError)
229
+ return j({ error: activeTextError, code: 'validation_failed' });
220
230
  const updates = {};
221
231
  if (title !== undefined)
222
232
  updates.title = title;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sendinel/mcp-server",
3
- "version": "1.0.161",
3
+ "version": "1.0.162",
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",