@jclvsh/iris 0.2.3 → 0.2.4

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.
Files changed (3) hide show
  1. package/README.md +383 -46
  2. package/dist/cli.js +3 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,32 +1,108 @@
1
1
  # @jclvsh/iris
2
2
 
3
- MCP server for the [Iris](https://iris-ai.dev) API — AI-powered messaging assistant for automated multi-channel outreach campaigns.
3
+ MCP server and CLI for the [Iris](https://iris-ai.dev) API — AI-powered messaging assistant for automated multi-channel outreach campaigns. Lets AI agents (Claude Code, Cursor) and humans manage campaigns, contacts, conversations, AI generations, discovery, channels, and webhooks.
4
4
 
5
- ## Install
5
+ ## Installation
6
6
 
7
- The package ships two binaries: `iris-mcp` (the MCP server, used in MCP host configs below) and `iris` (the CLI, for terminal use). One-shot run:
7
+ ```bash
8
+ npm install -g @jclvsh/iris
9
+ ```
10
+
11
+ This installs two binaries:
12
+
13
+ - `iris` — CLI for terminal use
14
+ - `iris-mcp` — MCP server for AI agents
15
+
16
+ Or run one-shot without installing:
8
17
 
9
18
  ```bash
10
19
  npx -y -p @jclvsh/iris iris-mcp
11
20
  ```
12
21
 
13
- ## Configuration
22
+ ## CLI
23
+
24
+ ```bash
25
+ # set your API key
26
+ export IRIS_API_KEY=is_live_...
27
+
28
+ # manage campaigns
29
+ iris campaigns list
30
+ iris campaigns create -n "spring outreach" -o product_promotion --product-name "acme widgets"
31
+ iris campaigns analyze <id>
32
+ iris campaigns usage <id>
33
+
34
+ # manage contacts
35
+ iris contacts list --campaign-id <id>
36
+ iris contacts create --campaign-id <id> -e jane@example.com --full-name "Jane Doe" --company-name "Acme"
37
+
38
+ # review the AI approval queue
39
+ iris messages pending --campaign-id <id>
40
+ iris messages approve <id>
41
+ iris messages reject <id> --reason "off-topic"
42
+ iris messages bulk -a approve --ids id1,id2,id3
43
+
44
+ # manage webhooks
45
+ iris webhooks create -u https://example.com/hook -e campaign.created,message.delivered
46
+ iris webhooks test <id>
47
+ iris webhooks deliveries <id>
48
+
49
+ # check your key
50
+ iris keys me
51
+
52
+ # table output
53
+ iris --format table campaigns list
54
+
55
+ # full help
56
+ iris --help
57
+ iris campaigns --help
58
+ ```
59
+
60
+ ### CLI Commands
61
+
62
+ | Group | Alias | Commands | Count |
63
+ | --- | --- | --- | --- |
64
+ | campaigns | `c` | list, get, create, update, delete, usage, analyze | 7 |
65
+ | contacts | `ct` | list, get, create, update, delete, usage | 6 |
66
+ | messages | `m` | pending, approve, reject, retry, feedback, bulk | 6 |
67
+ | conversations | `conv` | list, get, messages, read | 4 |
68
+ | discovery | `d` | search, search-campaign, sources, job | 4 |
69
+ | ai | — | generate, generate-campaign, analyze, usage, suggestions | 5 |
70
+ | keys | `k` | me, list, create, rename, revoke | 5 |
71
+ | webhooks | `w` | list, create, get, update, delete, test, deliveries | 7 |
72
+ | notifications | `n` | list, update, delete, read-all | 4 |
73
+ | analytics | `a` | overview, campaign, performance, response-time, contact-types | 5 |
74
+ | billing | `b` | plans | 1 |
75
+ | channels | `ch` | accounts, availability, send | 3 |
76
+ | credits | `cr` | balance, buy | 2 |
77
+
78
+ ## MCP Server Configuration
79
+
80
+ ### Environment Variables
81
+
82
+ | Variable | Required | Description |
83
+ | --- | --- | --- |
84
+ | `IRIS_API_KEY` | Yes | API key (must start with `is_live_`) |
85
+ | `IRIS_API_URL` | No | API base URL (default: `https://iris-ai.dev/api/v1`) |
86
+
87
+ > **Note:** the args use `-p @jclvsh/iris iris-mcp` to explicitly select the MCP-server bin. The package ships two binaries (`iris` for the CLI, `iris-mcp` for the MCP server), so a bare `npx @jclvsh/iris` would launch the CLI by default.
88
+
89
+ Get your API key at [iris-ai.dev/settings/api-keys](https://iris-ai.dev/settings/api-keys).
14
90
 
15
91
  ### Claude Code
16
92
 
17
- Add to your Claude Code settings:
93
+ Add to your `.claude/settings.json`:
18
94
 
19
95
  ```json
20
96
  {
21
- "mcpServers": {
22
- "iris": {
23
- "command": "npx",
24
- "args": ["-y", "-p", "@jclvsh/iris", "iris-mcp"],
25
- "env": {
26
- "IRIS_API_KEY": "is_live_..."
27
- }
28
- }
29
- }
97
+ "mcpServers": {
98
+ "iris": {
99
+ "command": "npx",
100
+ "args": ["-y", "-p", "@jclvsh/iris", "iris-mcp"],
101
+ "env": {
102
+ "IRIS_API_KEY": "is_live_your_key_here"
103
+ }
104
+ }
105
+ }
30
106
  }
31
107
  ```
32
108
 
@@ -36,45 +112,306 @@ Add to `.cursor/mcp.json`:
36
112
 
37
113
  ```json
38
114
  {
39
- "mcpServers": {
40
- "iris": {
41
- "command": "npx",
42
- "args": ["-y", "-p", "@jclvsh/iris", "iris-mcp"],
43
- "env": {
44
- "IRIS_API_KEY": "is_live_..."
45
- }
46
- }
47
- }
115
+ "mcpServers": {
116
+ "iris": {
117
+ "command": "npx",
118
+ "args": ["-y", "-p", "@jclvsh/iris", "iris-mcp"],
119
+ "env": {
120
+ "IRIS_API_KEY": "is_live_your_key_here"
121
+ }
122
+ }
123
+ }
48
124
  }
49
125
  ```
50
126
 
51
- ## Environment Variables
127
+ ## Available Tools
52
128
 
53
- | Variable | Required | Description |
54
- |----------|----------|-------------|
55
- | `IRIS_API_KEY` | Yes | API key (must start with `is_live_`) |
56
- | `IRIS_API_URL` | No | Base URL (default: `https://iris-ai.dev/api/v1`) |
129
+ ### Campaigns
57
130
 
58
- Get your API key at [iris-ai.dev/settings/api-keys](https://iris-ai.dev/settings/api-keys).
131
+ | Tool | Description |
132
+ | --- | --- |
133
+ | `list_campaigns` | List campaigns with optional status filter |
134
+ | `create_campaign` | Create a new outreach campaign |
135
+ | `get_campaign` | Get a campaign by ID with stats |
136
+ | `update_campaign` | Update a campaign's name, status, or follow-up settings |
137
+ | `delete_campaign` | Soft-delete a campaign (sets status to `deleted`) |
138
+ | `list_campaign_contacts` | List contacts in a campaign with optional status filter |
139
+ | `get_campaign_usage` | Get usage limits and current counts for a campaign |
140
+ | `analyze_campaign` | Trigger AI analysis to generate target profiles |
141
+ | `list_target_profiles` | List target profiles for a campaign |
142
+ | `create_target_profile` | Create a target profile for a campaign |
143
+ | `delete_target_profile` | Delete a target profile from a campaign |
59
144
 
60
- ## Available Tools
145
+ #### `create_campaign` Parameters
146
+
147
+ | Parameter | Type | Required | Description |
148
+ | --- | --- | --- | --- |
149
+ | `name` | string (1-100) | Yes | Campaign name |
150
+ | `objective_type` | enum | Yes | `venue_dj`, `venue_host`, `product_promotion`, `custom` |
151
+ | `product_name` | string (≤200) | No | Product name (for `product_promotion`) |
152
+ | `product_url` | string (URL) | No | Product URL (for `product_promotion`) |
153
+ | `product_description` | string (≤2000) | No | Product description (for `product_promotion`) |
154
+
155
+ #### `update_campaign` Parameters
156
+
157
+ | Parameter | Type | Required | Description |
158
+ | --- | --- | --- | --- |
159
+ | `id` | string (UUID) | Yes | Campaign ID |
160
+ | `name` | string (1-100) | No | New campaign name |
161
+ | `status` | enum | No | `draft`, `active`, `paused`, `completed`, `deleted` |
162
+ | `follow_up_enabled` | boolean | No | Enable follow-up emails |
163
+ | `follow_up_max_count` | number (0-10) | No | Max follow-up count |
164
+ | `follow_up_delay_days` | number (1-30) | No | Days between follow-ups |
165
+
166
+ #### `create_target_profile` Parameters
167
+
168
+ | Parameter | Type | Required | Description |
169
+ | --- | --- | --- | --- |
170
+ | `id` | string (UUID) | Yes | Campaign ID |
171
+ | `name` | string (1-200) | Yes | Profile name |
172
+ | `profile_type` | enum | Yes | `local_business`, `content_creator`, `influencer`, `b2b_professional`, `ecommerce`, `saas_company`, `agency`, `freelancer`, `other` |
173
+ | `job_titles` | string[] | No | Target job titles |
174
+ | `industries` | string[] | No | Target industries |
175
+ | `discovery_keywords` | string[] | No | Keywords for contact discovery |
176
+ | `recommended_channels` | string[] | No | `email`, `instagram`, `twitter`, `linkedin` |
177
+
178
+ ### Contacts
179
+
180
+ | Tool | Description |
181
+ | --- | --- |
182
+ | `list_contacts` | List contacts with search |
183
+ | `create_contact` | Create a new contact |
184
+ | `get_contact` | Get a contact by ID |
185
+ | `update_contact` | Update a contact's details |
186
+ | `delete_contact` | Soft-delete a contact |
187
+ | `bulk_import_contacts` | Import up to 500 contacts at once |
188
+ | `get_contact_usage` | Get usage limits for the billing period |
189
+ | `list_contact_conversations` | List conversations for a specific contact |
190
+
191
+ #### `create_contact` Parameters
192
+
193
+ | Parameter | Type | Required | Description |
194
+ | --- | --- | --- | --- |
195
+ | `email` | string (email) | Yes | Contact email address |
196
+ | `first_name` | string (≤100) | No | First name |
197
+ | `last_name` | string (≤100) | No | Last name |
198
+ | `company_name` | string (≤200) | No | Company name |
199
+ | `job_title` | string (≤200) | No | Job title |
200
+ | `phone` | string (≤50) | No | Phone number |
201
+ | `website` | string (URL) | No | Website URL |
202
+ | `tags` | string[] | No | Tags for categorization |
203
+
204
+ #### `bulk_import_contacts` Parameters
205
+
206
+ | Parameter | Type | Required | Description |
207
+ | --- | --- | --- | --- |
208
+ | `contacts` | object[] (1-500) | Yes | Array of contacts (`email`, `first_name?`, `last_name?`, `company_name?`, `job_title?`, `tags?`) |
209
+ | `campaign_id` | string (UUID) | No | Campaign to add contacts to |
210
+
211
+ ### Messages
212
+
213
+ | Tool | Description |
214
+ | --- | --- |
215
+ | `list_pending_messages` | List messages pending approval |
216
+ | `approve_message` | Approve a single pending message |
217
+ | `reject_message` | Reject a single pending message |
218
+ | `retry_message` | Retry a failed message send |
219
+ | `submit_message_feedback` | Submit feedback to improve future AI generations |
220
+ | `bulk_message_action` | Bulk approve or reject pending messages |
61
221
 
62
- | Category | Tools |
63
- |----------|-------|
64
- | Campaigns | list, create, get, update, delete, contacts, usage, analyze, target profiles |
65
- | Contacts | list, create, get, update, delete, bulk import, usage, conversations |
66
- | Conversations | list, get, messages, mark read, engagement metrics |
67
- | Messages | list pending, approve, reject, retry, feedback, bulk action |
68
- | AI | generate content, campaign content, analyze response, usage, suggestions |
69
- | Discovery | search contacts, campaign search, job status, sources |
70
- | Analytics | overview, campaign analytics, performance, response time, contact types |
71
- | Billing | plans |
72
- | Channels | connected accounts, availability, send message |
73
- | Notifications | list, update, delete, mark all read |
74
- | API Keys | current key, list, create, revoke |
75
- | Webhooks | list, create, get, update, delete, test, deliveries |
76
- | Agent Credits | balance, purchase pack (x402/MPP only) |
222
+ ### Conversations
223
+
224
+ | Tool | Description |
225
+ | --- | --- |
226
+ | `list_conversations` | List conversations with optional channel/status filters |
227
+ | `get_conversation` | Get a conversation by ID |
228
+ | `get_conversation_messages` | List messages in a conversation |
229
+ | `mark_conversation_read` | Mark a conversation as read |
230
+ | `get_engagement_metrics` | Get engagement metrics across conversations |
231
+
232
+ ### AI
233
+
234
+ | Tool | Description |
235
+ | --- | --- |
236
+ | `generate_content` | Generate AI content for a contact conversation (initial email, follow-up, reply) |
237
+ | `generate_campaign_content` | Generate campaign-level content (email templates, subject lines, briefs) |
238
+ | `analyze_response` | Analyze inbound message sentiment, intent, and suggested action |
239
+ | `get_ai_usage` | Get AI generation usage limits |
240
+ | `get_ai_suggestions` | Get AI-powered suggestions for a conversation |
241
+
242
+ #### `generate_content` Parameters
243
+
244
+ | Parameter | Type | Required | Description |
245
+ | --- | --- | --- | --- |
246
+ | `contact_id` | string (UUID) | Yes | Contact ID |
247
+ | `conversation_id` | string (UUID) | Yes | Conversation ID |
248
+ | `generation_type` | enum | Yes | `initial_email`, `follow_up`, `reply` |
249
+ | `context` | string (≤2000) | No | Additional context for the AI |
250
+
251
+ ### Discovery
252
+
253
+ | Tool | Description |
254
+ | --- | --- |
255
+ | `search_contacts` | Search for contacts by criteria (location, keywords, sources) |
256
+ | `search_campaign_contacts` | Run discovery scoped to a campaign's target profiles |
257
+ | `get_discovery_job` | Get the status of a discovery job |
258
+ | `list_discovery_sources` | List available discovery sources (Google Maps, social) |
259
+
260
+ ### Channels
261
+
262
+ | Tool | Description |
263
+ | --- | --- |
264
+ | `list_connected_accounts` | List your connected social accounts (Twitter, Instagram, LinkedIn) |
265
+ | `check_channel_availability` | Check which channels are reachable for a contact |
266
+ | `send_channel_message` | Send a message via a specific channel |
267
+
268
+ ### Analytics
269
+
270
+ | Tool | Description |
271
+ | --- | --- |
272
+ | `get_analytics_overview` | Account-level analytics overview |
273
+ | `get_campaign_analytics` | Per-campaign performance metrics |
274
+ | `get_performance_metrics` | Aggregate performance across campaigns |
275
+ | `get_response_time` | Response time distribution |
276
+ | `get_contact_types` | Engagement broken down by contact type |
277
+
278
+ ### Notifications
279
+
280
+ | Tool | Description |
281
+ | --- | --- |
282
+ | `list_notifications` | List your notifications |
283
+ | `update_notification` | Mark a notification as read or update its state |
284
+ | `delete_notification` | Delete a notification |
285
+ | `mark_all_notifications_read` | Mark every unread notification as read |
286
+
287
+ ### Billing
288
+
289
+ | Tool | Description |
290
+ | --- | --- |
291
+ | `get_billing_plans` | List available subscription plans |
292
+
293
+ ### API Keys
294
+
295
+ | Tool | Description |
296
+ | --- | --- |
297
+ | `get_current_api_key` | Get details about the currently authenticated key |
298
+ | `list_api_keys` | List all API keys for the account |
299
+ | `create_api_key` | Create a new API key (raw key returned once) |
300
+ | `revoke_api_key` | Revoke (delete) an API key |
301
+
302
+ #### `create_api_key` Parameters
303
+
304
+ | Parameter | Type | Required | Description |
305
+ | --- | --- | --- | --- |
306
+ | `name` | string (1-100) | Yes | Key name for identification |
307
+ | `scopes` | string[] | No | Permission scopes (defaults to all scopes) — see [Scopes](#api-key--scopes) |
308
+ | `expires_at` | string (ISO 8601) | No | Expiration date |
309
+
310
+ ### Webhooks
311
+
312
+ | Tool | Description |
313
+ | --- | --- |
314
+ | `list_webhooks` | List all configured webhooks |
315
+ | `create_webhook` | Create a new webhook endpoint |
316
+ | `get_webhook` | Get a webhook by ID |
317
+ | `update_webhook` | Update a webhook's URL, events, or active status |
318
+ | `delete_webhook` | Delete a webhook |
319
+ | `test_webhook` | Send a test event to a webhook URL |
320
+ | `rotate_webhook_secret` | Rotate the signing secret (new secret returned once) |
321
+ | `list_webhook_deliveries` | List delivery history for a webhook |
322
+
323
+ #### `create_webhook` Parameters
324
+
325
+ | Parameter | Type | Required | Description |
326
+ | --- | --- | --- | --- |
327
+ | `url` | string (HTTPS URL) | Yes | Webhook endpoint URL — HTTPS only |
328
+ | `events` | string[] (≥1) | Yes | Events to subscribe to — see [Webhook Events](#webhook-events) |
329
+ | `description` | string (≤500) | No | Webhook description |
330
+
331
+ #### `update_webhook` Parameters
332
+
333
+ | Parameter | Type | Required | Description |
334
+ | --- | --- | --- | --- |
335
+ | `id` | string (UUID) | Yes | Webhook ID |
336
+ | `url` | string (HTTPS URL) | No | New endpoint URL |
337
+ | `events` | string[] (≥1) | No | New events to subscribe to |
338
+ | `active` | boolean | No | Enable or disable the webhook |
339
+
340
+ ### Agent Credits
341
+
342
+ > Credits apply only to agents authenticating via x402 (USDC on Base) or MPP (Stripe). API key users do not need credits.
343
+
344
+ | Tool | Description |
345
+ | --- | --- |
346
+ | `get_credit_balance` | Check the agent credit balance |
347
+ | `purchase_credit_pack` | Purchase a 5-credit pack via MPP ($12.00) |
348
+
349
+ ## API Key & Scopes
350
+
351
+ Generate an API key at [iris-ai.dev/settings/api-keys](https://iris-ai.dev/settings/api-keys).
352
+
353
+ API keys support fine-grained scopes per resource:
354
+
355
+ | Scope | Access |
356
+ | --- | --- |
357
+ | `campaigns:read` / `campaigns:write` | Read or modify campaigns |
358
+ | `contacts:read` / `contacts:write` | Read or modify contacts |
359
+ | `conversations:read` / `conversations:write` | Read conversations or send messages |
360
+ | `messages:read` / `messages:write` | Read the queue, approve/reject/send |
361
+ | `ai:read` / `ai:write` | Read AI usage or trigger generations |
362
+ | `discovery:read` / `discovery:write` | Read sources or run discovery jobs |
363
+ | `analytics:read` | Read analytics dashboards |
364
+ | `billing:read` | Read billing plans |
365
+ | `channels:read` / `channels:write` | Read connected accounts or send via channels |
366
+ | `notifications:read` / `notifications:write` | Read or modify notifications |
367
+ | `webhooks:read` / `webhooks:write` | Read or manage webhook subscriptions |
368
+ | `keys:read` / `keys:write` | Read or manage API keys |
369
+
370
+ ### Recommended Scopes by Use Case
371
+
372
+ | Use Case | Recommended Scopes |
373
+ | --- | --- |
374
+ | AI agents / MCP | `campaigns:read`, `campaigns:write`, `contacts:read`, `contacts:write`, `messages:read`, `messages:write`, `ai:read`, `ai:write`, `conversations:read`, `conversations:write` |
375
+ | Read-only monitoring | `*:read` scopes only |
376
+ | Webhook management | `webhooks:read`, `webhooks:write` |
377
+ | Discovery automation | `discovery:read`, `discovery:write`, `contacts:write`, `campaigns:read` |
378
+
379
+ ## Webhook Events
380
+
381
+ | Event | Description |
382
+ | --- | --- |
383
+ | `campaign.created` | New campaign created |
384
+ | `campaign.updated` | Campaign details changed |
385
+ | `campaign.deleted` | Campaign soft-deleted |
386
+ | `contact.created` | New contact added |
387
+ | `contact.updated` | Contact details changed |
388
+ | `contact.deleted` | Contact soft-deleted |
389
+ | `conversation.created` | New conversation started |
390
+ | `conversation.reply_received` | Inbound reply received |
391
+ | `message.sent` | Outbound message sent |
392
+ | `message.delivered` | Message confirmed delivered |
393
+ | `message.opened` | Email opened (filtered for bots) |
394
+ | `message.bounced` | Message bounced |
395
+ | `message.approved` | Message approved in the queue |
396
+ | `message.rejected` | Message rejected in the queue |
397
+ | `discovery.completed` | Discovery job finished successfully |
398
+ | `discovery.failed` | Discovery job failed |
399
+
400
+ Webhook deliveries are signed with HMAC-SHA256 using the secret returned from `create_webhook` / `rotate_webhook_secret`. Verify the signature in the `X-Iris-Signature` header before trusting the payload.
77
401
 
78
402
  ## Documentation
79
403
 
80
- Full API documentation: [iris-ai.dev/docs](https://iris-ai.dev/docs)
404
+ Full API reference: [iris-ai.dev/docs](https://iris-ai.dev/docs)
405
+
406
+ ## Development
407
+
408
+ ```bash
409
+ # install dependencies
410
+ npm install
411
+
412
+ # build
413
+ npm run build
414
+
415
+ # run the MCP server
416
+ IRIS_API_KEY=is_live_... npm start
417
+ ```
package/dist/cli.js CHANGED
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  import { Command } from "commander";
3
4
  import { IrisClient } from "./client.js";
4
5
  import { handleError } from "./cli-utils.js";
6
+ const pkg = createRequire(import.meta.url)("../package.json");
5
7
  import { registerCampaignCommands } from "./commands/campaigns.js";
6
8
  import { registerContactCommands } from "./commands/contacts.js";
7
9
  import { registerMessageCommands } from "./commands/messages.js";
@@ -18,7 +20,7 @@ import { registerCreditCommands } from "./commands/credits.js";
18
20
  const program = new Command()
19
21
  .name("iris")
20
22
  .description("iris CLI - manage campaigns, contacts, messages, and outreach")
21
- .version("0.2.0")
23
+ .version(pkg.version)
22
24
  .option("--json", "output as JSON (default)")
23
25
  .option("--format <fmt>", "output format: json, table", "json");
24
26
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jclvsh/iris",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "MCP server for the Iris API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",