@jclvsh/iris 0.19.0 → 0.20.0
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.
- package/README.md +8 -2
- package/dist/commands/campaigns.js +87 -0
- package/dist/commands/conversations.js +13 -0
- package/dist/tools/campaigns.js +67 -0
- package/dist/tools/conversations.js +12 -0
- package/dist/tools/messages.js +4 -1
- package/dist/types.d.ts +23 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -61,10 +61,10 @@ iris campaigns --help
|
|
|
61
61
|
|
|
62
62
|
| Group | Alias | Commands | Count |
|
|
63
63
|
| ------------- | ------ | ------------------------------------------------------------- | ----- |
|
|
64
|
-
| campaigns | `c` | list, get, create, update, delete, usage, analyze
|
|
64
|
+
| campaigns | `c` | list, get, create, update, delete, usage, analyze, contacts, add-contacts, chats, chat-messages, rename-chat, delete-chat | 13 |
|
|
65
65
|
| contacts | `ct` | list, get, create, update, delete, usage | 6 |
|
|
66
66
|
| messages | `m` | pending, approve, reject, retry, feedback, bulk | 6 |
|
|
67
|
-
| conversations | `conv` | list, get, messages, read
|
|
67
|
+
| conversations | `conv` | list, get, create, send, messages, read, update | 7 |
|
|
68
68
|
| discovery | `d` | search, search-campaign, sources, job | 4 |
|
|
69
69
|
| ai | — | generate, generate-campaign, analyze, usage | 4 |
|
|
70
70
|
| keys | `k` | me, list, create, rename, revoke | 5 |
|
|
@@ -136,6 +136,11 @@ Add to `.cursor/mcp.json`:
|
|
|
136
136
|
| `update_campaign` | Update a campaign's name, status, or follow-up settings |
|
|
137
137
|
| `delete_campaign` | Soft-delete a campaign (sets status to `deleted`) |
|
|
138
138
|
| `list_campaign_contacts` | List contacts in a campaign with optional status filter |
|
|
139
|
+
| `add_campaign_contacts` | Add contacts to a campaign by id or inline; needed before activation |
|
|
140
|
+
| `list_campaign_chats` | List iris chat sessions (the conversational campaign builder) |
|
|
141
|
+
| `get_campaign_chat_messages` | List the messages in a chat session, oldest first |
|
|
142
|
+
| `rename_campaign_chat` | Rename a chat session |
|
|
143
|
+
| `delete_campaign_chat` | Soft-delete a chat session |
|
|
139
144
|
| `get_campaign_usage` | Get usage limits and current counts for a campaign |
|
|
140
145
|
| `analyze_campaign` | Trigger AI analysis to generate target profiles |
|
|
141
146
|
| `list_target_profiles` | List target profiles for a campaign |
|
|
@@ -225,6 +230,7 @@ Add to `.cursor/mcp.json`:
|
|
|
225
230
|
| --------------------------- | ------------------------------------------------------- |
|
|
226
231
|
| `list_conversations` | List conversations with optional channel/status filters |
|
|
227
232
|
| `get_conversation` | Get a conversation by ID |
|
|
233
|
+
| `update_conversation` | Update a conversation's status (active, archived, closed) |
|
|
228
234
|
| `get_conversation_messages` | List messages in a conversation |
|
|
229
235
|
| `mark_conversation_read` | Mark a conversation as read |
|
|
230
236
|
| `get_engagement_metrics` | Get engagement metrics across conversations |
|
|
@@ -120,6 +120,93 @@ export function registerCampaignCommands(program, client) {
|
|
|
120
120
|
handleError(error);
|
|
121
121
|
}
|
|
122
122
|
});
|
|
123
|
+
campaigns
|
|
124
|
+
.command("contacts <id>")
|
|
125
|
+
.description("list the contacts in a campaign")
|
|
126
|
+
.option("-p, --page <n>", "page number", "1")
|
|
127
|
+
.option("-s, --page-size <n>", "items per page (max 100)", "50")
|
|
128
|
+
.option("--status <status>", "filter by contact status")
|
|
129
|
+
.action(async (id, opts) => {
|
|
130
|
+
try {
|
|
131
|
+
const params = {};
|
|
132
|
+
if (opts.page)
|
|
133
|
+
params.page = opts.page;
|
|
134
|
+
if (opts.pageSize)
|
|
135
|
+
params.page_size = opts.pageSize;
|
|
136
|
+
if (opts.status)
|
|
137
|
+
params.status = opts.status;
|
|
138
|
+
const result = await client.get(`/campaigns/${id}/contacts`, params);
|
|
139
|
+
formatOutput(result, getFormat(program.opts()));
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
handleError(error);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
campaigns
|
|
146
|
+
.command("add-contacts <id>")
|
|
147
|
+
.description("link existing contacts to a campaign (a campaign needs at least one before it can start)")
|
|
148
|
+
.requiredOption("--contact-ids <ids>", "comma-separated contact IDs to link")
|
|
149
|
+
.option("--no-deduplicate", "link even if already linked (default skips duplicates)")
|
|
150
|
+
.action(async (id, opts) => {
|
|
151
|
+
try {
|
|
152
|
+
const body = { contact_ids: parseList(opts.contactIds) };
|
|
153
|
+
if (opts.deduplicate === false)
|
|
154
|
+
body.deduplicate = false;
|
|
155
|
+
const result = await client.post(`/campaigns/${id}/contacts`, body);
|
|
156
|
+
formatOutput(result, getFormat(program.opts()));
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
handleError(error);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
campaigns
|
|
163
|
+
.command("chats")
|
|
164
|
+
.description("list iris chat sessions, most recently updated first")
|
|
165
|
+
.action(async () => {
|
|
166
|
+
try {
|
|
167
|
+
const result = await client.get("/campaigns/chats");
|
|
168
|
+
formatOutput(result, getFormat(program.opts()));
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
handleError(error);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
campaigns
|
|
175
|
+
.command("chat-messages <chat-id>")
|
|
176
|
+
.description("list the messages in a chat session, oldest first")
|
|
177
|
+
.action(async (chatId) => {
|
|
178
|
+
try {
|
|
179
|
+
const result = await client.get(`/campaigns/chats/${chatId}/messages`);
|
|
180
|
+
formatOutput(result, getFormat(program.opts()));
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
handleError(error);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
campaigns
|
|
187
|
+
.command("rename-chat <chat-id> <title>")
|
|
188
|
+
.description("rename a chat session")
|
|
189
|
+
.action(async (chatId, title) => {
|
|
190
|
+
try {
|
|
191
|
+
const result = await client.patch(`/campaigns/chats/${chatId}`, { title });
|
|
192
|
+
formatOutput(result, getFormat(program.opts()));
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
handleError(error);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
campaigns
|
|
199
|
+
.command("delete-chat <chat-id>")
|
|
200
|
+
.description("soft-delete a chat session")
|
|
201
|
+
.action(async (chatId) => {
|
|
202
|
+
try {
|
|
203
|
+
await client.delete(`/campaigns/chats/${chatId}`);
|
|
204
|
+
console.log("chat deleted");
|
|
205
|
+
}
|
|
206
|
+
catch (error) {
|
|
207
|
+
handleError(error);
|
|
208
|
+
}
|
|
209
|
+
});
|
|
123
210
|
const targetProfiles = campaigns
|
|
124
211
|
.command("target-profiles")
|
|
125
212
|
.alias("tp")
|
|
@@ -110,4 +110,17 @@ export function registerConversationCommands(program, client) {
|
|
|
110
110
|
handleError(error);
|
|
111
111
|
}
|
|
112
112
|
});
|
|
113
|
+
conversations
|
|
114
|
+
.command("update <id>")
|
|
115
|
+
.description("update a conversation's status")
|
|
116
|
+
.requiredOption("--status <status>", "one of: active, archived, closed")
|
|
117
|
+
.action(async (id, opts) => {
|
|
118
|
+
try {
|
|
119
|
+
const result = await client.patch(`/conversations/${id}`, { status: opts.status });
|
|
120
|
+
formatOutput(result, getFormat(program.opts()));
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
handleError(error);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
113
126
|
}
|
package/dist/tools/campaigns.js
CHANGED
|
@@ -115,6 +115,73 @@ export function registerCampaignTools(server, client) {
|
|
|
115
115
|
return formatMcpError(error);
|
|
116
116
|
}
|
|
117
117
|
});
|
|
118
|
+
server.tool("add_campaign_contacts", "add contacts to a campaign, by id or by creating them inline. a campaign needs at least one contact before it can be activated. requires write scope.", {
|
|
119
|
+
id: z.string().uuid().describe("campaign ID"),
|
|
120
|
+
contact_ids: z.array(z.string().uuid()).optional().describe("ids of existing contacts to link"),
|
|
121
|
+
contacts: z
|
|
122
|
+
.array(z.record(z.string(), z.unknown()))
|
|
123
|
+
.optional()
|
|
124
|
+
.describe("new contacts to create and link (same shape as create_contact)"),
|
|
125
|
+
deduplicate: z.boolean().optional().describe("skip contacts already linked (default true)"),
|
|
126
|
+
}, async ({ id, contact_ids, contacts, deduplicate }) => {
|
|
127
|
+
try {
|
|
128
|
+
const body = {};
|
|
129
|
+
if (contact_ids)
|
|
130
|
+
body.contact_ids = contact_ids;
|
|
131
|
+
if (contacts)
|
|
132
|
+
body.contacts = contacts;
|
|
133
|
+
if (deduplicate !== undefined)
|
|
134
|
+
body.deduplicate = deduplicate;
|
|
135
|
+
const result = await client.post(`/campaigns/${id}/contacts`, body);
|
|
136
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
return formatMcpError(error);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
server.tool("list_campaign_chats", "list your iris chat sessions (the conversational campaign builder), most recently updated first, max 100. the live chat turn itself is a server-sent-events stream outside this tool set. requires read scope.", {}, async () => {
|
|
143
|
+
try {
|
|
144
|
+
const result = await client.get("/campaigns/chats");
|
|
145
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
return formatMcpError(error);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
server.tool("get_campaign_chat_messages", "list the messages in a chat session, oldest first. `content` is an array of opaque blocks (text / tool_use / tool_result). requires read scope.", {
|
|
152
|
+
chat_id: z.string().uuid().describe("chat session ID"),
|
|
153
|
+
}, async ({ chat_id }) => {
|
|
154
|
+
try {
|
|
155
|
+
const result = await client.get(`/campaigns/chats/${chat_id}/messages`);
|
|
156
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
return formatMcpError(error);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
server.tool("rename_campaign_chat", "rename a chat session. requires write scope.", {
|
|
163
|
+
chat_id: z.string().uuid().describe("chat session ID"),
|
|
164
|
+
title: z.string().min(1).max(200).describe("new title"),
|
|
165
|
+
}, async ({ chat_id, title }) => {
|
|
166
|
+
try {
|
|
167
|
+
const result = await client.patch(`/campaigns/chats/${chat_id}`, { title });
|
|
168
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
return formatMcpError(error);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
server.tool("delete_campaign_chat", "soft-delete a chat session. requires write scope.", {
|
|
175
|
+
chat_id: z.string().uuid().describe("chat session ID"),
|
|
176
|
+
}, async ({ chat_id }) => {
|
|
177
|
+
try {
|
|
178
|
+
await client.delete(`/campaigns/chats/${chat_id}`);
|
|
179
|
+
return { content: [{ type: "text", text: `chat ${chat_id} deleted` }] };
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
return formatMcpError(error);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
118
185
|
server.tool("get_campaign_usage", "get usage limits and current counts for a campaign. requires read scope.", {
|
|
119
186
|
id: z.string().uuid().describe("campaign ID"),
|
|
120
187
|
}, async ({ id }) => {
|
|
@@ -106,6 +106,18 @@ export function registerConversationTools(server, client) {
|
|
|
106
106
|
return formatMcpError(error);
|
|
107
107
|
}
|
|
108
108
|
});
|
|
109
|
+
server.tool("update_conversation", "update a conversation's status: active, archived, or closed. requires write scope.", {
|
|
110
|
+
id: z.string().uuid().describe("conversation ID"),
|
|
111
|
+
status: z.enum(["active", "archived", "closed"]).describe("new conversation status"),
|
|
112
|
+
}, async ({ id, status }) => {
|
|
113
|
+
try {
|
|
114
|
+
const result = await client.patch(`/conversations/${id}`, { status });
|
|
115
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
return formatMcpError(error);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
109
121
|
server.tool("get_engagement_metrics", "get overall engagement metrics across all conversations. requires read scope.", {}, async () => {
|
|
110
122
|
try {
|
|
111
123
|
const result = await client.get("/conversations/engagement");
|
package/dist/tools/messages.js
CHANGED
|
@@ -56,7 +56,10 @@ export function registerMessageTools(server, client) {
|
|
|
56
56
|
}
|
|
57
57
|
});
|
|
58
58
|
server.tool("mark_message_sent", "mark a pending manual-channel draft (tiktok, or instagram cold first-touch) as sent outside the platform. API-sendable drafts must use approve_message instead. requires write scope.", {
|
|
59
|
-
id: z
|
|
59
|
+
id: z
|
|
60
|
+
.string()
|
|
61
|
+
.uuid()
|
|
62
|
+
.describe("approval queue item ID, or the message ID for drafts created via create_message (they have no approval item)"),
|
|
60
63
|
}, async ({ id }) => {
|
|
61
64
|
try {
|
|
62
65
|
const result = await client.post(`/messages/${id}/mark-sent`);
|
package/dist/types.d.ts
CHANGED
|
@@ -52,6 +52,29 @@ export interface CampaignUsage {
|
|
|
52
52
|
discovery_runs: number;
|
|
53
53
|
discovery_limit: number;
|
|
54
54
|
}
|
|
55
|
+
/** `POST /campaigns/{id}/contacts` */
|
|
56
|
+
export interface AddCampaignContactsResult {
|
|
57
|
+
added_count: number;
|
|
58
|
+
duplicates_count: number;
|
|
59
|
+
total_contacts: number;
|
|
60
|
+
}
|
|
61
|
+
/** `GET /campaigns/chats`, `PATCH /campaigns/chats/{id}` */
|
|
62
|
+
export interface CampaignChat {
|
|
63
|
+
id: string;
|
|
64
|
+
campaign_id: string | null;
|
|
65
|
+
title: string | null;
|
|
66
|
+
status: string;
|
|
67
|
+
created_at: string;
|
|
68
|
+
updated_at: string;
|
|
69
|
+
}
|
|
70
|
+
/** `GET /campaigns/chats/{id}/messages` — `content` is an opaque block array. */
|
|
71
|
+
export interface CampaignChatMessage {
|
|
72
|
+
id: string;
|
|
73
|
+
chat_id: string;
|
|
74
|
+
role: string;
|
|
75
|
+
content: unknown;
|
|
76
|
+
created_at: string;
|
|
77
|
+
}
|
|
55
78
|
export interface TargetProfile {
|
|
56
79
|
id: string;
|
|
57
80
|
campaign_id: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jclvsh/iris",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "MCP server for the Iris API",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/JCLVSH/monorepo.git",
|
|
8
|
+
"directory": "apps/iris/packages/mcp"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"main": "dist/index.js",
|
|
7
12
|
"types": "dist/index.d.ts",
|