From 6ddfa1d4b98b999782303ca341a818414837b16a Mon Sep 17 00:00:00 2001 From: Harley Alexander <43975092+mayteio@users.noreply.github.com> Date: Thu, 22 Oct 2026 10:49:08 +0100 Subject: [PATCH 1/4] feat(workflows): add mcp tool to make an email template transactional Agents can create and edit email templates over MCP but cannot make one transactional, which the move of PostHog's own transactional emails onto workflows needs. - Add workflows-make-email-template-transactional as a typed-confirm prepare/execute pair, gated on workflows-transactional-email-api. - Say in the tool, the API description and the UI prompt that the change can't be undone and that sends ignore marketing opt-outs. - Regenerate OpenAPI types, MCP tool definitions and schema snapshots. Co-Authored-By: Claude Opus 5.5 Generated-By: PostHog Desktop Task-Id: c91d4fe4-cb37-4f9d-9598-946e91f7bc0c --- .../presentation/views/message_templates.py | 3 +- products/messaging/frontend/generated/api.ts | 2 +- .../messaging/frontend/generated/api.zod.ts | 2 +- .../MakeTransactionalPrompt.tsx | 1 + products/workflows/mcp/email_templates.yaml | 30 +++++++ .../schema/generated-tool-definitions.json | 30 +++++++ services/mcp/schema/tool-definitions-all.json | 30 +++++++ .../mcp/src/generated/email_templates/api.ts | 24 ++++- .../src/tools/generated/email_templates.ts | 90 +++++++++++++++++++ ...-email-template-transactional-execute.json | 16 ++++ ...-email-template-transactional-prepare.json | 22 +++++ .../tests/unit/tool-schema-snapshots.test.ts | 1 + 12 files changed, 247 insertions(+), 4 deletions(-) create mode 100644 services/mcp/tests/unit/__snapshots__/tool-schemas/workflows-make-email-template-transactional-execute.json create mode 100644 services/mcp/tests/unit/__snapshots__/tool-schemas/workflows-make-email-template-transactional-prepare.json diff --git a/products/messaging/backend/presentation/views/message_templates.py b/products/messaging/backend/presentation/views/message_templates.py index a4c0d5785e39..3573f6ffa6e1 100644 --- a/products/messaging/backend/presentation/views/message_templates.py +++ b/products/messaging/backend/presentation/views/message_templates.py @@ -791,7 +791,8 @@ def _require_transactional_email_flag(self) -> None: summary="Make a template transactional", description=( "Make this template sendable over the transactional email API. This creates the workflow that sends it, " - "with its own metrics, run history and versions. Calling it again on a transactional template changes " + "with its own metrics, run history and versions. This can't be undone: the template stays transactional. " + "Transactional sends ignore marketing opt-outs. Calling it again on a transactional template changes " "nothing." ), parameters=[TEMPLATE_ID_PARAMETER], diff --git a/products/messaging/frontend/generated/api.ts b/products/messaging/frontend/generated/api.ts index 17f050bec0ab..37b659d0838b 100644 --- a/products/messaging/frontend/generated/api.ts +++ b/products/messaging/frontend/generated/api.ts @@ -730,7 +730,7 @@ export const getMessagingTemplatesMakeTransactionalCreateUrl = (projectId: strin } /** - * Make this template sendable over the transactional email API. This creates the workflow that sends it, with its own metrics, run history and versions. Calling it again on a transactional template changes nothing. + * Make this template sendable over the transactional email API. This creates the workflow that sends it, with its own metrics, run history and versions. This can't be undone: the template stays transactional. Transactional sends ignore marketing opt-outs. Calling it again on a transactional template changes nothing. * @summary Make a template transactional */ export const messagingTemplatesMakeTransactionalCreate = async ( diff --git a/products/messaging/frontend/generated/api.zod.ts b/products/messaging/frontend/generated/api.zod.ts index bcbdb2664678..3816dda855be 100644 --- a/products/messaging/frontend/generated/api.zod.ts +++ b/products/messaging/frontend/generated/api.zod.ts @@ -1083,7 +1083,7 @@ export const MessagingTemplatesDesignPartialUpdateBody = /* @__PURE__ */ zod.obj }) /** - * Make this template sendable over the transactional email API. This creates the workflow that sends it, with its own metrics, run history and versions. Calling it again on a transactional template changes nothing. + * Make this template sendable over the transactional email API. This creates the workflow that sends it, with its own metrics, run history and versions. This can't be undone: the template stays transactional. Transactional sends ignore marketing opt-outs. Calling it again on a transactional template changes nothing. * @summary Make a template transactional */ export const MessagingTemplatesMakeTransactionalCreateBody = /* @__PURE__ */ zod.object({ diff --git a/products/workflows/frontend/TemplateLibrary/MakeTransactionalPrompt.tsx b/products/workflows/frontend/TemplateLibrary/MakeTransactionalPrompt.tsx index 94c014a42813..a8ace8d3333f 100644 --- a/products/workflows/frontend/TemplateLibrary/MakeTransactionalPrompt.tsx +++ b/products/workflows/frontend/TemplateLibrary/MakeTransactionalPrompt.tsx @@ -34,6 +34,7 @@ export function MakeTransactionalPrompt(props: MessageTemplateSceneLogicProps): Your edits save as a draft. Publishing updates the live email, and each publish keeps a version.
  • Transactional emails ignore marketing opt-outs, so don't use them for marketing.
  • +
  • You can't undo this. The template stays transactional.
  • + Make an email template sendable from code with one API call, for emails a person triggers such as password + resets, receipts and sign-in codes. This is one-way: the template can't be made non-transactional again. + Transactional sends ignore marketing opt-outs, so never use this for marketing email. The template needs a + subject and a body, and the project needs a verified email sender (pass from_integration_id to pick one, + otherwise the project's default sender is used). Requires human typed confirmation. The response has + transactional_hog_flow_id, the workflow that sends the email. Share the template's _posthogUrl so the user + can review and publish it. + confirmed_action: + message: > + About to make email template '{id}' transactional. This can't be undone, and its sends will ignore + marketing opt-outs. Reply 'confirm' to proceed. + action_label: make email template transactional + response: + exclude: + - content + - draft_content + - created_by workflows-patch-email-template: operation: messaging_templates_design_partial_update enabled: true diff --git a/services/mcp/schema/generated-tool-definitions.json b/services/mcp/schema/generated-tool-definitions.json index 470830dfb205..4202113ff79e 100644 --- a/services/mcp/schema/generated-tool-definitions.json +++ b/services/mcp/schema/generated-tool-definitions.json @@ -16403,6 +16403,36 @@ "readOnlyHint": true } }, + "workflows-make-email-template-transactional-execute": { + "description": "Step 2 of 2 for make email template transactional. Verifies the confirmation_hash from -prepare and the literal \"confirm\" string typed by the user, then performs the action. ONLY call this after the user has explicitly typed \"confirm\" in chat. Original action: Make an email template sendable from code with one API call, for emails a person triggers such as password resets, receipts and sign-in codes. This is one-way: the template can't be made non-transactional again. Transactional sends ignore marketing opt-outs, so never use this for marketing email. The template needs a subject and a body, and the project needs a verified email sender (pass from_integration_id to pick one, otherwise the project's default sender is used). Requires human typed confirmation. The response has transactional_hog_flow_id, the workflow that sends the email. Share the template's _posthogUrl so the user can review and publish it.", + "category": "Workflows", + "feature": "workflows", + "summary": "Make email template transactional (execute)", + "title": "Make email template transactional (execute)", + "required_scopes": ["hog_flow:write"], + "annotations": { + "destructiveHint": false, + "idempotentHint": true, + "openWorldHint": true, + "readOnlyHint": false + }, + "feature_flag": "workflows-transactional-email-api" + }, + "workflows-make-email-template-transactional-prepare": { + "description": "Step 1 of 2 for make email template transactional. Validates the arguments and returns a signed confirmation_hash plus a message to surface to the user. The user must reply with the literal word \"confirm\" before you call the matching -execute tool with the hash. Original action: Make an email template sendable from code with one API call, for emails a person triggers such as password resets, receipts and sign-in codes. This is one-way: the template can't be made non-transactional again. Transactional sends ignore marketing opt-outs, so never use this for marketing email. The template needs a subject and a body, and the project needs a verified email sender (pass from_integration_id to pick one, otherwise the project's default sender is used). Requires human typed confirmation. The response has transactional_hog_flow_id, the workflow that sends the email. Share the template's _posthogUrl so the user can review and publish it.", + "category": "Workflows", + "feature": "workflows", + "summary": "Make email template transactional (prepare)", + "title": "Make email template transactional (prepare)", + "required_scopes": ["hog_flow:write"], + "annotations": { + "destructiveHint": false, + "idempotentHint": true, + "openWorldHint": true, + "readOnlyHint": true + }, + "feature_flag": "workflows-transactional-email-api" + }, "workflows-patch-action-email": { "description": "Surgically edit the email inside one function_email step - the fastest path for copy tweaks and design changes on a workflow email. Use operations (the same design ops as workflows-patch-email-template, addressing blocks by id from the step's config.inputs.email.value.design) to edit the design, and email_patch to change subject, preheader, text, or recipients. After design ops the HTML is re-rendered server-side, so the sent email always matches the design. Edits apply atomically: an invalid batch changes nothing. On an active workflow, edits stage a draft (composing with any staged graph edits) and nothing reaches real people until workflows-publish. The full updated workflow is returned. Prefer this over workflows-patch-graph update_action for email content - it's smaller to send and keeps design and HTML in sync. For library templates use workflows-patch-email-template instead.", "category": "Workflows", diff --git a/services/mcp/schema/tool-definitions-all.json b/services/mcp/schema/tool-definitions-all.json index 4cd55998d085..4fee8c952fe8 100644 --- a/services/mcp/schema/tool-definitions-all.json +++ b/services/mcp/schema/tool-definitions-all.json @@ -17192,6 +17192,36 @@ "readOnlyHint": true } }, + "workflows-make-email-template-transactional-execute": { + "description": "Step 2 of 2 for make email template transactional. Verifies the confirmation_hash from -prepare and the literal \"confirm\" string typed by the user, then performs the action. ONLY call this after the user has explicitly typed \"confirm\" in chat. Original action: Make an email template sendable from code with one API call, for emails a person triggers such as password resets, receipts and sign-in codes. This is one-way: the template can't be made non-transactional again. Transactional sends ignore marketing opt-outs, so never use this for marketing email. The template needs a subject and a body, and the project needs a verified email sender (pass from_integration_id to pick one, otherwise the project's default sender is used). Requires human typed confirmation. The response has transactional_hog_flow_id, the workflow that sends the email. Share the template's _posthogUrl so the user can review and publish it.", + "category": "Workflows", + "feature": "workflows", + "summary": "Make email template transactional (execute)", + "title": "Make email template transactional (execute)", + "required_scopes": ["hog_flow:write"], + "annotations": { + "destructiveHint": false, + "idempotentHint": true, + "openWorldHint": true, + "readOnlyHint": false + }, + "feature_flag": "workflows-transactional-email-api" + }, + "workflows-make-email-template-transactional-prepare": { + "description": "Step 1 of 2 for make email template transactional. Validates the arguments and returns a signed confirmation_hash plus a message to surface to the user. The user must reply with the literal word \"confirm\" before you call the matching -execute tool with the hash. Original action: Make an email template sendable from code with one API call, for emails a person triggers such as password resets, receipts and sign-in codes. This is one-way: the template can't be made non-transactional again. Transactional sends ignore marketing opt-outs, so never use this for marketing email. The template needs a subject and a body, and the project needs a verified email sender (pass from_integration_id to pick one, otherwise the project's default sender is used). Requires human typed confirmation. The response has transactional_hog_flow_id, the workflow that sends the email. Share the template's _posthogUrl so the user can review and publish it.", + "category": "Workflows", + "feature": "workflows", + "summary": "Make email template transactional (prepare)", + "title": "Make email template transactional (prepare)", + "required_scopes": ["hog_flow:write"], + "annotations": { + "destructiveHint": false, + "idempotentHint": true, + "openWorldHint": true, + "readOnlyHint": true + }, + "feature_flag": "workflows-transactional-email-api" + }, "workflows-patch-action-email": { "description": "Surgically edit the email inside one function_email step - the fastest path for copy tweaks and design changes on a workflow email. Use operations (the same design ops as workflows-patch-email-template, addressing blocks by id from the step's config.inputs.email.value.design) to edit the design, and email_patch to change subject, preheader, text, or recipients. After design ops the HTML is re-rendered server-side, so the sent email always matches the design. Edits apply atomically: an invalid batch changes nothing. On an active workflow, edits stage a draft (composing with any staged graph edits) and nothing reaches real people until workflows-publish. The full updated workflow is returned. Prefer this over workflows-patch-graph update_action for email content - it's smaller to send and keeps design and HTML in sync. For library templates use workflows-patch-email-template instead.", "category": "Workflows", diff --git a/services/mcp/src/generated/email_templates/api.ts b/services/mcp/src/generated/email_templates/api.ts index 74397267a1a2..7c992efdbae0 100644 --- a/services/mcp/src/generated/email_templates/api.ts +++ b/services/mcp/src/generated/email_templates/api.ts @@ -3,7 +3,7 @@ * MCP service uses these Zod schemas for generated tool handlers. * To regenerate: hogli build:openapi * - * PostHog API - MCP 5 enabled ops + * PostHog API - MCP 6 enabled ops * OpenAPI spec version: 1.0.0 */ import * as zod from 'zod' @@ -396,3 +396,25 @@ export const MessagingTemplatesDesignPartialUpdateBody = () => zod.object({ "Ordered edits applied atomically to a template's Unlayer design: the stored design is read, the ops are applied in order, the result is validated and re-rendered to HTML, and it's saved only if valid — otherwise the template is unchanged. Reference blocks by id so you never resend the whole design." ), }) + +/** + * Make this template sendable over the transactional email API. This creates the workflow that sends it, with its own metrics, run history and versions. This can't be undone: the template stays transactional. Transactional sends ignore marketing opt-outs. Calling it again on a transactional template changes nothing. + * @summary Make a template transactional + */ +export const MessagingTemplatesMakeTransactionalCreateParams = () => zod.object({ + id: zod.string().describe('A UUID string identifying this message template.'), + project_id: zod + .string() + .describe( + "Project ID of the project you're trying to access. To find the ID of the project, make a call to \/api\/projects\/." + ), +}) + +export const MessagingTemplatesMakeTransactionalCreateBody = () => zod.object({ + from_integration_id: zod + .number() + .nullish() + .describe( + "ID of the verified email sender integration the email is sent from. Defaults to the project's default sender." + ), +}) diff --git a/services/mcp/src/tools/generated/email_templates.ts b/services/mcp/src/tools/generated/email_templates.ts index 4771f42e4c62..b102d2dd0916 100644 --- a/services/mcp/src/tools/generated/email_templates.ts +++ b/services/mcp/src/tools/generated/email_templates.ts @@ -5,6 +5,12 @@ import type { Schemas } from '@/api/generated' import * as orvalSchemas from '@/generated/email_templates/api' import { withUiApp } from '@/resources/ui-apps' import { EmailTemplateDesignPatchSchema } from '@/schema/tool-inputs' +import { getConfirmedActionRuntime } from '@/tools/confirmed-action-registry' +import { + executeConfirmedAction, + prepareConfirmedAction, + type PrepareConfirmedActionResult, +} from '@/tools/confirmed-action-runtime' import { withPostHogUrl, omitResponseFields, type WithPostHogUrl } from '@/tools/tool-utils' import type { Context, ToolBase, ZodObjectAny } from '@/tools/types' @@ -124,6 +130,88 @@ const workflowsListEmailTemplates = (): ToolBase< }, }) +const WorkflowsMakeEmailTemplateTransactionalSchema = () => { + const MessagingTemplatesMakeTransactionalCreateBody = orvalSchemas.MessagingTemplatesMakeTransactionalCreateBody() + const MessagingTemplatesMakeTransactionalCreateParams = + orvalSchemas.MessagingTemplatesMakeTransactionalCreateParams() + return MessagingTemplatesMakeTransactionalCreateParams.omit({ project_id: true }).extend( + MessagingTemplatesMakeTransactionalCreateBody.shape + ) +} + +const WorkflowsMakeEmailTemplateTransactionalSchemaExecute = z.strictObject({ + confirmation_hash: z + .string() + .describe('The confirmation_hash returned by the matching -prepare tool. Pass it back verbatim.'), + confirmation: z.string().describe('The literal string "confirm", typed by the user in chat. Required to proceed.'), +}) + +const workflowsMakeEmailTemplateTransactionalPrepare = (): ToolBase< + ReturnType, + PrepareConfirmedActionResult +> => ({ + name: 'workflows-make-email-template-transactional-prepare', + schema: WorkflowsMakeEmailTemplateTransactionalSchema(), + handler: async ( + context: Context, + params: z.infer> + ) => { + const __runtime = getConfirmedActionRuntime() + const __scopeProjectId = await context.stateManager.getProjectId() + return await prepareConfirmedAction(context, { + args: params, + purpose: 'workflows-make-email-template-transactional', + actionLabel: 'make email template transactional', + messageTemplate: + "About to make email template '{id}' transactional. This can't be undone, and its sends will ignore marketing opt-outs. Reply 'confirm' to proceed.\n", + codec: __runtime.codec, + stash: __runtime.stash, + boundScope: { projectId: String(__scopeProjectId) }, + }) + }, +}) + +const workflowsMakeEmailTemplateTransactionalExecute = (): ToolBase< + typeof WorkflowsMakeEmailTemplateTransactionalSchemaExecute, + WithPostHogUrl +> => ({ + name: 'workflows-make-email-template-transactional-execute', + schema: WorkflowsMakeEmailTemplateTransactionalSchemaExecute, + handler: async ( + context: Context, + confirmationParams: z.infer + ) => { + const __runtime = getConfirmedActionRuntime() + const __scopeProjectId = await context.stateManager.getProjectId() + const __guard = await executeConfirmedAction< + z.infer> + >(context, { + incomingArgs: confirmationParams, + purpose: 'workflows-make-email-template-transactional', + codec: __runtime.codec, + ledger: __runtime.ledger, + stash: __runtime.stash, + expectedScope: { projectId: String(__scopeProjectId) }, + }) + if (!__guard.ok) { + return __guard.result as never + } + const params = __guard.verifiedArgs + const projectId = __scopeProjectId + const body: Record = {} + if (params.from_integration_id !== undefined) { + body['from_integration_id'] = params.from_integration_id + } + const result = await context.api.request({ + method: 'POST', + path: `/api/projects/${encodeURIComponent(String(projectId))}/messaging_templates/${encodeURIComponent(String(params.id))}/make_transactional/`, + body, + }) + const filtered = omitResponseFields(result, ['content', 'draft_content', 'created_by']) as typeof result + return await withPostHogUrl(context, filtered, `/workflows/library/templates/${filtered.id}`) + }, +}) + const WorkflowsPatchEmailTemplateSchema = () => EmailTemplateDesignPatchSchema const workflowsPatchEmailTemplate = (): ToolBase< @@ -228,6 +316,8 @@ export const GENERATED_TOOLS: Record ToolBase> = { 'workflows-create-email-template': workflowsCreateEmailTemplate, 'workflows-get-email-template': workflowsGetEmailTemplate, 'workflows-list-email-templates': workflowsListEmailTemplates, + 'workflows-make-email-template-transactional-prepare': workflowsMakeEmailTemplateTransactionalPrepare, + 'workflows-make-email-template-transactional-execute': workflowsMakeEmailTemplateTransactionalExecute, 'workflows-patch-email-template': workflowsPatchEmailTemplate, 'workflows-show-email-template': workflowsShowEmailTemplate, 'workflows-update-email-template': workflowsUpdateEmailTemplate, diff --git a/services/mcp/tests/unit/__snapshots__/tool-schemas/workflows-make-email-template-transactional-execute.json b/services/mcp/tests/unit/__snapshots__/tool-schemas/workflows-make-email-template-transactional-execute.json new file mode 100644 index 000000000000..f9e863b2ae53 --- /dev/null +++ b/services/mcp/tests/unit/__snapshots__/tool-schemas/workflows-make-email-template-transactional-execute.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "confirmation": { + "description": "The literal string \"confirm\", typed by the user in chat. Required to proceed.", + "type": "string" + }, + "confirmation_hash": { + "description": "The confirmation_hash returned by the matching -prepare tool. Pass it back verbatim.", + "type": "string" + } + }, + "required": ["confirmation_hash", "confirmation"], + "type": "object" +} diff --git a/services/mcp/tests/unit/__snapshots__/tool-schemas/workflows-make-email-template-transactional-prepare.json b/services/mcp/tests/unit/__snapshots__/tool-schemas/workflows-make-email-template-transactional-prepare.json new file mode 100644 index 000000000000..778419a42fd7 --- /dev/null +++ b/services/mcp/tests/unit/__snapshots__/tool-schemas/workflows-make-email-template-transactional-prepare.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "properties": { + "from_integration_id": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "description": "ID of the verified email sender integration the email is sent from. Defaults to the project's default sender." + }, + "id": { + "description": "A UUID string identifying this message template.", + "type": "string" + } + }, + "required": ["id"], + "type": "object" +} diff --git a/services/mcp/tests/unit/tool-schema-snapshots.test.ts b/services/mcp/tests/unit/tool-schema-snapshots.test.ts index de6cbedff36c..cb4bbac08589 100644 --- a/services/mcp/tests/unit/tool-schema-snapshots.test.ts +++ b/services/mcp/tests/unit/tool-schema-snapshots.test.ts @@ -107,6 +107,7 @@ async function loadSnapshotTools(): Promise[]> { 'marketing-analytics-conversion-setup-ai': true, 'workflows-mcp-onboarding': true, 'insight-data-checks': true, + 'workflows-transactional-email-api': true, } return [...(await getToolsFromContext(createMockContext(), { featureFlags }))].sort((a, b) => a.name.localeCompare(b.name) From a1146623e2f848ef8d0512418ffe564cd6755aa8 Mon Sep 17 00:00:00 2001 From: Harley Alexander <43975092+mayteio@users.noreply.github.com> Date: Thu, 22 Oct 2026 10:49:12 +0100 Subject: [PATCH 2/4] chore: update OpenAPI generated types --- products/workflows/mcp/email_templates.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/products/workflows/mcp/email_templates.yaml b/products/workflows/mcp/email_templates.yaml index 5a8ce1c997b0..028996c3411e 100644 --- a/products/workflows/mcp/email_templates.yaml +++ b/products/workflows/mcp/email_templates.yaml @@ -86,7 +86,6 @@ tools: readOnly: false destructive: false idempotent: true - feature_flag: workflows-transactional-email-api enrich_url: '{id}' title: Make email template transactional description: > @@ -97,16 +96,17 @@ tools: otherwise the project's default sender is used). Requires human typed confirmation. The response has transactional_hog_flow_id, the workflow that sends the email. Share the template's _posthogUrl so the user can review and publish it. - confirmed_action: - message: > - About to make email template '{id}' transactional. This can't be undone, and its sends will ignore - marketing opt-outs. Reply 'confirm' to proceed. - action_label: make email template transactional + feature_flag: workflows-transactional-email-api response: exclude: - content - draft_content - created_by + confirmed_action: + message: > + About to make email template '{id}' transactional. This can't be undone, and its sends will ignore + marketing opt-outs. Reply 'confirm' to proceed. + action_label: make email template transactional workflows-patch-email-template: operation: messaging_templates_design_partial_update enabled: true From 60babe12db341ee0af29ce99acb174ec3faf1e1f Mon Sep 17 00:00:00 2001 From: Harley Alexander <43975092+mayteio@users.noreply.github.com> Date: Thu, 22 Oct 2026 10:49:15 +0100 Subject: [PATCH 3/4] fix(workflows): mark make-transactional tool destructive and register its flag - Add workflows-transactional-email-api to the branch flags in tool-filtering.test.ts, so the required-flags count matches. - Set destructive: true on workflows-make-email-template-transactional, because the change can't be undone. MCP clients then show their own confirm prompt too. Co-Authored-By: Claude Opus 5.5 Generated-By: PostHog Desktop Task-Id: c91d4fe4-cb37-4f9d-9598-946e91f7bc0c --- products/workflows/mcp/email_templates.yaml | 2 +- services/mcp/schema/generated-tool-definitions.json | 2 +- services/mcp/schema/tool-definitions-all.json | 2 +- services/mcp/tests/unit/tool-filtering.test.ts | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/products/workflows/mcp/email_templates.yaml b/products/workflows/mcp/email_templates.yaml index 028996c3411e..b16dee1b3000 100644 --- a/products/workflows/mcp/email_templates.yaml +++ b/products/workflows/mcp/email_templates.yaml @@ -84,7 +84,7 @@ tools: - hog_flow:write annotations: readOnly: false - destructive: false + destructive: true idempotent: true enrich_url: '{id}' title: Make email template transactional diff --git a/services/mcp/schema/generated-tool-definitions.json b/services/mcp/schema/generated-tool-definitions.json index 4202113ff79e..d66586d23a8b 100644 --- a/services/mcp/schema/generated-tool-definitions.json +++ b/services/mcp/schema/generated-tool-definitions.json @@ -16411,7 +16411,7 @@ "title": "Make email template transactional (execute)", "required_scopes": ["hog_flow:write"], "annotations": { - "destructiveHint": false, + "destructiveHint": true, "idempotentHint": true, "openWorldHint": true, "readOnlyHint": false diff --git a/services/mcp/schema/tool-definitions-all.json b/services/mcp/schema/tool-definitions-all.json index 4fee8c952fe8..fc8c2d8d093e 100644 --- a/services/mcp/schema/tool-definitions-all.json +++ b/services/mcp/schema/tool-definitions-all.json @@ -17200,7 +17200,7 @@ "title": "Make email template transactional (execute)", "required_scopes": ["hog_flow:write"], "annotations": { - "destructiveHint": false, + "destructiveHint": true, "idempotentHint": true, "openWorldHint": true, "readOnlyHint": false diff --git a/services/mcp/tests/unit/tool-filtering.test.ts b/services/mcp/tests/unit/tool-filtering.test.ts index ba3f52d9fabb..a173c99cc070 100644 --- a/services/mcp/tests/unit/tool-filtering.test.ts +++ b/services/mcp/tests/unit/tool-filtering.test.ts @@ -1110,6 +1110,7 @@ describe('Tool Filtering - Feature Flags', () => { 'marketing-analytics-conversion-setup-ai', 'insight-data-checks', 'logs-agent-tools', + 'workflows-transactional-email-api', ] expect(allFlags).toEqual(expect.arrayContaining(branchFlags)) // The flags branches add are asserted on the line above and held out of the list and From c77bc94fd997d7b3b1fb5412daddf0792bfa2ce8 Mon Sep 17 00:00:00 2001 From: Harley Alexander <43975092+mayteio@users.noreply.github.com> Date: Thu, 22 Oct 2026 10:49:29 +0100 Subject: [PATCH 4/4] chore(workflows): regenerate mcp tool definitions Adds the api_operations field that master's generator now emits for the make-transactional tool. Generated-By: PostHog Desktop Task-Id: 20d9dd00-fcbd-4c83-a5c3-68a47fd9be9a --- services/mcp/schema/generated-tool-definitions.json | 1 + services/mcp/schema/tool-definitions-all.json | 1 + 2 files changed, 2 insertions(+) diff --git a/services/mcp/schema/generated-tool-definitions.json b/services/mcp/schema/generated-tool-definitions.json index d66586d23a8b..0e437e8d6f1f 100644 --- a/services/mcp/schema/generated-tool-definitions.json +++ b/services/mcp/schema/generated-tool-definitions.json @@ -16410,6 +16410,7 @@ "summary": "Make email template transactional (execute)", "title": "Make email template transactional (execute)", "required_scopes": ["hog_flow:write"], + "api_operations": ["POST /api/projects/{project_id}/messaging_templates/{id}/make_transactional/"], "annotations": { "destructiveHint": true, "idempotentHint": true, diff --git a/services/mcp/schema/tool-definitions-all.json b/services/mcp/schema/tool-definitions-all.json index fc8c2d8d093e..a4cd456aa0b2 100644 --- a/services/mcp/schema/tool-definitions-all.json +++ b/services/mcp/schema/tool-definitions-all.json @@ -17199,6 +17199,7 @@ "summary": "Make email template transactional (execute)", "title": "Make email template transactional (execute)", "required_scopes": ["hog_flow:write"], + "api_operations": ["POST /api/projects/{project_id}/messaging_templates/{id}/make_transactional/"], "annotations": { "destructiveHint": true, "idempotentHint": true,