llmconveyors-mcp 0.3.0 → 0.3.1
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 +216 -164
- 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) {
|
|
@@ -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) {
|
|
@@ -209,8 +276,6 @@ function registerAtsTools(server2, client2) {
|
|
|
209
276
|
"ats-score",
|
|
210
277
|
"Score a resume against a job description for ATS compatibility. Returns overall score, grade, keyword matches, and improvement suggestions. Consumes credits. Requires scope: ats:write.",
|
|
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")
|
|
@@ -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 master resume. Returns the master resume with label, rawText, and structuredData. Requires scope: resume:read.",
|
|
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). Requires scope: resume:write.",
|
|
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
|
-
"Delete
|
|
435
|
-
{
|
|
436
|
-
|
|
437
|
-
},
|
|
438
|
-
async (params) => {
|
|
462
|
+
"Delete the user's master resume. Requires scope: resume:write.",
|
|
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
|
}
|
|
@@ -474,7 +500,7 @@ function registerUploadTools(server2, client2) {
|
|
|
474
500
|
"upload-job-file",
|
|
475
501
|
"Upload and parse a job description file. Accepts base64-encoded file content. Returns parsed job data. Requires scope: upload:write.",
|
|
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
|
},
|
|
@@ -496,7 +522,7 @@ function registerUploadTools(server2, client2) {
|
|
|
496
522
|
"Upload a job description as plain text or fetch from a URL. At least one of text or url is required. Returns parsed job data. Requires scope: upload:write.",
|
|
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) => {
|
|
@@ -527,13 +553,13 @@ function registerSessionTools(server2, client2) {
|
|
|
527
553
|
"session-create",
|
|
528
554
|
"Create a new session. Returns the created session object with its ID. 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 an array of session objects (or paginated envelope when limit is provided). Requires scope: sessions:read.",
|
|
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) {
|
|
@@ -675,6 +699,23 @@ function registerSessionTools(server2, client2) {
|
|
|
675
699
|
}
|
|
676
700
|
}
|
|
677
701
|
);
|
|
702
|
+
server2.tool(
|
|
703
|
+
"session-stats",
|
|
704
|
+
"Get session statistics (total sessions, active sequences, emails drafted, reply rate, credits used). 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
|
|
@@ -697,11 +738,13 @@ function registerSettingsTools(server2, client2) {
|
|
|
697
738
|
"settings-preferences-get",
|
|
698
739
|
"Get the current user's preferences. Requires scope: settings:read.",
|
|
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);
|
|
@@ -713,13 +756,14 @@ function registerSettingsTools(server2, client2) {
|
|
|
713
756
|
"Update the current user's preferences. Returns the updated preferences. Requires scope: settings:write.",
|
|
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);
|
|
@@ -762,7 +806,7 @@ function registerSettingsTools(server2, client2) {
|
|
|
762
806
|
"api-key-create",
|
|
763
807
|
"Create a new platform API key. The key value is shown ONLY in this response -- save it immediately. Requires scope: settings:write.",
|
|
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 }
|
|
@@ -830,11 +876,14 @@ function registerSettingsTools(server2, client2) {
|
|
|
830
876
|
"Rotate a platform API key -- revokes the old key and returns a new one. Save the new key immediately. Requires scope: settings:write.",
|
|
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. Requires scope: settings:read.",
|
|
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
|
-
"
|
|
910
|
+
"Get the status of all configured BYO provider keys. Returns provider names and their configuration status. Requires scope: settings:read.",
|
|
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
|
-
"Set a Bring Your Own API key for a provider (e.g.
|
|
923
|
+
"Set a Bring Your Own API key for a provider (e.g. gemini). BYO tier users get unlimited AI generation but still pay for contact enrichment. Requires scope: settings:write.",
|
|
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 the configured
|
|
943
|
+
"Remove the configured BYO API key for a provider. Requires scope: settings:write.",
|
|
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 supported BYO key providers. Returns provider names and status. 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
|
}
|
|
@@ -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 for use as context in AI generation. Returns success status. Requires scope:
|
|
1002
|
+
"Save a source document for use as context in AI generation. Returns success status. Requires scope: sessions:write.",
|
|
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
|
-
"Delete a generation and all its artifacts from a session. Requires scope: sessions:write.
|
|
1030
|
+
"Delete a generation and all its artifacts from a session. Requires scope: sessions:write.",
|
|
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 and create a sender profile for content generation. Returns sender context. Requires scope: sessions:write. At least one of companyWebsite or companyName must be provided.",
|
|
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. Requires scope: sessions:read.",
|
|
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
|
-
"Get a specific source document by type. Requires scope:
|
|
1084
|
+
"Get a specific source document by type. Requires scope: sessions:read.",
|
|
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
|
-
"Delete a source document by type. Requires scope:
|
|
1108
|
+
"Delete a source document by type. Requires scope: sessions:write.",
|
|
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. Returns a slug and public URL. Requires scope: sessions:read.",
|
|
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 your shared links (view counts, etc.). Requires scope:
|
|
1156
|
+
"Get statistics about your shared links (view counts, etc.). Requires scope: sessions:read.",
|
|
1102
1157
|
{},
|
|
1103
1158
|
async () => {
|
|
1104
1159
|
try {
|
|
@@ -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 (owner only). Requires scope:
|
|
1184
|
+
"Get visit statistics for a specific share link (owner only). Requires scope: sessions:read.",
|
|
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);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llmconveyors-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
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": {
|