Skip to content

Commit 68fb36a

Browse files
fix(intercom): expose manage-conversation options as static props for MCP v3 (#21753)
* fix(intercom): expose manage-conversation options as static props for MCP v3 `Manage A Conversation` revealed `type`, `assigneeId`, `teamAssigneeId`, `body` and `snoozedUntil` through `additionalProps()`, driven by `reloadProps` on `messageType` and `type`. An MCP tool resolves its JSON Schema once at registration, so props that only appear after a parent prop is set never reach an agent. As the issue notes, this action fetches nothing: `additionalProps()` only flipped `hidden` on props that were already declared, then returned `{}`. All five are now declared plainly and the mechanism is gone. Three of them -- `type`, `assigneeId` and `teamAssigneeId` -- were hidden but not marked optional, so simply unhiding them would have made them required and broken every existing configuration. They are now explicitly `optional: true`. `body` and `snoozedUntil` were already optional. Nothing became required and no default changed. Since the form no longer hides the props that do not apply, each description now says which `messageType` it belongs to, and the action description lists the mapping. That is also what an agent reads to call the tool correctly. Also fixes a bug this mechanism was hiding: `run()` never read `teamAssigneeId`. Assigning to a team set `type: "team"` and then sent `assignee_id: assigneeId`, which `additionalProps()` had just hidden and left undefined -- so team assignment silently sent no assignee at all. `assignee_id` now takes the team id when `type` is `team`. The two ids stay separate props because they list different options (admins vs teams). * fix(intercom): add a concrete ISO 8601 example to the snoozedUntil description Date prop descriptions must carry a concrete inline example, per the component guidelines. The format string is replaced with a real timestamp. * fixing the coderabbit review and changes related to manage conversation --------- Co-authored-by: vetrivigneshwaran <vicky@pipedream.com>
1 parent 099e61a commit 68fb36a

2 files changed

Lines changed: 48 additions & 52 deletions

File tree

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ConfigurationError } from "@pipedream/platform";
12
import {
23
MESSAGE_TYPE_OPTIONS,
34
TYPE_OPTIONS,
@@ -7,8 +8,8 @@ import intercom from "../../intercom.app.mjs";
78
export default {
89
key: "intercom-manage-conversation",
910
name: "Manage A Conversation",
10-
description: "Close/Snooze/Open/Assign a conversation by its ID. [See the documentation](https://developers.intercom.com/docs/references/2.12/rest-api/api.intercom.io/conversations/manageconversation).",
11-
version: "0.0.1",
11+
description: "Close, snooze, open, or assign a conversation by its ID. Which of the optional props apply depends on **Message Type**: `close` uses **Body**, `snoozed` uses **Snoozed Until**, `assignment` uses **Type** together with **Assignee ID** or **Team Assignee ID**, and `open` uses none of them. [See the documentation](https://developers.intercom.com/docs/references/2.12/rest-api/api.intercom.io/conversations/manageconversation).",
12+
version: "0.1.0",
1213
annotations: {
1314
destructiveHint: false,
1415
openWorldHint: true,
@@ -26,84 +27,53 @@ export default {
2627
messageType: {
2728
type: "string",
2829
label: "Message Type",
29-
description: "The kind of message being created.",
30-
reloadProps: true,
30+
description: "The kind of message being created, which determines the operation performed on the conversation. Use `close` to close it, `snoozed` to snooze it, `open` to reopen it, or `assignment` to assign it.",
3131
options: MESSAGE_TYPE_OPTIONS,
3232
},
33-
type: {
34-
type: "string",
35-
label: "Type",
36-
description: "The type of the message being created.",
37-
options: TYPE_OPTIONS,
38-
reloadProps: true,
39-
hidden: true,
40-
},
4133
adminId: {
4234
propDefinition: [
4335
intercom,
4436
"adminId",
4537
],
4638
},
39+
type: {
40+
type: "string",
41+
label: "Type",
42+
description: "Whether an assignment targets an admin or a team. Only used when **Message Type** is `assignment`. Set `admin` to assign using **Assignee ID**, or `team` to assign using **Team Assignee ID**.",
43+
options: TYPE_OPTIONS,
44+
optional: true,
45+
},
4746
assigneeId: {
4847
propDefinition: [
4948
intercom,
5049
"adminId",
5150
],
5251
label: "Assignee ID",
53-
description: "The `id` of the `admin` which will be assigned the conversation. A conversation can be assigned both an admin and a team.\nSet `0` if you want this assign to no admin (ie. Unassigned).",
54-
hidden: true,
52+
description: "The `id` of the `admin` which will be assigned the conversation. Only used when **Message Type** is `assignment` and **Type** is `admin`. Set `0` to assign to no admin (ie. Unassigned).",
53+
optional: true,
5554
},
5655
teamAssigneeId: {
5756
propDefinition: [
5857
intercom,
5958
"teamAssigneeId",
6059
],
61-
hidden: true,
60+
label: "Team Assignee ID",
61+
description: "The `id` of the `team` which will be assigned the conversation. Only used when **Message Type** is `assignment` and **Type** is `team`. Set `0` to assign to no team (ie. Unassigned).",
62+
optional: true,
6263
},
6364
body: {
6465
type: "string",
6566
label: "Body",
66-
description: "The text body of the comment.",
67-
hidden: true,
67+
description: "The text body of the comment. Used when **Message Type** is `close` or `assignment`.",
6868
optional: true,
6969
},
7070
snoozedUntil: {
7171
type: "string",
7272
label: "Snoozed Until",
73-
description: "The date and time the conversation will be snoozed until. Format: YYYY-MM-DDTHH:MM:SSZ",
74-
hidden: true,
73+
description: "The date and time the conversation will be snoozed until, as an ISO 8601 timestamp — for example `2026-08-24T18:30:00Z`. Only used when **Message Type** is `snoozed`.",
7574
optional: true,
7675
},
7776
},
78-
additionalProps(props) {
79-
props.type.hidden = true;
80-
props.body.hidden = true;
81-
props.snoozedUntil.hidden = true;
82-
props.assigneeId.hidden = true;
83-
84-
switch (this.messageType) {
85-
case "snoozed":
86-
props.snoozedUntil.hidden = false;
87-
break;
88-
case "close":
89-
props.body.hidden = false;
90-
break;
91-
case "assignment":
92-
props.type.hidden = false;
93-
props.body.hidden = false;
94-
props.assigneeId.hidden = false;
95-
96-
if (this.type === "team") {
97-
props.teamAssigneeId.hidden = false;
98-
props.assigneeId.hidden = true;
99-
} else if (this.type === "admin") {
100-
props.teamAssigneeId.hidden = true;
101-
props.assigneeId.hidden = false;
102-
}
103-
break;
104-
}
105-
return {};
106-
},
10777
methods: {
10878
manageConversation({
10979
conversationId, ...args
@@ -125,8 +95,30 @@ export default {
12595
messageType,
12696
snoozedUntil,
12797
assigneeId,
98+
teamAssigneeId,
12899
} = this;
129100

101+
let snoozedUntilTimestamp;
102+
if (snoozedUntil) {
103+
const parsed = Date.parse(snoozedUntil);
104+
if (Number.isNaN(parsed)) {
105+
throw new ConfigurationError("`Snoozed Until` must be a valid ISO 8601 timestamp");
106+
}
107+
snoozedUntilTimestamp = parsed / 1000;
108+
}
109+
110+
if (messageType === "assignment") {
111+
if (type !== "admin" && type !== "team") {
112+
throw new ConfigurationError("`Type` must be `admin` or `team` when `Message Type` is `assignment`");
113+
}
114+
if (type === "admin" && assigneeId === undefined) {
115+
throw new ConfigurationError("`Assignee ID` is required when `Type` is `admin`");
116+
}
117+
if (type === "team" && teamAssigneeId === undefined) {
118+
throw new ConfigurationError("`Team Assignee ID` is required when `Type` is `team`");
119+
}
120+
}
121+
130122
const response = await manageConversation({
131123
$,
132124
conversationId,
@@ -137,12 +129,16 @@ export default {
137129
type: messageType === "close"
138130
? "admin"
139131
: type,
140-
snoozed_until: snoozedUntil && Date.parse(snoozedUntil) / 1000,
141-
assignee_id: assigneeId,
132+
snoozed_until: snoozedUntilTimestamp,
133+
// A team assignment carries the team's id in `assignee_id`; the admin and
134+
// team ids come from different props because they list different options.
135+
assignee_id: type === "team"
136+
? teamAssigneeId
137+
: assigneeId,
142138
},
143139
});
144140

145-
$.export("$summary", "Conversation managed successfully");
141+
$.export("$summary", `Conversation ${conversationId} updated with message type "${messageType}"`);
146142
return response;
147143
},
148144
};

components/intercom/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/intercom",
3-
"version": "0.9.0",
3+
"version": "0.10.0",
44
"description": "Pipedream Intercom Components",
55
"main": "intercom.app.mjs",
66
"keywords": [

0 commit comments

Comments
 (0)