@hyperstar/mcp 0.1.9 → 0.1.11
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 +52 -34
- package/dist/auth/cli-auth-client.js +0 -1
- package/dist/auth/cli-auth-state.js +0 -1
- package/dist/auth/local-callback.js +0 -1
- package/dist/auth/pkce.js +0 -1
- package/dist/bulk-email-guidance.js +0 -1
- package/dist/bulk-email-inputs.d.ts +254 -0
- package/dist/bulk-email-inputs.js +168 -0
- package/dist/bulk-email-tool-body.d.ts +6 -0
- package/dist/bulk-email-tool-body.js +37 -0
- package/dist/campaign-creator-selection.js +0 -1
- package/dist/cli.js +2 -2
- package/dist/config.js +15 -2
- package/dist/discovery.js +0 -1
- package/dist/http.js +0 -1
- package/dist/index.js +0 -1
- package/dist/package-metadata.d.ts +2 -0
- package/dist/package-metadata.js +12 -0
- package/dist/schemas.js +0 -1
- package/dist/search-result-projection.d.ts +3 -1
- package/dist/search-result-projection.js +33 -3
- package/dist/server.js +5 -2
- package/dist/tool-descriptions.d.ts +4 -4
- package/dist/tool-descriptions.js +4 -5
- package/dist/tool-guidance.js +24 -7
- package/dist/tool-http-helpers.js +0 -1
- package/dist/tool-inputs.d.ts +324 -131
- package/dist/tool-inputs.js +87 -92
- package/dist/tool-result.js +0 -1
- package/dist/tools.js +11 -31
- package/dist/workflow-content.d.ts +1 -0
- package/dist/workflow-content.js +19 -3
- package/dist/workspaces.d.ts +1 -1
- package/dist/workspaces.js +9 -2
- package/package.json +24 -2
- package/dist/auth/cli-auth-client.js.map +0 -1
- package/dist/auth/cli-auth-state.js.map +0 -1
- package/dist/auth/local-callback.js.map +0 -1
- package/dist/auth/pkce.js.map +0 -1
- package/dist/bulk-email-guidance.js.map +0 -1
- package/dist/campaign-creator-selection.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/discovery.js.map +0 -1
- package/dist/http.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/schemas.js.map +0 -1
- package/dist/search-result-projection.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/tool-descriptions.js.map +0 -1
- package/dist/tool-guidance.js.map +0 -1
- package/dist/tool-http-helpers.js.map +0 -1
- package/dist/tool-inputs.js.map +0 -1
- package/dist/tool-result.js.map +0 -1
- package/dist/tools.js.map +0 -1
- package/dist/workflow-content.js.map +0 -1
- package/dist/workspaces.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ CLI login.
|
|
|
7
7
|
|
|
8
8
|
## Install
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Run the MCP server directly from npm:
|
|
11
11
|
|
|
12
12
|
```sh
|
|
13
13
|
npx -y --package @hyperstar/mcp hyperstar-mcp
|
|
@@ -37,16 +37,16 @@ npx -y --package @hyperstar/mcp hyperstar workspaces list --json
|
|
|
37
37
|
npx -y --package @hyperstar/mcp hyperstar workspaces use org_123
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
For unreleased local package testing, pack from the package directory and use
|
|
41
|
+
the filename printed by `npm pack`:
|
|
41
42
|
|
|
42
43
|
```sh
|
|
43
44
|
cd projects/hyperstar-mcp
|
|
44
|
-
npm pack --
|
|
45
|
-
|
|
46
|
-
npx -y --package
|
|
47
|
-
npx -y --package
|
|
48
|
-
npx -y --package
|
|
49
|
-
npx -y --package ./hyperstar-mcp-0.1.0.tgz hyperstar workspaces use org_123
|
|
45
|
+
TARBALL=$(npm pack --silent)
|
|
46
|
+
npx -y --package "./$TARBALL" hyperstar-mcp
|
|
47
|
+
npx -y --package "./$TARBALL" hyperstar login
|
|
48
|
+
npx -y --package "./$TARBALL" hyperstar workspaces list --json
|
|
49
|
+
npx -y --package "./$TARBALL" hyperstar workspaces use org_123
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
The first public scoped publish must use public access. This package sets
|
|
@@ -55,8 +55,9 @@ credentials are configured.
|
|
|
55
55
|
|
|
56
56
|
## MCP client config
|
|
57
57
|
|
|
58
|
-
Service-account auth is the simplest non-interactive setup.
|
|
59
|
-
|
|
58
|
+
Service-account auth is the simplest non-interactive setup. For production,
|
|
59
|
+
configure only the service-account API key and use the package's default
|
|
60
|
+
Hyperstar Product API base URL:
|
|
60
61
|
|
|
61
62
|
```json
|
|
62
63
|
{
|
|
@@ -65,7 +66,6 @@ server with a Hyperstar Product API base URL and service-account API key:
|
|
|
65
66
|
"command": "npx",
|
|
66
67
|
"args": ["-y", "--package", "@hyperstar/mcp", "hyperstar-mcp"],
|
|
67
68
|
"env": {
|
|
68
|
-
"HYPERSTAR_API_BASE_URL": "https://api.hyperstar.example",
|
|
69
69
|
"HYPERSTAR_API_KEY": "hstar_test_public-prefix.secret"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -85,11 +85,7 @@ login state created by the `hyperstar` CLI:
|
|
|
85
85
|
"mcpServers": {
|
|
86
86
|
"hyperstar": {
|
|
87
87
|
"command": "npx",
|
|
88
|
-
"args": ["-y", "--package", "@hyperstar/mcp", "hyperstar-mcp"]
|
|
89
|
-
"env": {
|
|
90
|
-
"HYPERSTAR_API_BASE_URL": "https://api.hyperstar.example",
|
|
91
|
-
"HYPERSTAR_APP_BASE_URL": "https://app.hyperstar.example"
|
|
92
|
-
}
|
|
88
|
+
"args": ["-y", "--package", "@hyperstar/mcp", "hyperstar-mcp"]
|
|
93
89
|
}
|
|
94
90
|
}
|
|
95
91
|
}
|
|
@@ -152,21 +148,6 @@ npm test
|
|
|
152
148
|
npm run build
|
|
153
149
|
```
|
|
154
150
|
|
|
155
|
-
Internal MCP smoke testing requires an approved fixture supplied through local
|
|
156
|
-
environment variables:
|
|
157
|
-
|
|
158
|
-
```sh
|
|
159
|
-
HYPERSTAR_API_BASE_URL=<internal-api-url> \
|
|
160
|
-
HYPERSTAR_APP_BASE_URL=<internal-app-url> \
|
|
161
|
-
HYPERSTAR_MCP_SMOKE_INTERNAL_FIXTURE=1 \
|
|
162
|
-
HYPERSTAR_MCP_SMOKE_CAMPAIGN_ID=<campaign_id> \
|
|
163
|
-
HYPERSTAR_MCP_SMOKE_CAMPAIGN_NAME=<campaign_name> \
|
|
164
|
-
HYPERSTAR_MCP_SMOKE_RECIPIENT_ID=<campaign_creator_id> \
|
|
165
|
-
npm run smoke:dev
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
To include the real-send check, add `HYPERSTAR_MCP_SMOKE_REAL_SEND=1`.
|
|
169
|
-
|
|
170
151
|
## Examples
|
|
171
152
|
|
|
172
153
|
Search creators:
|
|
@@ -184,6 +165,16 @@ Search creators:
|
|
|
184
165
|
}
|
|
185
166
|
```
|
|
186
167
|
|
|
168
|
+
Common search filters are supplied as a structured JSON object. Useful fields
|
|
169
|
+
include `follower_range` as `{ "min": 1000, "max": 100000 }`,
|
|
170
|
+
`avg_engagement_rate`, `avg_views`, `has_email`, `email_contactability`,
|
|
171
|
+
`is_verified`, `has_tiktok_shop`, `creator_gender`, `creator_language`,
|
|
172
|
+
`category_1`, Instagram `category_name`, `gmv`, and `gpm`; `gmv` and `gpm` are
|
|
173
|
+
TikTok-only. Put broad niches and countries in `query` / `region` unless a
|
|
174
|
+
named structured filter applies. Use `sort_by` for `relevance`,
|
|
175
|
+
`follower_count`, `engagement_rate`, `avg_views`, `views_growth_rate`, `gmv`, or
|
|
176
|
+
`gpm`.
|
|
177
|
+
|
|
187
178
|
Search tools return compact creator summaries by default so agents do not load
|
|
188
179
|
full profile payloads into context. Use `get_search_results` with
|
|
189
180
|
`detail_level: "full"` only when a page of raw creator rows is explicitly
|
|
@@ -228,9 +219,32 @@ Save search results to a campaign roster:
|
|
|
228
219
|
}
|
|
229
220
|
```
|
|
230
221
|
|
|
222
|
+
Check recipient readiness before any bulk send:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"tool": "check_bulk_email_readiness",
|
|
227
|
+
"arguments": {
|
|
228
|
+
"campaign_id": 123,
|
|
229
|
+
"recipient_target": {
|
|
230
|
+
"type": "ids",
|
|
231
|
+
"campaign_creator_ids": [7, 8]
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
For filtered campaign roster sends, use `recipient_target.type: "selection"`
|
|
238
|
+
and pass `campaign_creator_selection`. The selection must include at least one
|
|
239
|
+
narrowing filter such as `workflow_filter: "email_not_sent"`, `platform`,
|
|
240
|
+
`source_type`, `search`, or `has_video`; empty selections,
|
|
241
|
+
`workflow_filter: "all"` by itself, and exclusions-only selections are
|
|
242
|
+
rejected.
|
|
243
|
+
|
|
231
244
|
Start a bulk email job. This performs a real send. The response includes the
|
|
232
245
|
queued job fields plus `next_tool: "get_bulk_email_job"` and `next_arguments`
|
|
233
|
-
so agents know how to check progress
|
|
246
|
+
so agents know how to check progress. Only call this after readiness has passed
|
|
247
|
+
and the user has authorized the send:
|
|
234
248
|
|
|
235
249
|
```json
|
|
236
250
|
{
|
|
@@ -239,8 +253,12 @@ so agents know how to check progress:
|
|
|
239
253
|
"campaign_id": 123,
|
|
240
254
|
"subject": "Partnership idea",
|
|
241
255
|
"body_text": "Hi, we would like to introduce our new campaign.",
|
|
242
|
-
"
|
|
243
|
-
|
|
256
|
+
"recipient_target": {
|
|
257
|
+
"type": "ids",
|
|
258
|
+
"campaign_creator_ids": [7, 8]
|
|
259
|
+
},
|
|
260
|
+
"idempotency_key": "campaign-123-intro-2026-07-09",
|
|
261
|
+
"send_confirmation": "user_authorized"
|
|
244
262
|
}
|
|
245
263
|
}
|
|
246
264
|
```
|
package/dist/auth/pkce.js
CHANGED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const EmailSubjectSchema: z.ZodString;
|
|
3
|
+
export declare const IdempotencyKeySchema: z.ZodString;
|
|
4
|
+
declare const CampaignCreatorSelectionSchema: z.ZodObject<{
|
|
5
|
+
workflow_filter: z.ZodOptional<z.ZodEnum<{
|
|
6
|
+
all: "all";
|
|
7
|
+
email: "email";
|
|
8
|
+
email_not_sent: "email_not_sent";
|
|
9
|
+
email_sent: "email_sent";
|
|
10
|
+
replied: "replied";
|
|
11
|
+
negotiating: "negotiating";
|
|
12
|
+
rejected_hold: "rejected_hold";
|
|
13
|
+
rejected: "rejected";
|
|
14
|
+
hold: "hold";
|
|
15
|
+
contract: "contract";
|
|
16
|
+
contracted: "contracted";
|
|
17
|
+
content: "content";
|
|
18
|
+
draft: "draft";
|
|
19
|
+
final_approved: "final_approved";
|
|
20
|
+
posted: "posted";
|
|
21
|
+
}>>;
|
|
22
|
+
outreach_stage: z.ZodOptional<z.ZodString>;
|
|
23
|
+
platform: z.ZodOptional<z.ZodEnum<{
|
|
24
|
+
tiktok: "tiktok";
|
|
25
|
+
instagram: "instagram";
|
|
26
|
+
}>>;
|
|
27
|
+
country: z.ZodOptional<z.ZodString>;
|
|
28
|
+
has_video: z.ZodOptional<z.ZodBoolean>;
|
|
29
|
+
source_type: z.ZodOptional<z.ZodEnum<{
|
|
30
|
+
saved_list: "saved_list";
|
|
31
|
+
file_upload: "file_upload";
|
|
32
|
+
manual_add: "manual_add";
|
|
33
|
+
form_submission: "form_submission";
|
|
34
|
+
discovery_search: "discovery_search";
|
|
35
|
+
}>>;
|
|
36
|
+
search: z.ZodOptional<z.ZodString>;
|
|
37
|
+
excluded_ids: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
38
|
+
}, z.core.$strict>;
|
|
39
|
+
export type CampaignCreatorSelectionInput = z.infer<typeof CampaignCreatorSelectionSchema>;
|
|
40
|
+
export declare const CheckBulkEmailReadinessInputSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
41
|
+
campaign_id: z.ZodNumber;
|
|
42
|
+
campaign_creator_ids: z.ZodArray<z.ZodNumber>;
|
|
43
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
44
|
+
campaign_id: z.ZodNumber;
|
|
45
|
+
campaign_creator_selection: z.ZodObject<{
|
|
46
|
+
workflow_filter: z.ZodOptional<z.ZodEnum<{
|
|
47
|
+
all: "all";
|
|
48
|
+
email: "email";
|
|
49
|
+
email_not_sent: "email_not_sent";
|
|
50
|
+
email_sent: "email_sent";
|
|
51
|
+
replied: "replied";
|
|
52
|
+
negotiating: "negotiating";
|
|
53
|
+
rejected_hold: "rejected_hold";
|
|
54
|
+
rejected: "rejected";
|
|
55
|
+
hold: "hold";
|
|
56
|
+
contract: "contract";
|
|
57
|
+
contracted: "contracted";
|
|
58
|
+
content: "content";
|
|
59
|
+
draft: "draft";
|
|
60
|
+
final_approved: "final_approved";
|
|
61
|
+
posted: "posted";
|
|
62
|
+
}>>;
|
|
63
|
+
outreach_stage: z.ZodOptional<z.ZodString>;
|
|
64
|
+
platform: z.ZodOptional<z.ZodEnum<{
|
|
65
|
+
tiktok: "tiktok";
|
|
66
|
+
instagram: "instagram";
|
|
67
|
+
}>>;
|
|
68
|
+
country: z.ZodOptional<z.ZodString>;
|
|
69
|
+
has_video: z.ZodOptional<z.ZodBoolean>;
|
|
70
|
+
source_type: z.ZodOptional<z.ZodEnum<{
|
|
71
|
+
saved_list: "saved_list";
|
|
72
|
+
file_upload: "file_upload";
|
|
73
|
+
manual_add: "manual_add";
|
|
74
|
+
form_submission: "form_submission";
|
|
75
|
+
discovery_search: "discovery_search";
|
|
76
|
+
}>>;
|
|
77
|
+
search: z.ZodOptional<z.ZodString>;
|
|
78
|
+
excluded_ids: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
79
|
+
}, z.core.$strict>;
|
|
80
|
+
}, z.core.$strict>]>;
|
|
81
|
+
export declare const CheckBulkEmailReadinessDiscoveryInputSchema: z.ZodObject<{
|
|
82
|
+
campaign_id: z.ZodNumber;
|
|
83
|
+
recipient_target: z.ZodUnion<readonly [z.ZodObject<{
|
|
84
|
+
type: z.ZodLiteral<"ids">;
|
|
85
|
+
campaign_creator_ids: z.ZodArray<z.ZodNumber>;
|
|
86
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
87
|
+
type: z.ZodLiteral<"selection">;
|
|
88
|
+
campaign_creator_selection: z.ZodObject<{
|
|
89
|
+
workflow_filter: z.ZodOptional<z.ZodEnum<{
|
|
90
|
+
all: "all";
|
|
91
|
+
email: "email";
|
|
92
|
+
email_not_sent: "email_not_sent";
|
|
93
|
+
email_sent: "email_sent";
|
|
94
|
+
replied: "replied";
|
|
95
|
+
negotiating: "negotiating";
|
|
96
|
+
rejected_hold: "rejected_hold";
|
|
97
|
+
rejected: "rejected";
|
|
98
|
+
hold: "hold";
|
|
99
|
+
contract: "contract";
|
|
100
|
+
contracted: "contracted";
|
|
101
|
+
content: "content";
|
|
102
|
+
draft: "draft";
|
|
103
|
+
final_approved: "final_approved";
|
|
104
|
+
posted: "posted";
|
|
105
|
+
}>>;
|
|
106
|
+
outreach_stage: z.ZodOptional<z.ZodString>;
|
|
107
|
+
platform: z.ZodOptional<z.ZodEnum<{
|
|
108
|
+
tiktok: "tiktok";
|
|
109
|
+
instagram: "instagram";
|
|
110
|
+
}>>;
|
|
111
|
+
country: z.ZodOptional<z.ZodString>;
|
|
112
|
+
has_video: z.ZodOptional<z.ZodBoolean>;
|
|
113
|
+
source_type: z.ZodOptional<z.ZodEnum<{
|
|
114
|
+
saved_list: "saved_list";
|
|
115
|
+
file_upload: "file_upload";
|
|
116
|
+
manual_add: "manual_add";
|
|
117
|
+
form_submission: "form_submission";
|
|
118
|
+
discovery_search: "discovery_search";
|
|
119
|
+
}>>;
|
|
120
|
+
search: z.ZodOptional<z.ZodString>;
|
|
121
|
+
excluded_ids: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
122
|
+
}, z.core.$strict>;
|
|
123
|
+
}, z.core.$strict>]>;
|
|
124
|
+
}, z.core.$strict>;
|
|
125
|
+
export declare const StartBulkEmailInputSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
126
|
+
campaign_id: z.ZodNumber;
|
|
127
|
+
subject: z.ZodString;
|
|
128
|
+
body_text: z.ZodString;
|
|
129
|
+
from_email: z.ZodOptional<z.ZodString>;
|
|
130
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
131
|
+
form_id: z.ZodOptional<z.ZodNumber>;
|
|
132
|
+
form_language: z.ZodOptional<z.ZodEnum<{
|
|
133
|
+
en: "en";
|
|
134
|
+
ko: "ko";
|
|
135
|
+
jp: "jp";
|
|
136
|
+
}>>;
|
|
137
|
+
idempotency_key: z.ZodString;
|
|
138
|
+
send_confirmation: z.ZodLiteral<"user_authorized">;
|
|
139
|
+
campaign_creator_ids: z.ZodArray<z.ZodNumber>;
|
|
140
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
141
|
+
campaign_id: z.ZodNumber;
|
|
142
|
+
subject: z.ZodString;
|
|
143
|
+
body_text: z.ZodString;
|
|
144
|
+
from_email: z.ZodOptional<z.ZodString>;
|
|
145
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
146
|
+
form_id: z.ZodOptional<z.ZodNumber>;
|
|
147
|
+
form_language: z.ZodOptional<z.ZodEnum<{
|
|
148
|
+
en: "en";
|
|
149
|
+
ko: "ko";
|
|
150
|
+
jp: "jp";
|
|
151
|
+
}>>;
|
|
152
|
+
idempotency_key: z.ZodString;
|
|
153
|
+
send_confirmation: z.ZodLiteral<"user_authorized">;
|
|
154
|
+
campaign_creator_selection: z.ZodObject<{
|
|
155
|
+
workflow_filter: z.ZodOptional<z.ZodEnum<{
|
|
156
|
+
all: "all";
|
|
157
|
+
email: "email";
|
|
158
|
+
email_not_sent: "email_not_sent";
|
|
159
|
+
email_sent: "email_sent";
|
|
160
|
+
replied: "replied";
|
|
161
|
+
negotiating: "negotiating";
|
|
162
|
+
rejected_hold: "rejected_hold";
|
|
163
|
+
rejected: "rejected";
|
|
164
|
+
hold: "hold";
|
|
165
|
+
contract: "contract";
|
|
166
|
+
contracted: "contracted";
|
|
167
|
+
content: "content";
|
|
168
|
+
draft: "draft";
|
|
169
|
+
final_approved: "final_approved";
|
|
170
|
+
posted: "posted";
|
|
171
|
+
}>>;
|
|
172
|
+
outreach_stage: z.ZodOptional<z.ZodString>;
|
|
173
|
+
platform: z.ZodOptional<z.ZodEnum<{
|
|
174
|
+
tiktok: "tiktok";
|
|
175
|
+
instagram: "instagram";
|
|
176
|
+
}>>;
|
|
177
|
+
country: z.ZodOptional<z.ZodString>;
|
|
178
|
+
has_video: z.ZodOptional<z.ZodBoolean>;
|
|
179
|
+
source_type: z.ZodOptional<z.ZodEnum<{
|
|
180
|
+
saved_list: "saved_list";
|
|
181
|
+
file_upload: "file_upload";
|
|
182
|
+
manual_add: "manual_add";
|
|
183
|
+
form_submission: "form_submission";
|
|
184
|
+
discovery_search: "discovery_search";
|
|
185
|
+
}>>;
|
|
186
|
+
search: z.ZodOptional<z.ZodString>;
|
|
187
|
+
excluded_ids: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
188
|
+
}, z.core.$strict>;
|
|
189
|
+
}, z.core.$strict>]>;
|
|
190
|
+
export declare const StartBulkEmailDiscoveryInputSchema: z.ZodObject<{
|
|
191
|
+
campaign_id: z.ZodNumber;
|
|
192
|
+
subject: z.ZodString;
|
|
193
|
+
body_text: z.ZodString;
|
|
194
|
+
from_email: z.ZodOptional<z.ZodString>;
|
|
195
|
+
attachments: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
196
|
+
form_id: z.ZodOptional<z.ZodNumber>;
|
|
197
|
+
form_language: z.ZodOptional<z.ZodEnum<{
|
|
198
|
+
en: "en";
|
|
199
|
+
ko: "ko";
|
|
200
|
+
jp: "jp";
|
|
201
|
+
}>>;
|
|
202
|
+
idempotency_key: z.ZodString;
|
|
203
|
+
send_confirmation: z.ZodLiteral<"user_authorized">;
|
|
204
|
+
recipient_target: z.ZodUnion<readonly [z.ZodObject<{
|
|
205
|
+
type: z.ZodLiteral<"ids">;
|
|
206
|
+
campaign_creator_ids: z.ZodArray<z.ZodNumber>;
|
|
207
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
208
|
+
type: z.ZodLiteral<"selection">;
|
|
209
|
+
campaign_creator_selection: z.ZodObject<{
|
|
210
|
+
workflow_filter: z.ZodOptional<z.ZodEnum<{
|
|
211
|
+
all: "all";
|
|
212
|
+
email: "email";
|
|
213
|
+
email_not_sent: "email_not_sent";
|
|
214
|
+
email_sent: "email_sent";
|
|
215
|
+
replied: "replied";
|
|
216
|
+
negotiating: "negotiating";
|
|
217
|
+
rejected_hold: "rejected_hold";
|
|
218
|
+
rejected: "rejected";
|
|
219
|
+
hold: "hold";
|
|
220
|
+
contract: "contract";
|
|
221
|
+
contracted: "contracted";
|
|
222
|
+
content: "content";
|
|
223
|
+
draft: "draft";
|
|
224
|
+
final_approved: "final_approved";
|
|
225
|
+
posted: "posted";
|
|
226
|
+
}>>;
|
|
227
|
+
outreach_stage: z.ZodOptional<z.ZodString>;
|
|
228
|
+
platform: z.ZodOptional<z.ZodEnum<{
|
|
229
|
+
tiktok: "tiktok";
|
|
230
|
+
instagram: "instagram";
|
|
231
|
+
}>>;
|
|
232
|
+
country: z.ZodOptional<z.ZodString>;
|
|
233
|
+
has_video: z.ZodOptional<z.ZodBoolean>;
|
|
234
|
+
source_type: z.ZodOptional<z.ZodEnum<{
|
|
235
|
+
saved_list: "saved_list";
|
|
236
|
+
file_upload: "file_upload";
|
|
237
|
+
manual_add: "manual_add";
|
|
238
|
+
form_submission: "form_submission";
|
|
239
|
+
discovery_search: "discovery_search";
|
|
240
|
+
}>>;
|
|
241
|
+
search: z.ZodOptional<z.ZodString>;
|
|
242
|
+
excluded_ids: z.ZodOptional<z.ZodArray<z.ZodNumber>>;
|
|
243
|
+
}, z.core.$strict>;
|
|
244
|
+
}, z.core.$strict>]>;
|
|
245
|
+
}, z.core.$strict>;
|
|
246
|
+
export type CheckBulkEmailReadinessInput = z.infer<typeof CheckBulkEmailReadinessInputSchema>;
|
|
247
|
+
export type StartBulkEmailInput = z.infer<typeof StartBulkEmailInputSchema>;
|
|
248
|
+
type CheckBulkEmailReadinessDiscoveryInput = z.infer<typeof CheckBulkEmailReadinessDiscoveryInputSchema>;
|
|
249
|
+
type StartBulkEmailDiscoveryInput = z.infer<typeof StartBulkEmailDiscoveryInputSchema>;
|
|
250
|
+
/** Convert the MCP-discoverable recipient target into the Product API shape. */
|
|
251
|
+
export declare function normalizeCheckBulkEmailReadinessInput(input: CheckBulkEmailReadinessDiscoveryInput): CheckBulkEmailReadinessInput;
|
|
252
|
+
/** Convert the MCP-discoverable send target into the Product API shape. */
|
|
253
|
+
export declare function normalizeStartBulkEmailInput(input: StartBulkEmailDiscoveryInput): StartBulkEmailInput;
|
|
254
|
+
export {};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const EmailSubjectSchema = z.string().trim().min(1).max(500);
|
|
3
|
+
const HeaderValueSchema = z
|
|
4
|
+
.string()
|
|
5
|
+
.trim()
|
|
6
|
+
.regex(/^[\x21-\x7e]+$/, {
|
|
7
|
+
message: "value contains unsupported header characters",
|
|
8
|
+
});
|
|
9
|
+
export const IdempotencyKeySchema = HeaderValueSchema.min(1).max(128);
|
|
10
|
+
const SendConfirmationSchema = z.literal("user_authorized");
|
|
11
|
+
const CampaignCreatorWorkflowFilterSchema = z.enum([
|
|
12
|
+
"all",
|
|
13
|
+
"email",
|
|
14
|
+
"email_not_sent",
|
|
15
|
+
"email_sent",
|
|
16
|
+
"replied",
|
|
17
|
+
"negotiating",
|
|
18
|
+
"rejected_hold",
|
|
19
|
+
"rejected",
|
|
20
|
+
"hold",
|
|
21
|
+
"contract",
|
|
22
|
+
"contracted",
|
|
23
|
+
"content",
|
|
24
|
+
"draft",
|
|
25
|
+
"final_approved",
|
|
26
|
+
"posted",
|
|
27
|
+
]);
|
|
28
|
+
const PositiveIdListSchema = z.array(z.number().int().positive()).min(1);
|
|
29
|
+
const CampaignCreatorSelectionSchema = z
|
|
30
|
+
.object({
|
|
31
|
+
workflow_filter: CampaignCreatorWorkflowFilterSchema.optional(),
|
|
32
|
+
outreach_stage: z.string().trim().min(1).optional(),
|
|
33
|
+
platform: z.enum(["tiktok", "instagram"]).optional(),
|
|
34
|
+
country: z.string().trim().min(1).optional(),
|
|
35
|
+
has_video: z.boolean().optional(),
|
|
36
|
+
source_type: z
|
|
37
|
+
.enum([
|
|
38
|
+
"saved_list",
|
|
39
|
+
"file_upload",
|
|
40
|
+
"manual_add",
|
|
41
|
+
"form_submission",
|
|
42
|
+
"discovery_search",
|
|
43
|
+
])
|
|
44
|
+
.optional(),
|
|
45
|
+
search: z.string().trim().min(1).optional(),
|
|
46
|
+
excluded_ids: z.array(z.number().int().positive()).optional(),
|
|
47
|
+
})
|
|
48
|
+
.strict()
|
|
49
|
+
.superRefine((value, context) => {
|
|
50
|
+
const hasNarrowingFilter = (value.workflow_filter !== undefined &&
|
|
51
|
+
value.workflow_filter !== "all") ||
|
|
52
|
+
value.outreach_stage !== undefined ||
|
|
53
|
+
value.platform !== undefined ||
|
|
54
|
+
value.country !== undefined ||
|
|
55
|
+
value.has_video !== undefined ||
|
|
56
|
+
value.source_type !== undefined ||
|
|
57
|
+
value.search !== undefined;
|
|
58
|
+
if (!hasNarrowingFilter) {
|
|
59
|
+
context.addIssue({
|
|
60
|
+
code: "custom",
|
|
61
|
+
message: "campaign_creator_selection must include a narrowing filter; use campaign_creator_ids for exact rows",
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const CampaignRecipientIdsTargetSchema = z
|
|
66
|
+
.object({
|
|
67
|
+
campaign_creator_ids: PositiveIdListSchema,
|
|
68
|
+
})
|
|
69
|
+
.strict();
|
|
70
|
+
const CampaignRecipientSelectionTargetSchema = z
|
|
71
|
+
.object({
|
|
72
|
+
campaign_creator_selection: CampaignCreatorSelectionSchema,
|
|
73
|
+
})
|
|
74
|
+
.strict();
|
|
75
|
+
const CampaignRecipientTargetSchema = z.union([
|
|
76
|
+
z
|
|
77
|
+
.object({
|
|
78
|
+
type: z.literal("ids"),
|
|
79
|
+
campaign_creator_ids: PositiveIdListSchema.describe("Exact campaign creator row IDs selected from list_campaign_creators."),
|
|
80
|
+
})
|
|
81
|
+
.strict(),
|
|
82
|
+
z
|
|
83
|
+
.object({
|
|
84
|
+
type: z.literal("selection"),
|
|
85
|
+
campaign_creator_selection: CampaignCreatorSelectionSchema.describe("Narrowed campaign roster selection, such as workflow_filter: email_not_sent."),
|
|
86
|
+
})
|
|
87
|
+
.strict(),
|
|
88
|
+
]);
|
|
89
|
+
function validateFormLanguage(value, context) {
|
|
90
|
+
if (value.form_language !== undefined && value.form_id === undefined) {
|
|
91
|
+
context.addIssue({
|
|
92
|
+
code: "custom",
|
|
93
|
+
message: "form_id is required when form_language is provided",
|
|
94
|
+
path: ["form_id"],
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
const CheckBulkEmailReadinessBaseSchema = z.object({
|
|
99
|
+
campaign_id: z.number().int().positive(),
|
|
100
|
+
});
|
|
101
|
+
export const CheckBulkEmailReadinessInputSchema = z.union([
|
|
102
|
+
CheckBulkEmailReadinessBaseSchema.merge(CampaignRecipientIdsTargetSchema),
|
|
103
|
+
CheckBulkEmailReadinessBaseSchema.merge(CampaignRecipientSelectionTargetSchema),
|
|
104
|
+
]);
|
|
105
|
+
export const CheckBulkEmailReadinessDiscoveryInputSchema = CheckBulkEmailReadinessBaseSchema.extend({
|
|
106
|
+
recipient_target: CampaignRecipientTargetSchema,
|
|
107
|
+
}).strict();
|
|
108
|
+
const StartBulkEmailBaseSchema = z
|
|
109
|
+
.object({
|
|
110
|
+
campaign_id: z.number().int().positive(),
|
|
111
|
+
subject: EmailSubjectSchema,
|
|
112
|
+
body_text: z.string().trim().min(1),
|
|
113
|
+
from_email: z.string().trim().min(1).optional(),
|
|
114
|
+
attachments: z.array(z.string().trim().min(1)).optional(),
|
|
115
|
+
form_id: z.number().int().positive().optional(),
|
|
116
|
+
form_language: z.enum(["en", "ko", "jp"]).optional(),
|
|
117
|
+
idempotency_key: IdempotencyKeySchema,
|
|
118
|
+
send_confirmation: SendConfirmationSchema,
|
|
119
|
+
})
|
|
120
|
+
.strict();
|
|
121
|
+
export const StartBulkEmailInputSchema = z
|
|
122
|
+
.union([
|
|
123
|
+
StartBulkEmailBaseSchema.merge(CampaignRecipientIdsTargetSchema),
|
|
124
|
+
StartBulkEmailBaseSchema.merge(CampaignRecipientSelectionTargetSchema),
|
|
125
|
+
])
|
|
126
|
+
.superRefine(validateFormLanguage);
|
|
127
|
+
export const StartBulkEmailDiscoveryInputSchema = StartBulkEmailBaseSchema.extend({
|
|
128
|
+
recipient_target: CampaignRecipientTargetSchema,
|
|
129
|
+
})
|
|
130
|
+
.strict()
|
|
131
|
+
.superRefine(validateFormLanguage);
|
|
132
|
+
/** Convert the MCP-discoverable recipient target into the Product API shape. */
|
|
133
|
+
export function normalizeCheckBulkEmailReadinessInput(input) {
|
|
134
|
+
if (input.recipient_target.type === "ids") {
|
|
135
|
+
return {
|
|
136
|
+
campaign_id: input.campaign_id,
|
|
137
|
+
campaign_creator_ids: input.recipient_target.campaign_creator_ids,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
campaign_id: input.campaign_id,
|
|
142
|
+
campaign_creator_selection: input.recipient_target.campaign_creator_selection,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** Convert the MCP-discoverable send target into the Product API shape. */
|
|
146
|
+
export function normalizeStartBulkEmailInput(input) {
|
|
147
|
+
const base = {
|
|
148
|
+
campaign_id: input.campaign_id,
|
|
149
|
+
subject: input.subject,
|
|
150
|
+
body_text: input.body_text,
|
|
151
|
+
from_email: input.from_email,
|
|
152
|
+
attachments: input.attachments,
|
|
153
|
+
form_id: input.form_id,
|
|
154
|
+
form_language: input.form_language,
|
|
155
|
+
idempotency_key: input.idempotency_key,
|
|
156
|
+
send_confirmation: input.send_confirmation,
|
|
157
|
+
};
|
|
158
|
+
if (input.recipient_target.type === "ids") {
|
|
159
|
+
return {
|
|
160
|
+
...base,
|
|
161
|
+
campaign_creator_ids: input.recipient_target.campaign_creator_ids,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
...base,
|
|
166
|
+
campaign_creator_selection: input.recipient_target.campaign_creator_selection,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { JsonObject } from "./http.js";
|
|
2
|
+
import type { CheckBulkEmailReadinessInput, StartBulkEmailInput } from "./tool-inputs.js";
|
|
3
|
+
/** Build the campaign bulk-email readiness request body. */
|
|
4
|
+
export declare function readinessRequestBody(input: CheckBulkEmailReadinessInput): JsonObject;
|
|
5
|
+
/** Build the campaign bulk-email job request body. */
|
|
6
|
+
export declare function startBulkEmailRequestBody(input: StartBulkEmailInput): JsonObject;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { campaignCreatorSelectionBody } from "./campaign-creator-selection.js";
|
|
2
|
+
import { compactJsonObject } from "./tool-http-helpers.js";
|
|
3
|
+
/** Build the campaign bulk-email readiness request body. */
|
|
4
|
+
export function readinessRequestBody(input) {
|
|
5
|
+
return campaignRecipientTargetBody(input);
|
|
6
|
+
}
|
|
7
|
+
/** Build the campaign bulk-email job request body. */
|
|
8
|
+
export function startBulkEmailRequestBody(input) {
|
|
9
|
+
return compactJsonObject([
|
|
10
|
+
["subject", input.subject],
|
|
11
|
+
["body_text", input.body_text],
|
|
12
|
+
["from_email", input.from_email],
|
|
13
|
+
["attachments", input.attachments],
|
|
14
|
+
...campaignRecipientTargetEntries(input),
|
|
15
|
+
["form_id", input.form_id],
|
|
16
|
+
["form_language", input.form_language],
|
|
17
|
+
["idempotency_key", input.idempotency_key],
|
|
18
|
+
["send_confirmation", input.send_confirmation],
|
|
19
|
+
]);
|
|
20
|
+
}
|
|
21
|
+
function campaignRecipientTargetBody(input) {
|
|
22
|
+
return compactJsonObject(campaignRecipientTargetEntries(input));
|
|
23
|
+
}
|
|
24
|
+
function campaignRecipientTargetEntries(input) {
|
|
25
|
+
return [
|
|
26
|
+
[
|
|
27
|
+
"campaign_creator_ids",
|
|
28
|
+
"campaign_creator_ids" in input ? input.campaign_creator_ids : undefined,
|
|
29
|
+
],
|
|
30
|
+
[
|
|
31
|
+
"campaign_creator_selection",
|
|
32
|
+
campaignCreatorSelectionBody("campaign_creator_selection" in input
|
|
33
|
+
? input.campaign_creator_selection
|
|
34
|
+
: undefined),
|
|
35
|
+
],
|
|
36
|
+
];
|
|
37
|
+
}
|
package/dist/cli.js
CHANGED
|
@@ -98,8 +98,9 @@ export async function runCli(argv = process.argv.slice(2), dependencies = {}) {
|
|
|
98
98
|
}
|
|
99
99
|
/** Parse CLI arguments using Node's standard parser. */
|
|
100
100
|
function parseCommand(argv) {
|
|
101
|
+
const args = argv[0] === "--" ? argv.slice(1) : argv;
|
|
101
102
|
const parsed = parseArgs({
|
|
102
|
-
args: [...
|
|
103
|
+
args: [...args],
|
|
103
104
|
allowPositionals: true,
|
|
104
105
|
options: {
|
|
105
106
|
json: { type: "boolean", default: false },
|
|
@@ -320,4 +321,3 @@ if (isDirectCliInvocation(import.meta.url, process.argv[1])) {
|
|
|
320
321
|
process.exitCode = exitCode;
|
|
321
322
|
});
|
|
322
323
|
}
|
|
323
|
-
//# sourceMappingURL=cli.js.map
|