llmconveyors-mcp 0.3.0 → 0.3.2
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/dist/index.js +259 -207
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { LLMConveyors } from "llmconveyors";
|
|
|
9
9
|
import { z } from "zod";
|
|
10
10
|
|
|
11
11
|
// src/utils/error-handler.ts
|
|
12
|
-
import { LLMConveyorsError, RateLimitError } from "llmconveyors";
|
|
12
|
+
import { LLMConveyorsError, RateLimitError, NetworkError, TimeoutError } from "llmconveyors";
|
|
13
13
|
function handleToolError(err) {
|
|
14
14
|
if (err instanceof LLMConveyorsError) {
|
|
15
15
|
const payload = {
|
|
@@ -19,10 +19,13 @@ function handleToolError(err) {
|
|
|
19
19
|
...err.hint != null && { hint: err.hint },
|
|
20
20
|
...err.details != null && { details: err.details },
|
|
21
21
|
...err.requestId != null && { requestId: err.requestId },
|
|
22
|
+
...err.timestamp != null && { timestamp: err.timestamp },
|
|
23
|
+
...err.path != null && { path: err.path },
|
|
22
24
|
retryable: err.isRetryable()
|
|
23
25
|
};
|
|
24
26
|
if (err instanceof RateLimitError) {
|
|
25
|
-
if (err.retryAfter != null) payload.
|
|
27
|
+
if (err.retryAfter != null) payload.retryAfterSeconds = err.retryAfter;
|
|
28
|
+
if (err.retryAfterMs != null) payload.retryAfterMs = err.retryAfterMs;
|
|
26
29
|
if (err.rateLimitInfo != null) payload.rateLimitInfo = err.rateLimitInfo;
|
|
27
30
|
}
|
|
28
31
|
return {
|
|
@@ -30,6 +33,28 @@ function handleToolError(err) {
|
|
|
30
33
|
isError: true
|
|
31
34
|
};
|
|
32
35
|
}
|
|
36
|
+
if (err instanceof NetworkError) {
|
|
37
|
+
return {
|
|
38
|
+
content: [{ type: "text", text: JSON.stringify({
|
|
39
|
+
error: err.message,
|
|
40
|
+
type: "NetworkError",
|
|
41
|
+
retryable: true,
|
|
42
|
+
...err.cause != null && { cause: String(err.cause) }
|
|
43
|
+
}, null, 2) }],
|
|
44
|
+
isError: true
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (err instanceof TimeoutError) {
|
|
48
|
+
return {
|
|
49
|
+
content: [{ type: "text", text: JSON.stringify({
|
|
50
|
+
error: err.message,
|
|
51
|
+
type: "TimeoutError",
|
|
52
|
+
retryable: true,
|
|
53
|
+
...err.cause != null && { cause: String(err.cause) }
|
|
54
|
+
}, null, 2) }],
|
|
55
|
+
isError: true
|
|
56
|
+
};
|
|
57
|
+
}
|
|
33
58
|
const message = err instanceof Error ? err.message : String(err);
|
|
34
59
|
return {
|
|
35
60
|
content: [{ type: "text", text: `Error: ${message}` }],
|
|
@@ -41,23 +66,35 @@ function handleToolError(err) {
|
|
|
41
66
|
function registerAgentTools(server2, client2) {
|
|
42
67
|
server2.tool(
|
|
43
68
|
"job-hunter-run",
|
|
44
|
-
"Run the Job Hunter agent \u2014 generates a tailored CV, cover letter, and cold email for a job application.
|
|
69
|
+
"Run the Job Hunter agent \u2014 generates a tailored CV, cover letter, and cold email for a job application. Supports phased execution: set autoSelectContacts=false to pause for contact selection (poll with agent-status, respond with agent-interact). Consumes 30-500 credits. Rate limited: 10 req/min. Requires scope: jobs:write. Check balance with settings-usage-summary before running.",
|
|
45
70
|
{
|
|
46
71
|
companyName: z.string().describe("Target company name"),
|
|
47
72
|
jobTitle: z.string().describe("Job title to apply for"),
|
|
48
|
-
jobDescription: z.string().
|
|
49
|
-
companyWebsite: z.string().
|
|
73
|
+
jobDescription: z.string().describe("Full job description text"),
|
|
74
|
+
companyWebsite: z.string().describe("Target company website URL for research phase"),
|
|
75
|
+
sessionId: z.string().optional().describe("Existing session ID to continue a previous run"),
|
|
76
|
+
generationId: z.string().optional().describe("Existing generation ID to continue"),
|
|
50
77
|
masterResumeId: z.string().optional().describe("ID of a stored master resume to use"),
|
|
78
|
+
tier: z.enum(["free", "byo"]).optional().describe("Billing tier: free (platform credits) or byo (bring your own key)"),
|
|
79
|
+
model: z.enum(["flash", "pro"]).optional().describe("AI model: flash (faster/cheaper) or pro (higher quality)"),
|
|
80
|
+
webhookUrl: z.string().optional().describe("Webhook URL for async status updates (generation.completed, generation.failed, generation.awaiting_input)"),
|
|
81
|
+
mode: z.enum(["standard", "cold_outreach"]).optional().describe("Generation mode"),
|
|
51
82
|
theme: z.enum(["even", "stackoverflow", "class", "professional", "elegant", "macchiato", "react", "academic"]).optional().describe("Resume theme"),
|
|
83
|
+
autoSelectContacts: z.boolean().optional().describe("Set false for phased execution with contact selection gate. Default true for API keys."),
|
|
84
|
+
skipResearchCache: z.boolean().optional().describe("Force fresh company research instead of using cache"),
|
|
52
85
|
contactName: z.string().optional().describe("Hiring manager or recruiter name"),
|
|
53
86
|
contactTitle: z.string().optional().describe("Contact job title"),
|
|
54
87
|
contactEmail: z.string().optional().describe("Contact email for cold outreach"),
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
autoSelectContacts: z.boolean().optional().describe("Set false for phased execution with contact selection gate. Default true for API keys."),
|
|
88
|
+
genericEmail: z.string().optional().describe("Generic company email (e.g. careers@company.com) as fallback"),
|
|
89
|
+
emailAddresses: z.string().optional().describe("Comma-separated email addresses for outreach"),
|
|
58
90
|
originalCV: z.string().optional().describe("Original CV text to use directly instead of master resume"),
|
|
59
91
|
extensiveCV: z.string().optional().describe("Extended/detailed CV text for richer generation"),
|
|
60
|
-
|
|
92
|
+
cvStrategy: z.string().optional().describe("Strategy instructions for CV generation"),
|
|
93
|
+
coverLetterStrategy: z.string().optional().describe("Strategy instructions for cover letter generation"),
|
|
94
|
+
coldEmailStrategy: z.string().optional().describe("Strategy instructions for cold email generation"),
|
|
95
|
+
reconStrategy: z.string().optional().describe("Strategy instructions for company research/recon phase"),
|
|
96
|
+
specificCore: z.string().optional().describe("Specific core competencies or skills to emphasize"),
|
|
97
|
+
companyProfile: z.string().optional().describe("Pre-researched company profile to skip research phase"),
|
|
61
98
|
jobSourceUrl: z.string().optional().describe("URL of the original job posting")
|
|
62
99
|
},
|
|
63
100
|
async (params) => {
|
|
@@ -65,19 +102,31 @@ function registerAgentTools(server2, client2) {
|
|
|
65
102
|
const result = await client2.agents.run("job-hunter", {
|
|
66
103
|
companyName: params.companyName,
|
|
67
104
|
jobTitle: params.jobTitle,
|
|
68
|
-
|
|
69
|
-
|
|
105
|
+
jobDescription: params.jobDescription,
|
|
106
|
+
companyWebsite: params.companyWebsite,
|
|
107
|
+
...params.sessionId != null && { sessionId: params.sessionId },
|
|
108
|
+
...params.generationId != null && { generationId: params.generationId },
|
|
70
109
|
...params.masterResumeId != null && { masterResumeId: params.masterResumeId },
|
|
110
|
+
...params.tier != null && { tier: params.tier },
|
|
111
|
+
...params.model != null && { model: params.model },
|
|
112
|
+
...params.webhookUrl != null && { webhookUrl: params.webhookUrl },
|
|
113
|
+
...params.mode != null && { mode: params.mode },
|
|
71
114
|
...params.theme != null && { theme: params.theme },
|
|
115
|
+
...params.autoSelectContacts != null && { autoSelectContacts: params.autoSelectContacts },
|
|
116
|
+
...params.skipResearchCache != null && { skipResearchCache: params.skipResearchCache },
|
|
72
117
|
...params.contactName != null && { contactName: params.contactName },
|
|
73
118
|
...params.contactTitle != null && { contactTitle: params.contactTitle },
|
|
74
119
|
...params.contactEmail != null && { contactEmail: params.contactEmail },
|
|
75
|
-
...params.
|
|
76
|
-
...params.
|
|
77
|
-
...params.autoSelectContacts != null && { autoSelectContacts: params.autoSelectContacts },
|
|
120
|
+
...params.genericEmail != null && { genericEmail: params.genericEmail },
|
|
121
|
+
...params.emailAddresses != null && { emailAddresses: params.emailAddresses },
|
|
78
122
|
...params.originalCV != null && { originalCV: params.originalCV },
|
|
79
123
|
...params.extensiveCV != null && { extensiveCV: params.extensiveCV },
|
|
80
|
-
...params.
|
|
124
|
+
...params.cvStrategy != null && { cvStrategy: params.cvStrategy },
|
|
125
|
+
...params.coverLetterStrategy != null && { coverLetterStrategy: params.coverLetterStrategy },
|
|
126
|
+
...params.coldEmailStrategy != null && { coldEmailStrategy: params.coldEmailStrategy },
|
|
127
|
+
...params.reconStrategy != null && { reconStrategy: params.reconStrategy },
|
|
128
|
+
...params.specificCore != null && { specificCore: params.specificCore },
|
|
129
|
+
...params.companyProfile != null && { companyProfile: params.companyProfile },
|
|
81
130
|
...params.jobSourceUrl != null && { jobSourceUrl: params.jobSourceUrl }
|
|
82
131
|
});
|
|
83
132
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -88,30 +137,54 @@ function registerAgentTools(server2, client2) {
|
|
|
88
137
|
);
|
|
89
138
|
server2.tool(
|
|
90
139
|
"b2b-sales-run",
|
|
91
|
-
"Run the B2B Sales agent \u2014 researches a company and generates personalized sales outreach. Consumes 50-500 credits. Rate limited: 10 req/min. Requires scope: sales:write. Check balance with settings-usage-summary before running.",
|
|
140
|
+
"Run the B2B Sales agent \u2014 researches a company and generates personalized sales outreach (emails, follow-ups). Supports phased execution: set autoSelectContacts=false to pause for contact selection, autoApproveDraft=false to review before sending. Poll with agent-status, respond with agent-interact. Consumes 50-500 credits. Rate limited: 10 req/min. Requires scope: sales:write. Check balance with settings-usage-summary before running.",
|
|
92
141
|
{
|
|
93
142
|
companyName: z.string().describe("Target company name"),
|
|
94
143
|
companyWebsite: z.string().describe("Target company website URL"),
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
strategy: z.string().optional().describe("Sales strategy to use"),
|
|
98
|
-
webhookUrl: z.string().optional().describe("Webhook URL for async status updates"),
|
|
144
|
+
sessionId: z.string().optional().describe("Existing session ID to continue a previous run"),
|
|
145
|
+
generationId: z.string().optional().describe("Existing generation ID to continue"),
|
|
99
146
|
model: z.enum(["flash", "pro"]).optional().describe("AI model: flash (faster/cheaper) or pro (higher quality)"),
|
|
100
147
|
userCompanyContext: z.string().optional().describe("Context about your own company for personalization"),
|
|
101
|
-
|
|
148
|
+
targetCompanyContext: z.string().optional().describe("Pre-researched context about the target company"),
|
|
149
|
+
contactName: z.string().optional().describe("Target contact name"),
|
|
150
|
+
contactTitle: z.string().optional().describe("Target contact job title"),
|
|
151
|
+
contactEmail: z.string().optional().describe("Target contact email address"),
|
|
152
|
+
senderName: z.string().optional().describe("Name of the person sending the outreach"),
|
|
153
|
+
salesStrategy: z.string().optional().describe("Sales strategy to use for outreach generation"),
|
|
154
|
+
reconStrategy: z.string().optional().describe("Strategy instructions for company research/recon phase"),
|
|
155
|
+
companyResearch: z.string().optional().describe("Pre-researched company information to skip research phase"),
|
|
156
|
+
researchMode: z.enum(["parallel", "sequential"]).optional().describe("Research execution mode: parallel (faster) or sequential"),
|
|
157
|
+
autoSelectContacts: z.boolean().optional().describe("Set false for phased execution with contact selection gate"),
|
|
158
|
+
autoApproveDraft: z.boolean().optional().describe("Set false to pause for draft review before finalizing"),
|
|
159
|
+
autoApproveFollowups: z.boolean().optional().describe("Set false to pause for follow-up review before finalizing"),
|
|
160
|
+
followUpCount: z.number().optional().describe("Number of follow-up emails to generate"),
|
|
161
|
+
followUpDelayDays: z.number().optional().describe("Days between follow-up emails"),
|
|
162
|
+
skipResearchCache: z.boolean().optional().describe("Force fresh company research instead of using cache")
|
|
102
163
|
},
|
|
103
164
|
async (params) => {
|
|
104
165
|
try {
|
|
105
166
|
const result = await client2.agents.run("b2b-sales", {
|
|
106
167
|
companyName: params.companyName,
|
|
107
168
|
companyWebsite: params.companyWebsite,
|
|
108
|
-
...params.targetProfile != null && { targetProfile: params.targetProfile },
|
|
109
169
|
...params.sessionId != null && { sessionId: params.sessionId },
|
|
110
|
-
...params.
|
|
111
|
-
...params.webhookUrl != null && { webhookUrl: params.webhookUrl },
|
|
170
|
+
...params.generationId != null && { generationId: params.generationId },
|
|
112
171
|
...params.model != null && { model: params.model },
|
|
113
172
|
...params.userCompanyContext != null && { userCompanyContext: params.userCompanyContext },
|
|
114
|
-
...params.
|
|
173
|
+
...params.targetCompanyContext != null && { targetCompanyContext: params.targetCompanyContext },
|
|
174
|
+
...params.contactName != null && { contactName: params.contactName },
|
|
175
|
+
...params.contactTitle != null && { contactTitle: params.contactTitle },
|
|
176
|
+
...params.contactEmail != null && { contactEmail: params.contactEmail },
|
|
177
|
+
...params.senderName != null && { senderName: params.senderName },
|
|
178
|
+
...params.salesStrategy != null && { salesStrategy: params.salesStrategy },
|
|
179
|
+
...params.reconStrategy != null && { reconStrategy: params.reconStrategy },
|
|
180
|
+
...params.companyResearch != null && { companyResearch: params.companyResearch },
|
|
181
|
+
...params.researchMode != null && { researchMode: params.researchMode },
|
|
182
|
+
...params.autoSelectContacts != null && { autoSelectContacts: params.autoSelectContacts },
|
|
183
|
+
...params.autoApproveDraft != null && { autoApproveDraft: params.autoApproveDraft },
|
|
184
|
+
...params.autoApproveFollowups != null && { autoApproveFollowups: params.autoApproveFollowups },
|
|
185
|
+
...params.followUpCount != null && { followUpCount: params.followUpCount },
|
|
186
|
+
...params.followUpDelayDays != null && { followUpDelayDays: params.followUpDelayDays },
|
|
187
|
+
...params.skipResearchCache != null && { skipResearchCache: params.skipResearchCache }
|
|
115
188
|
});
|
|
116
189
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
117
190
|
} catch (err) {
|
|
@@ -121,7 +194,7 @@ function registerAgentTools(server2, client2) {
|
|
|
121
194
|
);
|
|
122
195
|
server2.tool(
|
|
123
196
|
"agent-status",
|
|
124
|
-
"
|
|
197
|
+
"Poll the status of a running agent job to check progress, completion, or if it is awaiting input. Returns status, logs, and artifacts when available. Use this after calling job-hunter-run or b2b-sales-run to monitor the asynchronous job. When status is awaiting_input, use agent-interact to respond. Read-only, no side effects. Requires scope: jobs:read or sales:read.",
|
|
125
198
|
{
|
|
126
199
|
agentType: z.enum(["job-hunter", "b2b-sales"]).describe("Agent type"),
|
|
127
200
|
jobId: z.string().describe("Job ID returned from a generate call"),
|
|
@@ -140,7 +213,7 @@ function registerAgentTools(server2, client2) {
|
|
|
140
213
|
);
|
|
141
214
|
server2.tool(
|
|
142
215
|
"agent-interact",
|
|
143
|
-
"Submit a response to a phased agent workflow that is awaiting input. Used when agent-status returns awaiting_input. Rate limited: 10 req/min. Requires scope: jobs:write or sales:write.",
|
|
216
|
+
"Submit a response to a phased agent workflow that is awaiting input (e.g. contact selection, draft approval). Used when agent-status returns status=awaiting_input. The interactionType and interactionData fields come from the awaiting_input response. Rate limited: 10 req/min. Requires scope: jobs:write or sales:write.",
|
|
144
217
|
{
|
|
145
218
|
agentType: z.enum(["job-hunter", "b2b-sales"]).describe("Agent type"),
|
|
146
219
|
generationId: z.string().describe("Generation ID from the run or status response"),
|
|
@@ -164,20 +237,14 @@ function registerAgentTools(server2, client2) {
|
|
|
164
237
|
);
|
|
165
238
|
server2.tool(
|
|
166
239
|
"job-hunter-generate-cv",
|
|
167
|
-
"Generate a CV synchronously without running the full Job Hunter pipeline. Faster but produces only a CV, no cover letter or cold email. Consumes credits. Rate limited: 10 req/min. Requires scope: jobs:write.",
|
|
240
|
+
"Generate a CV synchronously without running the full Job Hunter pipeline. Faster but produces only a CV, no cover letter or cold email. Pass a prompt describing the desired CV content, style, or modifications. Consumes credits. Rate limited: 10 req/min. Requires scope: jobs:write.",
|
|
168
241
|
{
|
|
169
|
-
prompt: z.string().describe("Prompt for CV generation \u2014 describe the desired CV content, style, or modifications")
|
|
170
|
-
resume: z.record(z.unknown()).optional().describe("Resume data object in JSON Resume format"),
|
|
171
|
-
jobDescription: z.string().optional().describe("Job description text for tailoring"),
|
|
172
|
-
theme: z.enum(["even", "stackoverflow", "class", "professional", "elegant", "macchiato", "react", "academic"]).optional().describe("Resume theme")
|
|
242
|
+
prompt: z.string().describe("Prompt for CV generation \u2014 describe the desired CV content, style, or modifications")
|
|
173
243
|
},
|
|
174
244
|
async (params) => {
|
|
175
245
|
try {
|
|
176
246
|
const result = await client2.agents.generateCv({
|
|
177
|
-
prompt: params.prompt
|
|
178
|
-
...params.resume != null && { resume: params.resume },
|
|
179
|
-
...params.jobDescription != null && { jobDescription: params.jobDescription },
|
|
180
|
-
...params.theme != null && { theme: params.theme }
|
|
247
|
+
prompt: params.prompt
|
|
181
248
|
});
|
|
182
249
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
183
250
|
} catch (err) {
|
|
@@ -187,7 +254,7 @@ function registerAgentTools(server2, client2) {
|
|
|
187
254
|
);
|
|
188
255
|
server2.tool(
|
|
189
256
|
"agent-manifest",
|
|
190
|
-
"Get the manifest
|
|
257
|
+
"Get the manifest for an agent type, describing its input fields, capabilities, supported options, and billing information (credit costs per action). Use this to discover what parameters an agent accepts before running it, or to display pricing information. Read-only, no side effects. Requires scope: jobs:read or sales:read.",
|
|
191
258
|
{
|
|
192
259
|
agentType: z.enum(["job-hunter", "b2b-sales"]).describe("Agent type")
|
|
193
260
|
},
|
|
@@ -207,10 +274,8 @@ import { z as z2 } from "zod";
|
|
|
207
274
|
function registerAtsTools(server2, client2) {
|
|
208
275
|
server2.tool(
|
|
209
276
|
"ats-score",
|
|
210
|
-
"Score a resume against a job description for ATS compatibility. Returns overall score, grade,
|
|
277
|
+
"Score a resume against a job description for ATS (Applicant Tracking System) compatibility using a 3-pass hybrid analysis (keyword extraction, deterministic matching, semantic gap analysis). Returns an overall score, letter grade, matched/missing keywords, and actionable improvement suggestions. Use this before job-hunter-run to assess resume fit, or standalone to evaluate how well a resume matches a specific job posting. Consumes credits. Requires scope: ats:write. Use upload-job-text to parse a job description first if you have a URL.",
|
|
211
278
|
{
|
|
212
|
-
// TODO(SDK): SDK type uses `resume: Record<string, unknown>` and `jobDescription: Record<string, unknown>`
|
|
213
|
-
// but the actual API expects string fields. Remove cast once SDK types are fixed.
|
|
214
279
|
resumeText: z2.string().describe("Resume as plain text"),
|
|
215
280
|
jobDescription: z2.string().describe("Job description as plain text"),
|
|
216
281
|
jobTitle: z2.string().optional().describe("Job title for additional context")
|
|
@@ -235,7 +300,7 @@ import { z as z3 } from "zod";
|
|
|
235
300
|
function registerResumeTools(server2, client2) {
|
|
236
301
|
server2.tool(
|
|
237
302
|
"resume-parse",
|
|
238
|
-
"Parse a resume file into structured JSON Resume format. Accepts base64-encoded file content. Requires scope: resume:write.",
|
|
303
|
+
"Parse a resume file (PDF, DOCX, or TXT) into structured JSON Resume format. Accepts base64-encoded file content and returns structured data with contact info, work experience, education, and skills. Use this to extract structured data from an existing resume file. For uploading and parsing in one step, use upload-resume instead. Requires scope: resume:write.",
|
|
239
304
|
{
|
|
240
305
|
fileBase64: z3.string().describe("Base64-encoded resume file (PDF, DOCX, TXT)"),
|
|
241
306
|
filename: z3.string().describe("Original filename with extension"),
|
|
@@ -258,7 +323,7 @@ function registerResumeTools(server2, client2) {
|
|
|
258
323
|
);
|
|
259
324
|
server2.tool(
|
|
260
325
|
"resume-validate",
|
|
261
|
-
"Validate a resume
|
|
326
|
+
"Validate a resume object against the JSON Resume schema, returning any errors and warnings (missing fields, invalid formats, incomplete sections). Use this after parsing or editing a resume to verify it is well-formed before rendering or submitting to agents. Does not modify the resume. Requires scope: resume:write.",
|
|
262
327
|
{
|
|
263
328
|
resume: z3.record(z3.unknown()).describe("Resume object in JSON Resume format")
|
|
264
329
|
},
|
|
@@ -273,7 +338,7 @@ function registerResumeTools(server2, client2) {
|
|
|
273
338
|
);
|
|
274
339
|
server2.tool(
|
|
275
340
|
"resume-render",
|
|
276
|
-
"Render a
|
|
341
|
+
"Render a JSON Resume object to a downloadable PDF or HTML file using a specified theme. Returns a URL to download the generated file. Use this to produce a polished, formatted resume for sharing or printing. Use resume-themes to see available themes. For a quick inline preview without generating a file, use resume-preview instead. Requires scope: resume:write.",
|
|
277
342
|
{
|
|
278
343
|
resume: z3.record(z3.unknown()).describe("Resume object in JSON Resume format"),
|
|
279
344
|
theme: z3.string().describe("Theme name (e.g. even, stackoverflow, class, professional, elegant, macchiato, react, academic)"),
|
|
@@ -294,7 +359,7 @@ function registerResumeTools(server2, client2) {
|
|
|
294
359
|
);
|
|
295
360
|
server2.tool(
|
|
296
361
|
"resume-preview",
|
|
297
|
-
"Preview a
|
|
362
|
+
"Preview a JSON Resume object as inline HTML using a specified theme. Returns the rendered HTML string directly (not a URL). Use this for quick visual previews without generating a downloadable file. For producing a downloadable PDF or HTML file, use resume-render instead. Requires scope: resume:write.",
|
|
298
363
|
{
|
|
299
364
|
resume: z3.record(z3.unknown()).describe("Resume object in JSON Resume format"),
|
|
300
365
|
theme: z3.string().describe("Theme name (e.g. even, stackoverflow, class, professional)")
|
|
@@ -313,7 +378,7 @@ function registerResumeTools(server2, client2) {
|
|
|
313
378
|
);
|
|
314
379
|
server2.tool(
|
|
315
380
|
"resume-themes",
|
|
316
|
-
"List all available resume themes
|
|
381
|
+
"List all available resume themes with their IDs, names, and descriptions. Use this to discover theme options before calling resume-render or resume-preview, or to let the user choose a theme. Read-only, no side effects. Requires scope: resume:read.",
|
|
317
382
|
{},
|
|
318
383
|
async () => {
|
|
319
384
|
try {
|
|
@@ -326,7 +391,7 @@ function registerResumeTools(server2, client2) {
|
|
|
326
391
|
);
|
|
327
392
|
server2.tool(
|
|
328
393
|
"resume-import-rx",
|
|
329
|
-
"
|
|
394
|
+
"Convert a resume from Reactive Resume (RxResume) format into JSON Resume format. Use this to import resumes exported from the Reactive Resume application. Returns the converted resume object. Does not store the result; save it with master-resume-upsert if needed. Requires scope: resume:write. For the reverse conversion, use resume-export-rx.",
|
|
330
395
|
{
|
|
331
396
|
data: z3.record(z3.unknown()).describe("RxResume data object to import")
|
|
332
397
|
},
|
|
@@ -341,7 +406,7 @@ function registerResumeTools(server2, client2) {
|
|
|
341
406
|
);
|
|
342
407
|
server2.tool(
|
|
343
408
|
"resume-export-rx",
|
|
344
|
-
"
|
|
409
|
+
"Convert a JSON Resume object to Reactive Resume (RxResume) format for use in the Reactive Resume application. Optionally include design/styling configuration. Read-only conversion, does not modify the source resume. Requires scope: resume:read. For the reverse conversion, use resume-import-rx.",
|
|
345
410
|
{
|
|
346
411
|
resume: z3.record(z3.unknown()).describe("Resume object in JSON Resume format"),
|
|
347
412
|
designBlob: z3.record(z3.unknown()).optional().describe("Optional design/styling configuration")
|
|
@@ -359,33 +424,12 @@ function registerResumeTools(server2, client2) {
|
|
|
359
424
|
}
|
|
360
425
|
);
|
|
361
426
|
server2.tool(
|
|
362
|
-
"master-resume-
|
|
363
|
-
"
|
|
364
|
-
{
|
|
365
|
-
name: z3.string().describe("Name/label for this master resume"),
|
|
366
|
-
resume: z3.record(z3.unknown()).describe("Resume data object (structured JSON Resume or raw text in a wrapper)"),
|
|
367
|
-
metadata: z3.record(z3.unknown()).optional().describe("Optional metadata for the master resume")
|
|
368
|
-
},
|
|
369
|
-
async (params) => {
|
|
370
|
-
try {
|
|
371
|
-
const result = await client2.resume.createMaster({
|
|
372
|
-
name: params.name,
|
|
373
|
-
resume: params.resume,
|
|
374
|
-
...params.metadata != null && { metadata: params.metadata }
|
|
375
|
-
});
|
|
376
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
377
|
-
} catch (err) {
|
|
378
|
-
return handleToolError(err);
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
);
|
|
382
|
-
server2.tool(
|
|
383
|
-
"master-resume-list",
|
|
384
|
-
"List all master resumes. Returns an array of master resume objects. Requires scope: resume:read.",
|
|
427
|
+
"master-resume-get",
|
|
428
|
+
"Get the user's stored master resume, returning its label, raw text, and structured data. The master resume serves as the default resume for agent runs when no other resume is provided. Use this to review the current master resume before running job-hunter-run. Read-only, no side effects. Requires scope: resume:read. Use master-resume-upsert to create or update it.",
|
|
385
429
|
{},
|
|
386
430
|
async () => {
|
|
387
431
|
try {
|
|
388
|
-
const result = await client2.resume.
|
|
432
|
+
const result = await client2.resume.getMaster();
|
|
389
433
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
390
434
|
} catch (err) {
|
|
391
435
|
return handleToolError(err);
|
|
@@ -393,35 +437,19 @@ function registerResumeTools(server2, client2) {
|
|
|
393
437
|
}
|
|
394
438
|
);
|
|
395
439
|
server2.tool(
|
|
396
|
-
"master-resume-
|
|
397
|
-
"
|
|
440
|
+
"master-resume-upsert",
|
|
441
|
+
"Create or replace the user's master resume (upsert). The master resume is used as the default resume for job-hunter-run when no other resume is provided. Overwrites any existing master resume. Requires scope: resume:write. Use master-resume-get to check if one already exists. Use resume-parse to extract structured data from a file before saving.",
|
|
398
442
|
{
|
|
399
|
-
|
|
443
|
+
label: z3.string().describe("Label for the master resume"),
|
|
444
|
+
rawText: z3.string().describe("Raw text content of the resume"),
|
|
445
|
+
structuredData: z3.record(z3.unknown()).optional().describe("Optional structured resume data")
|
|
400
446
|
},
|
|
401
447
|
async (params) => {
|
|
402
448
|
try {
|
|
403
|
-
const result = await client2.resume.
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
);
|
|
410
|
-
server2.tool(
|
|
411
|
-
"master-resume-update",
|
|
412
|
-
"Update a master resume by ID. Returns the updated master resume. Requires scope: resume:write.",
|
|
413
|
-
{
|
|
414
|
-
id: z3.string().describe("Master resume ID"),
|
|
415
|
-
name: z3.string().optional().describe("Updated name/label"),
|
|
416
|
-
resume: z3.record(z3.unknown()).optional().describe("Updated resume data object"),
|
|
417
|
-
metadata: z3.record(z3.unknown()).optional().describe("Updated metadata")
|
|
418
|
-
},
|
|
419
|
-
async (params) => {
|
|
420
|
-
try {
|
|
421
|
-
const result = await client2.resume.updateMaster(params.id, {
|
|
422
|
-
...params.name != null && { name: params.name },
|
|
423
|
-
...params.resume != null && { resume: params.resume },
|
|
424
|
-
...params.metadata != null && { metadata: params.metadata }
|
|
449
|
+
const result = await client2.resume.upsertMaster({
|
|
450
|
+
label: params.label,
|
|
451
|
+
rawText: params.rawText,
|
|
452
|
+
...params.structuredData != null && { structuredData: params.structuredData }
|
|
425
453
|
});
|
|
426
454
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
427
455
|
} catch (err) {
|
|
@@ -431,14 +459,12 @@ function registerResumeTools(server2, client2) {
|
|
|
431
459
|
);
|
|
432
460
|
server2.tool(
|
|
433
461
|
"master-resume-delete",
|
|
434
|
-
"
|
|
435
|
-
{
|
|
436
|
-
|
|
437
|
-
},
|
|
438
|
-
async (params) => {
|
|
462
|
+
"Permanently delete the user's master resume. After deletion, agent runs will require a resume to be provided directly. This is irreversible. Requires scope: resume:write. Use master-resume-get to review the resume before deleting.",
|
|
463
|
+
{},
|
|
464
|
+
async () => {
|
|
439
465
|
try {
|
|
440
|
-
await client2.resume.deleteMaster(
|
|
441
|
-
return { content: [{ type: "text", text: JSON.stringify(
|
|
466
|
+
const result = await client2.resume.deleteMaster();
|
|
467
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
442
468
|
} catch (err) {
|
|
443
469
|
return handleToolError(err);
|
|
444
470
|
}
|
|
@@ -451,7 +477,7 @@ import { z as z4 } from "zod";
|
|
|
451
477
|
function registerUploadTools(server2, client2) {
|
|
452
478
|
server2.tool(
|
|
453
479
|
"upload-resume",
|
|
454
|
-
"Upload
|
|
480
|
+
"Upload a resume file (PDF, DOCX, TXT) as base64-encoded content and parse it into structured data. Returns extracted contact info, work experience, education, and skills. Use this as the first step in a job application workflow before running ats-score or job-hunter-run. Max file size ~10 MB. Requires scope: upload:write. For parsing without the upload step, use resume-parse instead.",
|
|
455
481
|
{
|
|
456
482
|
fileBase64: z4.string().max(13981014).describe("Base64-encoded file content (PDF, DOCX, etc.) \u2014 max ~10 MB"),
|
|
457
483
|
filename: z4.string().describe("Original filename with extension (e.g. resume.pdf)"),
|
|
@@ -472,9 +498,9 @@ function registerUploadTools(server2, client2) {
|
|
|
472
498
|
);
|
|
473
499
|
server2.tool(
|
|
474
500
|
"upload-job-file",
|
|
475
|
-
"Upload
|
|
501
|
+
"Upload a job description file (PDF, DOCX, TXT) as base64-encoded content and parse it into structured job data. Returns extracted job title, requirements, qualifications, and company info. Use this when the job description is in a file rather than plain text. Max file size ~10 MB. Requires scope: upload:write. For plain text or URL-based job descriptions, use upload-job-text instead.",
|
|
476
502
|
{
|
|
477
|
-
fileBase64: z4.string().describe("Base64-encoded file content (PDF, DOCX, etc.)"),
|
|
503
|
+
fileBase64: z4.string().max(13981014).describe("Base64-encoded file content (PDF, DOCX, etc.) \u2014 max ~10 MB"),
|
|
478
504
|
filename: z4.string().describe("Original filename with extension"),
|
|
479
505
|
contentType: z4.string().optional().describe("MIME type")
|
|
480
506
|
},
|
|
@@ -493,10 +519,10 @@ function registerUploadTools(server2, client2) {
|
|
|
493
519
|
);
|
|
494
520
|
server2.tool(
|
|
495
521
|
"upload-job-text",
|
|
496
|
-
"
|
|
522
|
+
"Parse a job description from plain text or fetch and parse from a URL. Returns structured job data including title, requirements, and qualifications. Use this when you have the job description as text or a URL to a job posting page. At least one of text or url is required. Requires scope: upload:write. For file-based job descriptions (PDF, DOCX), use upload-job-file instead.",
|
|
497
523
|
{
|
|
498
524
|
text: z4.string().max(5e4).optional().describe("Job description text (max 50K characters). Required if url is not provided."),
|
|
499
|
-
url: z4.string().optional().describe("URL to fetch job description from. Required if text is not provided."),
|
|
525
|
+
url: z4.string().url().max(2048).optional().describe("URL to fetch job description from. Required if text is not provided."),
|
|
500
526
|
source: z4.string().optional().describe("Source label/identifier for the job posting")
|
|
501
527
|
},
|
|
502
528
|
async (params) => {
|
|
@@ -525,15 +551,15 @@ import { z as z5 } from "zod";
|
|
|
525
551
|
function registerSessionTools(server2, client2) {
|
|
526
552
|
server2.tool(
|
|
527
553
|
"session-create",
|
|
528
|
-
"Create a new session. Returns the
|
|
554
|
+
"Create a new session for grouping agent runs and their artifacts. Returns the session object with its ID. Sessions organize multiple generations (agent runs) into a logical workspace. Use this before running job-hunter-run or b2b-sales-run with a specific sessionId. Requires scope: sessions:write.",
|
|
529
555
|
{
|
|
530
|
-
|
|
556
|
+
sessionId: z5.string().optional().describe("Optional client-generated session ID"),
|
|
531
557
|
metadata: z5.record(z5.unknown()).optional().describe("Optional session metadata")
|
|
532
558
|
},
|
|
533
559
|
async (params) => {
|
|
534
560
|
try {
|
|
535
561
|
const result = await client2.sessions.create({
|
|
536
|
-
|
|
562
|
+
...params.sessionId != null && { sessionId: params.sessionId },
|
|
537
563
|
...params.metadata != null && { metadata: params.metadata }
|
|
538
564
|
});
|
|
539
565
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
@@ -544,18 +570,16 @@ function registerSessionTools(server2, client2) {
|
|
|
544
570
|
);
|
|
545
571
|
server2.tool(
|
|
546
572
|
"session-list",
|
|
547
|
-
"List sessions with
|
|
573
|
+
"List sessions with cursor-based pagination. Returns session objects with IDs, creation dates, and metadata. Use this to browse existing sessions or find a session to resume. When limit is provided, returns a paginated envelope with a cursor for the next page. Read-only, no side effects. Requires scope: sessions:read. Use session-get or session-hydrate to get full details for a specific session.",
|
|
548
574
|
{
|
|
549
|
-
|
|
550
|
-
limit: z5.number().optional().describe("Number of sessions per page")
|
|
551
|
-
agentType: z5.string().optional().describe("Filter by agent type (job-hunter or b2b-sales)")
|
|
575
|
+
cursor: z5.string().optional().describe("Cursor for pagination (ISO 8601 datetime string)"),
|
|
576
|
+
limit: z5.number().min(1).max(50).optional().describe("Number of sessions per page (1-50)")
|
|
552
577
|
},
|
|
553
578
|
async (params) => {
|
|
554
579
|
try {
|
|
555
580
|
const result = await client2.sessions.list({
|
|
556
|
-
|
|
557
|
-
limit: params.limit
|
|
558
|
-
agentType: params.agentType
|
|
581
|
+
...params.cursor != null && { cursor: params.cursor },
|
|
582
|
+
...params.limit != null && { limit: params.limit }
|
|
559
583
|
});
|
|
560
584
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
561
585
|
} catch (err) {
|
|
@@ -565,7 +589,7 @@ function registerSessionTools(server2, client2) {
|
|
|
565
589
|
);
|
|
566
590
|
server2.tool(
|
|
567
591
|
"session-get",
|
|
568
|
-
"Get a session by ID
|
|
592
|
+
"Get a session by ID, returning the session object with its generation history (list of agent runs). Use this to check what generations exist in a session without loading full artifacts. Read-only, no side effects. Requires scope: sessions:read. For full session data including all artifacts and logs, use session-hydrate instead.",
|
|
569
593
|
{
|
|
570
594
|
id: z5.string().describe("Session ID")
|
|
571
595
|
},
|
|
@@ -580,7 +604,7 @@ function registerSessionTools(server2, client2) {
|
|
|
580
604
|
);
|
|
581
605
|
server2.tool(
|
|
582
606
|
"session-hydrate",
|
|
583
|
-
"
|
|
607
|
+
"Load a session with all its artifacts, logs, and generation details. Returns the complete session state including generated CVs, cover letters, emails, and conversation history. Use this to review full agent outputs or prepare artifacts for download. Heavier than session-get, so prefer session-get for lightweight lookups. Read-only, no side effects. Requires scope: sessions:read.",
|
|
584
608
|
{
|
|
585
609
|
id: z5.string().describe("Session ID")
|
|
586
610
|
},
|
|
@@ -595,7 +619,7 @@ function registerSessionTools(server2, client2) {
|
|
|
595
619
|
);
|
|
596
620
|
server2.tool(
|
|
597
621
|
"session-download",
|
|
598
|
-
"Download
|
|
622
|
+
"Download a specific artifact from a session by its storage key. Returns base64-encoded content for binary files (PDF, DOCX, images) or plain text for text files. Use this to retrieve individual generated files like a rendered PDF resume or cover letter. Get artifact keys from session-hydrate first. Read-only, no side effects. Requires scope: sessions:read. For downloading by storage path instead of session context, use document-download.",
|
|
599
623
|
{
|
|
600
624
|
id: z5.string().describe("Session ID"),
|
|
601
625
|
key: z5.string().describe("Artifact storage key from session hydration")
|
|
@@ -627,7 +651,7 @@ function registerSessionTools(server2, client2) {
|
|
|
627
651
|
);
|
|
628
652
|
server2.tool(
|
|
629
653
|
"session-delete",
|
|
630
|
-
"
|
|
654
|
+
"Permanently delete a session and all its generations, artifacts, and logs. This is irreversible. Use this to clean up completed or unwanted sessions. Requires scope: sessions:write. Use session-list to find sessions, and session-hydrate to review contents before deleting.",
|
|
631
655
|
{
|
|
632
656
|
id: z5.string().describe("Session ID")
|
|
633
657
|
},
|
|
@@ -642,7 +666,7 @@ function registerSessionTools(server2, client2) {
|
|
|
642
666
|
);
|
|
643
667
|
server2.tool(
|
|
644
668
|
"session-init",
|
|
645
|
-
"
|
|
669
|
+
"Get the default session configuration, including available agent types, supported features, and default settings. Use this to discover what agents and capabilities are available before creating sessions. Read-only, no side effects. Requires scope: sessions:read.",
|
|
646
670
|
{},
|
|
647
671
|
async () => {
|
|
648
672
|
try {
|
|
@@ -655,7 +679,7 @@ function registerSessionTools(server2, client2) {
|
|
|
655
679
|
);
|
|
656
680
|
server2.tool(
|
|
657
681
|
"session-log",
|
|
658
|
-
"Append a log entry to
|
|
682
|
+
"Append a log entry to an existing session for tracking conversation history, tool usage, or status updates. Creates a new log record in the session. Use this to maintain an audit trail of actions taken during a session. Requires scope: sessions:write. Use session-hydrate to read back the full log history.",
|
|
659
683
|
{
|
|
660
684
|
id: z5.string().describe("Session ID"),
|
|
661
685
|
role: z5.enum(["user", "assistant", "system", "tool", "status"]).describe("Log entry role"),
|
|
@@ -675,6 +699,23 @@ function registerSessionTools(server2, client2) {
|
|
|
675
699
|
}
|
|
676
700
|
}
|
|
677
701
|
);
|
|
702
|
+
server2.tool(
|
|
703
|
+
"session-stats",
|
|
704
|
+
"Get aggregate session statistics for an agent type, including total sessions, active sequences, emails drafted, reply rate, and credits consumed. Use this to review overall usage and performance metrics for job-hunter or b2b-sales workflows. Read-only, no side effects. Requires scope: sessions:read.",
|
|
705
|
+
{
|
|
706
|
+
agentType: z5.enum(["job-hunter", "b2b-sales"]).describe("Agent type to get stats for")
|
|
707
|
+
},
|
|
708
|
+
async (params) => {
|
|
709
|
+
try {
|
|
710
|
+
const result = await client2.sessions.stats({
|
|
711
|
+
agentType: params.agentType
|
|
712
|
+
});
|
|
713
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
714
|
+
} catch (err) {
|
|
715
|
+
return handleToolError(err);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
);
|
|
678
719
|
}
|
|
679
720
|
|
|
680
721
|
// src/tools/settings.ts
|
|
@@ -682,7 +723,7 @@ import { z as z6 } from "zod";
|
|
|
682
723
|
function registerSettingsTools(server2, client2) {
|
|
683
724
|
server2.tool(
|
|
684
725
|
"settings-profile",
|
|
685
|
-
"Get the current user's profile
|
|
726
|
+
"Get the current user's profile including email, name, subscription plan, and remaining credit balance. Use this to check available credits before running agents (job-hunter-run, b2b-sales-run) or to verify account identity. Read-only, no side effects. Requires scope: settings:read. For detailed usage breakdown, use settings-usage-summary instead.",
|
|
686
727
|
{},
|
|
687
728
|
async () => {
|
|
688
729
|
try {
|
|
@@ -695,13 +736,15 @@ function registerSettingsTools(server2, client2) {
|
|
|
695
736
|
);
|
|
696
737
|
server2.tool(
|
|
697
738
|
"settings-preferences-get",
|
|
698
|
-
"Get the current user's preferences. Requires scope: settings:read.",
|
|
739
|
+
"Get the current user's preferences, optionally filtered by agent type. Returns configuration like default themes, generation settings, and notification preferences. Read-only, no side effects. Requires scope: settings:read. Use settings-preferences-update to modify preferences.",
|
|
699
740
|
{
|
|
700
|
-
agentType: z6.string().optional().describe("Filter preferences by agent type (e.g. job-hunter, b2b-sales)
|
|
741
|
+
agentType: z6.string().optional().describe("Filter preferences by agent type (e.g. job-hunter, b2b-sales)")
|
|
701
742
|
},
|
|
702
743
|
async (params) => {
|
|
703
744
|
try {
|
|
704
|
-
const result = await client2.settings.getPreferences(
|
|
745
|
+
const result = await client2.settings.getPreferences(
|
|
746
|
+
params.agentType != null ? { agentType: params.agentType } : void 0
|
|
747
|
+
);
|
|
705
748
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
706
749
|
} catch (err) {
|
|
707
750
|
return handleToolError(err);
|
|
@@ -710,16 +753,17 @@ function registerSettingsTools(server2, client2) {
|
|
|
710
753
|
);
|
|
711
754
|
server2.tool(
|
|
712
755
|
"settings-preferences-update",
|
|
713
|
-
"Update the current user's preferences.
|
|
756
|
+
"Update the current user's preferences, optionally scoped to a specific agent type. Modifies stored preferences and returns the updated values. Use this to configure default themes, generation settings, or notification preferences. Requires scope: settings:write. Use settings-preferences-get first to see current values before updating.",
|
|
714
757
|
{
|
|
715
758
|
preferences: z6.record(z6.unknown()).describe("Preferences object to update"),
|
|
716
|
-
agentType: z6.string().optional().describe("Agent type to scope preferences to (e.g. job-hunter, b2b-sales)
|
|
759
|
+
agentType: z6.string().optional().describe("Agent type to scope preferences to (e.g. job-hunter, b2b-sales)")
|
|
717
760
|
},
|
|
718
761
|
async (params) => {
|
|
719
762
|
try {
|
|
720
|
-
const result = await client2.settings.updatePreferences(
|
|
721
|
-
|
|
722
|
-
|
|
763
|
+
const result = await client2.settings.updatePreferences(
|
|
764
|
+
params.preferences,
|
|
765
|
+
params.agentType != null ? { agentType: params.agentType } : void 0
|
|
766
|
+
);
|
|
723
767
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
724
768
|
} catch (err) {
|
|
725
769
|
return handleToolError(err);
|
|
@@ -728,7 +772,7 @@ function registerSettingsTools(server2, client2) {
|
|
|
728
772
|
);
|
|
729
773
|
server2.tool(
|
|
730
774
|
"settings-usage-summary",
|
|
731
|
-
"Get
|
|
775
|
+
"Get an aggregate summary of the user's API usage and credit consumption, including total credits used, remaining balance, and usage by category. Use this to check credit balance before running agents or to monitor spending. Read-only, no side effects. Requires scope: settings:read. For individual usage entries with timestamps, use settings-usage-logs instead.",
|
|
732
776
|
{},
|
|
733
777
|
async () => {
|
|
734
778
|
try {
|
|
@@ -741,7 +785,7 @@ function registerSettingsTools(server2, client2) {
|
|
|
741
785
|
);
|
|
742
786
|
server2.tool(
|
|
743
787
|
"settings-usage-logs",
|
|
744
|
-
"Get paginated usage logs
|
|
788
|
+
"Get paginated usage logs showing individual entries with action type, credits consumed, and timestamps. Use this to audit specific credit charges or investigate unexpected usage. Read-only, no side effects. Requires scope: settings:read. For an aggregate overview, use settings-usage-summary instead.",
|
|
745
789
|
{
|
|
746
790
|
offset: z6.number().optional().describe("Offset for pagination"),
|
|
747
791
|
limit: z6.number().max(100).optional().describe("Number of entries to return (max 100)")
|
|
@@ -760,9 +804,9 @@ function registerSettingsTools(server2, client2) {
|
|
|
760
804
|
);
|
|
761
805
|
server2.tool(
|
|
762
806
|
"api-key-create",
|
|
763
|
-
"Create a new platform API key. The key value is
|
|
807
|
+
"Create a new platform API key with specified permission scopes. The key value is returned ONLY in this response and cannot be retrieved later, so save it immediately. Creates a new key record. Requires scope: settings:write. Use api-key-list to see existing keys. Use api-key-revoke to delete keys you no longer need.",
|
|
764
808
|
{
|
|
765
|
-
|
|
809
|
+
label: z6.string().describe("Human-readable label for the API key"),
|
|
766
810
|
scopes: z6.array(z6.enum([
|
|
767
811
|
"*",
|
|
768
812
|
"jobs:write",
|
|
@@ -778,7 +822,9 @@ function registerSettingsTools(server2, client2) {
|
|
|
778
822
|
"resume:write",
|
|
779
823
|
"ats:write",
|
|
780
824
|
"webhook:read",
|
|
781
|
-
"webhook:write"
|
|
825
|
+
"webhook:write",
|
|
826
|
+
"outreach:read",
|
|
827
|
+
"outreach:write"
|
|
782
828
|
])).describe("Permission scopes for the key. Use '*' for all scopes."),
|
|
783
829
|
expiresAt: z6.string().optional().describe("Expiration date as ISO 8601 string"),
|
|
784
830
|
monthlyCreditsLimit: z6.number().optional().describe("Monthly credit usage cap for this key")
|
|
@@ -786,7 +832,7 @@ function registerSettingsTools(server2, client2) {
|
|
|
786
832
|
async (params) => {
|
|
787
833
|
try {
|
|
788
834
|
const result = await client2.settings.createApiKey({
|
|
789
|
-
|
|
835
|
+
label: params.label,
|
|
790
836
|
scopes: params.scopes,
|
|
791
837
|
...params.expiresAt != null && { expiresAt: params.expiresAt },
|
|
792
838
|
...params.monthlyCreditsLimit != null && { monthlyCreditsLimit: params.monthlyCreditsLimit }
|
|
@@ -799,7 +845,7 @@ function registerSettingsTools(server2, client2) {
|
|
|
799
845
|
);
|
|
800
846
|
server2.tool(
|
|
801
847
|
"api-key-list",
|
|
802
|
-
"List all platform API keys. Returns key metadata (hash,
|
|
848
|
+
"List all platform API keys for the current user. Returns key metadata (hash, label, scopes, creation date) but NOT the actual key values (those are only shown at creation time). Use this to find key hashes for revocation, rotation, or usage queries. Read-only, no side effects. Requires scope: settings:read.",
|
|
803
849
|
{},
|
|
804
850
|
async () => {
|
|
805
851
|
try {
|
|
@@ -812,7 +858,7 @@ function registerSettingsTools(server2, client2) {
|
|
|
812
858
|
);
|
|
813
859
|
server2.tool(
|
|
814
860
|
"api-key-revoke",
|
|
815
|
-
"
|
|
861
|
+
"Permanently revoke and delete a platform API key by its hash. The key immediately stops working for all API calls. This is irreversible. Use this to remove compromised or unused keys. Requires scope: settings:write. Use api-key-list first to find the key hash. For replacing a key with a new one, use api-key-rotate instead.",
|
|
816
862
|
{
|
|
817
863
|
hash: z6.string().describe("API key hash to revoke")
|
|
818
864
|
},
|
|
@@ -827,14 +873,17 @@ function registerSettingsTools(server2, client2) {
|
|
|
827
873
|
);
|
|
828
874
|
server2.tool(
|
|
829
875
|
"api-key-rotate",
|
|
830
|
-
"Rotate a platform API key
|
|
876
|
+
"Rotate a platform API key by revoking the old key and issuing a new one. The new key value is returned ONLY in this response, so save it immediately. An optional grace period keeps the old key valid during transition. Use this for periodic key rotation or when a key may be compromised but you need continuity. Requires scope: settings:write. For immediate revocation without replacement, use api-key-revoke instead.",
|
|
831
877
|
{
|
|
832
878
|
hash: z6.string().describe("API key hash to rotate"),
|
|
833
|
-
gracePeriodHours: z6.number().optional().describe("Hours the old key remains valid after rotation (default: 24)
|
|
879
|
+
gracePeriodHours: z6.number().optional().describe("Hours the old key remains valid after rotation (default: 24)")
|
|
834
880
|
},
|
|
835
881
|
async (params) => {
|
|
836
882
|
try {
|
|
837
|
-
const result = await client2.settings.rotateApiKey(
|
|
883
|
+
const result = await client2.settings.rotateApiKey(
|
|
884
|
+
params.hash,
|
|
885
|
+
params.gracePeriodHours != null ? { gracePeriodHours: params.gracePeriodHours } : void 0
|
|
886
|
+
);
|
|
838
887
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
839
888
|
} catch (err) {
|
|
840
889
|
return handleToolError(err);
|
|
@@ -843,16 +892,13 @@ function registerSettingsTools(server2, client2) {
|
|
|
843
892
|
);
|
|
844
893
|
server2.tool(
|
|
845
894
|
"api-key-usage",
|
|
846
|
-
"Get usage statistics for a specific API key by its hash. Requires scope: settings:read.
|
|
895
|
+
"Get usage statistics for a specific API key by its hash, including request counts and credit consumption. Use this to monitor per-key usage or identify which key is consuming the most credits. Read-only, no side effects. Requires scope: settings:read. Use api-key-list to find key hashes.",
|
|
847
896
|
{
|
|
848
897
|
hash: z6.string().describe("API key hash")
|
|
849
898
|
},
|
|
850
899
|
async (params) => {
|
|
851
900
|
try {
|
|
852
|
-
const
|
|
853
|
-
const result = await httpClient.request(
|
|
854
|
-
`/settings/platform-api-keys/${encodeURIComponent(params.hash)}/usage`
|
|
855
|
-
);
|
|
901
|
+
const result = await client2.settings.getApiKeyUsage(params.hash);
|
|
856
902
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
857
903
|
} catch (err) {
|
|
858
904
|
return handleToolError(err);
|
|
@@ -861,11 +907,11 @@ function registerSettingsTools(server2, client2) {
|
|
|
861
907
|
);
|
|
862
908
|
server2.tool(
|
|
863
909
|
"byo-key-get",
|
|
864
|
-
"Check
|
|
910
|
+
"Check the configuration status of all Bring Your Own (BYO) API keys. Returns each provider name and whether a key is configured. Use this to verify BYO key setup before running agents with tier=byo. Read-only, no side effects. Requires scope: settings:read. Use settings-supported-providers to see which providers are available. Use byo-key-set to configure a key.",
|
|
865
911
|
{},
|
|
866
912
|
async () => {
|
|
867
913
|
try {
|
|
868
|
-
const result = await client2.settings.
|
|
914
|
+
const result = await client2.settings.getProviderKeyStatus();
|
|
869
915
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
870
916
|
} catch (err) {
|
|
871
917
|
return handleToolError(err);
|
|
@@ -874,16 +920,17 @@ function registerSettingsTools(server2, client2) {
|
|
|
874
920
|
);
|
|
875
921
|
server2.tool(
|
|
876
922
|
"byo-key-set",
|
|
877
|
-
"
|
|
923
|
+
"Configure a Bring Your Own (BYO) API key for an AI provider (e.g. gemini). BYO tier users get unlimited AI generation but still pay for contact enrichment credits. Stores the key securely on the platform. Requires scope: settings:write. Use settings-supported-providers to see available providers. Use byo-key-get to check current configuration. Use byo-key-remove to delete a configured key.",
|
|
878
924
|
{
|
|
925
|
+
provider: z6.string().describe("Provider name (e.g. gemini)"),
|
|
879
926
|
apiKey: z6.string().describe("The API key to set"),
|
|
880
|
-
|
|
927
|
+
baseUrl: z6.string().optional().describe("Optional custom base URL for the provider")
|
|
881
928
|
},
|
|
882
929
|
async (params) => {
|
|
883
930
|
try {
|
|
884
|
-
const result = await client2.settings.
|
|
931
|
+
const result = await client2.settings.setProviderKey(params.provider, {
|
|
885
932
|
apiKey: params.apiKey,
|
|
886
|
-
|
|
933
|
+
...params.baseUrl != null && { baseUrl: params.baseUrl }
|
|
887
934
|
});
|
|
888
935
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
889
936
|
} catch (err) {
|
|
@@ -893,12 +940,27 @@ function registerSettingsTools(server2, client2) {
|
|
|
893
940
|
);
|
|
894
941
|
server2.tool(
|
|
895
942
|
"byo-key-remove",
|
|
896
|
-
"Remove
|
|
943
|
+
"Remove a configured Bring Your Own (BYO) API key for a provider. After removal, agent runs will use platform credits instead of the BYO key. Requires scope: settings:write. Use byo-key-get to check which providers have keys configured before removing.",
|
|
944
|
+
{
|
|
945
|
+
provider: z6.string().describe("Provider name to remove the key for (e.g. gemini)")
|
|
946
|
+
},
|
|
947
|
+
async (params) => {
|
|
948
|
+
try {
|
|
949
|
+
const result = await client2.settings.removeProviderKey(params.provider);
|
|
950
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
951
|
+
} catch (err) {
|
|
952
|
+
return handleToolError(err);
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
);
|
|
956
|
+
server2.tool(
|
|
957
|
+
"settings-supported-providers",
|
|
958
|
+
"List all AI providers that support Bring Your Own (BYO) API keys, including provider names and availability status. Use this to discover which providers can be configured with byo-key-set before setting up BYO keys. Read-only, no side effects. Requires scope: settings:read.",
|
|
897
959
|
{},
|
|
898
960
|
async () => {
|
|
899
961
|
try {
|
|
900
|
-
await client2.settings.
|
|
901
|
-
return { content: [{ type: "text", text: JSON.stringify(
|
|
962
|
+
const result = await client2.settings.getSupportedProviders();
|
|
963
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
902
964
|
} catch (err) {
|
|
903
965
|
return handleToolError(err);
|
|
904
966
|
}
|
|
@@ -906,7 +968,7 @@ function registerSettingsTools(server2, client2) {
|
|
|
906
968
|
);
|
|
907
969
|
server2.tool(
|
|
908
970
|
"webhook-secret-get",
|
|
909
|
-
"Get the current webhook secret
|
|
971
|
+
"Get the current webhook signing secret used to verify webhook payloads from the LLM Conveyors platform. Use this when setting up webhook receivers to validate that incoming webhooks are authentic. Read-only, no side effects. Requires scope: webhook:read. Use webhook-secret-rotate to generate a new secret if the current one is compromised.",
|
|
910
972
|
{},
|
|
911
973
|
async () => {
|
|
912
974
|
try {
|
|
@@ -919,7 +981,7 @@ function registerSettingsTools(server2, client2) {
|
|
|
919
981
|
);
|
|
920
982
|
server2.tool(
|
|
921
983
|
"webhook-secret-rotate",
|
|
922
|
-
"Rotate the webhook secret
|
|
984
|
+
"Rotate the webhook signing secret, generating a new one and immediately invalidating the old secret. All existing webhook receivers must be updated with the new secret or they will reject incoming payloads. Rate limited: 5 per hour. Requires scope: webhook:write. Use webhook-secret-get to retrieve the current secret before rotating.",
|
|
923
985
|
{},
|
|
924
986
|
async () => {
|
|
925
987
|
try {
|
|
@@ -937,7 +999,7 @@ import { z as z7 } from "zod";
|
|
|
937
999
|
function registerContentTools(server2, client2) {
|
|
938
1000
|
server2.tool(
|
|
939
1001
|
"content-save",
|
|
940
|
-
"Save a source document
|
|
1002
|
+
"Save a source document that will be used as context in future AI generation runs (job-hunter-run, b2b-sales-run). Overwrites any existing document of the same type. Use this to store your CV, cover letter templates, or strategy documents before running agents. Requires scope: sessions:write. Use content-list-sources to see what is already saved. Use content-get-source to read a specific saved document.",
|
|
941
1003
|
{
|
|
942
1004
|
docType: z7.enum([
|
|
943
1005
|
"original_cv",
|
|
@@ -965,18 +1027,14 @@ function registerContentTools(server2, client2) {
|
|
|
965
1027
|
);
|
|
966
1028
|
server2.tool(
|
|
967
1029
|
"content-delete-generation",
|
|
968
|
-
"
|
|
1030
|
+
"Permanently delete a generation and all its artifacts (CV, cover letter, emails) from a session. This is irreversible and removes all files associated with that generation. Use this to clean up unwanted outputs. Requires scope: sessions:write. Use session-hydrate first to review the generation before deleting.",
|
|
969
1031
|
{
|
|
970
1032
|
id: z7.string().describe("Generation ID to delete"),
|
|
971
1033
|
sessionId: z7.string().describe("Session ID that owns the generation")
|
|
972
1034
|
},
|
|
973
1035
|
async (params) => {
|
|
974
1036
|
try {
|
|
975
|
-
const
|
|
976
|
-
const result = await httpClient.request(
|
|
977
|
-
`/content/generations/${encodeURIComponent(params.id)}`,
|
|
978
|
-
{ method: "DELETE", query: { sessionId: params.sessionId } }
|
|
979
|
-
);
|
|
1037
|
+
const result = await client2.content.deleteGeneration(params.id, params.sessionId);
|
|
980
1038
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
981
1039
|
} catch (err) {
|
|
982
1040
|
return handleToolError(err);
|
|
@@ -985,21 +1043,23 @@ function registerContentTools(server2, client2) {
|
|
|
985
1043
|
);
|
|
986
1044
|
server2.tool(
|
|
987
1045
|
"content-research-sender",
|
|
988
|
-
"Research and create a sender profile for content generation. Returns sender context. Requires scope:
|
|
1046
|
+
"Research a company and create a sender profile for personalized content generation. Returns structured sender context (company info, positioning, value propositions). Use this before b2b-sales-run to pre-populate sender context for better outreach personalization. Consumes credits. At least one of companyWebsite or companyName must be provided. Requires scope: sessions:write.",
|
|
989
1047
|
{
|
|
990
1048
|
companyWebsite: z7.string().optional().describe("Company website to research"),
|
|
991
1049
|
companyName: z7.string().optional().describe("Company name for context")
|
|
992
1050
|
},
|
|
993
1051
|
async (params) => {
|
|
994
1052
|
try {
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1053
|
+
if (!params.companyWebsite && !params.companyName) {
|
|
1054
|
+
return {
|
|
1055
|
+
content: [{ type: "text", text: JSON.stringify({ error: "At least one of companyWebsite or companyName is required" }, null, 2) }],
|
|
1056
|
+
isError: true
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
const body = {};
|
|
1060
|
+
if (params.companyWebsite != null) body.companyWebsite = params.companyWebsite;
|
|
1061
|
+
if (params.companyName != null) body.companyName = params.companyName;
|
|
1062
|
+
const result = await client2.content.researchSender(body);
|
|
1003
1063
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1004
1064
|
} catch (err) {
|
|
1005
1065
|
return handleToolError(err);
|
|
@@ -1008,12 +1068,11 @@ function registerContentTools(server2, client2) {
|
|
|
1008
1068
|
);
|
|
1009
1069
|
server2.tool(
|
|
1010
1070
|
"content-list-sources",
|
|
1011
|
-
"List all saved source documents used as context for AI generation. Requires scope:
|
|
1071
|
+
"List all saved source documents used as context for AI generation, showing document types and metadata. Use this to check what context documents are available before running agents. Read-only, no side effects. Requires scope: sessions:read. Use content-get-source to read a specific document. Use content-save to add or update documents.",
|
|
1012
1072
|
{},
|
|
1013
1073
|
async () => {
|
|
1014
1074
|
try {
|
|
1015
|
-
const
|
|
1016
|
-
const result = await httpClient.request("/content/sources");
|
|
1075
|
+
const result = await client2.content.listSources();
|
|
1017
1076
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1018
1077
|
} catch (err) {
|
|
1019
1078
|
return handleToolError(err);
|
|
@@ -1022,7 +1081,7 @@ function registerContentTools(server2, client2) {
|
|
|
1022
1081
|
);
|
|
1023
1082
|
server2.tool(
|
|
1024
1083
|
"content-get-source",
|
|
1025
|
-
"
|
|
1084
|
+
"Retrieve the full content of a specific saved source document by type (e.g. original_cv, cv_strategy, cold_email_strategy). Use this to review or display a previously saved context document. Read-only, no side effects. Requires scope: sessions:read. Use content-list-sources to see all available document types.",
|
|
1026
1085
|
{
|
|
1027
1086
|
docType: z7.enum([
|
|
1028
1087
|
"original_cv",
|
|
@@ -1037,8 +1096,7 @@ function registerContentTools(server2, client2) {
|
|
|
1037
1096
|
},
|
|
1038
1097
|
async (params) => {
|
|
1039
1098
|
try {
|
|
1040
|
-
const
|
|
1041
|
-
const result = await httpClient.request(`/content/sources/${encodeURIComponent(params.docType)}`);
|
|
1099
|
+
const result = await client2.content.getSource(params.docType);
|
|
1042
1100
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1043
1101
|
} catch (err) {
|
|
1044
1102
|
return handleToolError(err);
|
|
@@ -1047,7 +1105,7 @@ function registerContentTools(server2, client2) {
|
|
|
1047
1105
|
);
|
|
1048
1106
|
server2.tool(
|
|
1049
1107
|
"content-delete-source",
|
|
1050
|
-
"
|
|
1108
|
+
"Permanently delete a saved source document by type. Future agent runs will no longer use this document as context. Use this to remove outdated context documents before saving new ones. Requires scope: sessions:write. Use content-list-sources to verify which documents exist before deleting.",
|
|
1051
1109
|
{
|
|
1052
1110
|
docType: z7.enum([
|
|
1053
1111
|
"original_cv",
|
|
@@ -1062,11 +1120,8 @@ function registerContentTools(server2, client2) {
|
|
|
1062
1120
|
},
|
|
1063
1121
|
async (params) => {
|
|
1064
1122
|
try {
|
|
1065
|
-
const
|
|
1066
|
-
|
|
1067
|
-
method: "DELETE"
|
|
1068
|
-
});
|
|
1069
|
-
return { content: [{ type: "text", text: JSON.stringify(result ?? { success: true, message: "Source deleted", docType: params.docType }, null, 2) }] };
|
|
1123
|
+
const result = await client2.content.deleteSource(params.docType);
|
|
1124
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1070
1125
|
} catch (err) {
|
|
1071
1126
|
return handleToolError(err);
|
|
1072
1127
|
}
|
|
@@ -1079,7 +1134,7 @@ import { z as z8 } from "zod";
|
|
|
1079
1134
|
function registerSharesTools(server2, client2) {
|
|
1080
1135
|
server2.tool(
|
|
1081
1136
|
"share-create",
|
|
1082
|
-
"Create a shareable public link for a generation's artifacts. Returns a slug and public URL. Requires scope: sessions:
|
|
1137
|
+
"Create a shareable public link for a generation's artifacts (resume, cover letter, emails). Returns a slug and public URL that anyone can view without authentication. Creates a new share record. Requires scope: sessions:read. Use after running job-hunter-run or b2b-sales-run to share the output. Use share-slug-stats to track views.",
|
|
1083
1138
|
{
|
|
1084
1139
|
sessionId: z8.string().describe("Session ID containing the generation"),
|
|
1085
1140
|
generationId: z8.string().describe("Generation ID to share")
|
|
@@ -1098,7 +1153,7 @@ function registerSharesTools(server2, client2) {
|
|
|
1098
1153
|
);
|
|
1099
1154
|
server2.tool(
|
|
1100
1155
|
"share-stats",
|
|
1101
|
-
"Get statistics about
|
|
1156
|
+
"Get aggregate statistics about all shared links for the current user, including total shares and total views. Use this for an overview of sharing activity. Read-only, no side effects. Requires scope: sessions:read. For per-link stats, use share-slug-stats with a specific slug.",
|
|
1102
1157
|
{},
|
|
1103
1158
|
async () => {
|
|
1104
1159
|
try {
|
|
@@ -1111,7 +1166,7 @@ function registerSharesTools(server2, client2) {
|
|
|
1111
1166
|
);
|
|
1112
1167
|
server2.tool(
|
|
1113
1168
|
"share-get-public",
|
|
1114
|
-
"
|
|
1169
|
+
"Retrieve a publicly shared resource by its slug. Returns the shared artifacts (resume, cover letter, emails) without requiring authentication. Use this to view what a share link contains. Read-only, no side effects. No auth required (public endpoint).",
|
|
1115
1170
|
{
|
|
1116
1171
|
slug: z8.string().describe("Public share slug")
|
|
1117
1172
|
},
|
|
@@ -1126,16 +1181,13 @@ function registerSharesTools(server2, client2) {
|
|
|
1126
1181
|
);
|
|
1127
1182
|
server2.tool(
|
|
1128
1183
|
"share-slug-stats",
|
|
1129
|
-
"Get visit statistics for a specific share link
|
|
1184
|
+
"Get visit statistics for a specific share link, including view count and visit timestamps. Only accessible by the share owner. Use this to track engagement on a specific shared artifact. Read-only, no side effects. Requires scope: sessions:read. For aggregate stats across all shares, use share-stats instead.",
|
|
1130
1185
|
{
|
|
1131
1186
|
slug: z8.string().describe("Share link slug")
|
|
1132
1187
|
},
|
|
1133
1188
|
async (params) => {
|
|
1134
1189
|
try {
|
|
1135
|
-
const
|
|
1136
|
-
const result = await httpClient.request(
|
|
1137
|
-
`/shares/${encodeURIComponent(params.slug)}/stats`
|
|
1138
|
-
);
|
|
1190
|
+
const result = await client2.shares.getShareStats(params.slug);
|
|
1139
1191
|
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
1140
1192
|
} catch (err) {
|
|
1141
1193
|
return handleToolError(err);
|
|
@@ -1149,7 +1201,7 @@ import { z as z9 } from "zod";
|
|
|
1149
1201
|
function registerDocumentTools(server2, client2) {
|
|
1150
1202
|
server2.tool(
|
|
1151
1203
|
"document-download",
|
|
1152
|
-
"Download a document by its storage path. Returns base64-encoded content for binary files (PDF, DOCX, images) or plain text for text files. Requires scope: sessions:read.",
|
|
1204
|
+
"Download a document artifact by its storage path. Returns base64-encoded content for binary files (PDF, DOCX, images) or plain text for text files. Use this to retrieve generated artifacts like rendered resumes or reports when you have the storage path. For downloading artifacts from a specific session, use session-download instead (which takes a session ID and artifact key). Read-only, no side effects. Requires scope: sessions:read.",
|
|
1153
1205
|
{
|
|
1154
1206
|
path: z9.string().describe("Document storage path")
|
|
1155
1207
|
},
|
|
@@ -1185,7 +1237,7 @@ import { z as z10 } from "zod";
|
|
|
1185
1237
|
function registerReferralTools(server2, client2) {
|
|
1186
1238
|
server2.tool(
|
|
1187
1239
|
"referral-stats",
|
|
1188
|
-
"Get referral program statistics including total referrals and credits earned. Requires scope: settings:read.",
|
|
1240
|
+
"Get referral program statistics for the current user, including total referrals, successful conversions, and credits earned. Use this to check referral performance or display earnings. Read-only, no side effects. Requires scope: settings:read. Use referral-code to get the shareable referral link.",
|
|
1189
1241
|
{},
|
|
1190
1242
|
async () => {
|
|
1191
1243
|
try {
|
|
@@ -1198,7 +1250,7 @@ function registerReferralTools(server2, client2) {
|
|
|
1198
1250
|
);
|
|
1199
1251
|
server2.tool(
|
|
1200
1252
|
"referral-code",
|
|
1201
|
-
"Get
|
|
1253
|
+
"Get the current user's referral code and shareable referral link. Use this to retrieve the code for sharing with others. Read-only, no side effects. Requires scope: settings:read. To customize the code, use referral-vanity-code. To check referral performance, use referral-stats.",
|
|
1202
1254
|
{},
|
|
1203
1255
|
async () => {
|
|
1204
1256
|
try {
|
|
@@ -1211,7 +1263,7 @@ function registerReferralTools(server2, client2) {
|
|
|
1211
1263
|
);
|
|
1212
1264
|
server2.tool(
|
|
1213
1265
|
"referral-vanity-code",
|
|
1214
|
-
"Set a custom vanity code for
|
|
1266
|
+
"Set a custom vanity code for the user's referral link, replacing the auto-generated code. This permanently changes the referral URL. Rate limited: 5 per hour. Requires scope: settings:write. Use referral-code first to see the current code before changing it.",
|
|
1215
1267
|
{
|
|
1216
1268
|
code: z10.string().describe("Custom vanity code to set")
|
|
1217
1269
|
},
|
|
@@ -1239,7 +1291,7 @@ var CONSENT_PURPOSES = [
|
|
|
1239
1291
|
function registerPrivacyTools(server2, client2) {
|
|
1240
1292
|
server2.tool(
|
|
1241
1293
|
"privacy-list-consents",
|
|
1242
|
-
"List all privacy consent
|
|
1294
|
+
"List all privacy consent records for the current user, showing each data processing purpose and whether consent is granted or revoked. Use this to check consent status before running tools that require specific consents (e.g. ai-generation, contact-enrichment). Read-only, no side effects. Requires scope: settings:read.",
|
|
1243
1295
|
{},
|
|
1244
1296
|
async () => {
|
|
1245
1297
|
try {
|
|
@@ -1252,7 +1304,7 @@ function registerPrivacyTools(server2, client2) {
|
|
|
1252
1304
|
);
|
|
1253
1305
|
server2.tool(
|
|
1254
1306
|
"privacy-grant-consent",
|
|
1255
|
-
"Grant consent for a specific data processing purpose. Requires scope: settings:write.",
|
|
1307
|
+
"Grant consent for a specific data processing purpose. This enables the platform to process data for that purpose (e.g. ai-generation enables agent runs, contact-enrichment enables contact lookups). Modifies the user's consent record. Requires scope: settings:write. Use privacy-list-consents to check current status first. Use privacy-revoke-consent to undo.",
|
|
1256
1308
|
{
|
|
1257
1309
|
purpose: z11.enum(CONSENT_PURPOSES).describe("Consent purpose to grant")
|
|
1258
1310
|
},
|
|
@@ -1267,7 +1319,7 @@ function registerPrivacyTools(server2, client2) {
|
|
|
1267
1319
|
);
|
|
1268
1320
|
server2.tool(
|
|
1269
1321
|
"privacy-revoke-consent",
|
|
1270
|
-
"Revoke consent for a specific data processing purpose. Requires scope: settings:write.",
|
|
1322
|
+
"Revoke a previously granted consent for a specific data processing purpose. This may disable platform features that depend on that consent (e.g. revoking ai-generation prevents agent runs). Modifies the user's consent record. Requires scope: settings:write. Use privacy-list-consents to check current status first.",
|
|
1271
1323
|
{
|
|
1272
1324
|
purpose: z11.enum(CONSENT_PURPOSES).describe("Consent purpose to revoke")
|
|
1273
1325
|
},
|
|
@@ -1286,7 +1338,7 @@ function registerPrivacyTools(server2, client2) {
|
|
|
1286
1338
|
function registerHealthTools(server2, client2) {
|
|
1287
1339
|
server2.tool(
|
|
1288
1340
|
"health-root",
|
|
1289
|
-
"Get API
|
|
1341
|
+
"Get the LLM Conveyors API server name and version. Use this to verify the MCP server is connected and reachable before running other tools. No authentication required. Returns JSON with name and version fields. For deeper diagnostics, use health-check instead.",
|
|
1290
1342
|
{},
|
|
1291
1343
|
async () => {
|
|
1292
1344
|
try {
|
|
@@ -1299,7 +1351,7 @@ function registerHealthTools(server2, client2) {
|
|
|
1299
1351
|
);
|
|
1300
1352
|
server2.tool(
|
|
1301
1353
|
"health-check",
|
|
1302
|
-
"
|
|
1354
|
+
"Run a detailed health check on the LLM Conveyors API, returning status, uptime, version, dependency checks, and memory usage. Use this to diagnose connectivity or performance issues before retrying failed tool calls. No authentication required. For a simple alive/dead check, use health-live instead.",
|
|
1303
1355
|
{},
|
|
1304
1356
|
async () => {
|
|
1305
1357
|
try {
|
|
@@ -1312,7 +1364,7 @@ function registerHealthTools(server2, client2) {
|
|
|
1312
1364
|
);
|
|
1313
1365
|
server2.tool(
|
|
1314
1366
|
"health-ready",
|
|
1315
|
-
"Check API readiness.
|
|
1367
|
+
"Check whether the LLM Conveyors API is ready to accept requests (all dependencies initialized). Use this in automation pipelines to wait for readiness before sending agent runs. No authentication required. Returns a simple ready/not-ready status. For process liveness only, use health-live instead.",
|
|
1316
1368
|
{},
|
|
1317
1369
|
async () => {
|
|
1318
1370
|
try {
|
|
@@ -1325,7 +1377,7 @@ function registerHealthTools(server2, client2) {
|
|
|
1325
1377
|
);
|
|
1326
1378
|
server2.tool(
|
|
1327
1379
|
"health-live",
|
|
1328
|
-
"Check API
|
|
1380
|
+
"Check whether the LLM Conveyors API process is alive and responding. Use this as a lightweight heartbeat check in monitoring or retry loops. No authentication required. Returns a simple alive status. For dependency-level diagnostics, use health-check instead.",
|
|
1329
1381
|
{},
|
|
1330
1382
|
async () => {
|
|
1331
1383
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llmconveyors-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"mcpName": "io.github.ebenezer-isaac/llmconveyors",
|
|
5
5
|
"description": "MCP server that connects AI agents to LLM Conveyors — run Job Hunter, B2B Sales, and other AI agents from Claude, Cursor, or any MCP client",
|
|
6
6
|
"type": "module",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
54
|
-
"llmconveyors": "^0.
|
|
54
|
+
"llmconveyors": "^0.3.0",
|
|
55
55
|
"zod": "^3.24.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|