@vantageos/vantage-crm-mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +260 -0
- package/dist/convex/crm/_helpers.js +24 -0
- package/dist/convex/crm/activities.js +220 -0
- package/dist/convex/crm/briefing.js +198 -0
- package/dist/convex/crm/calendarCron.js +92 -0
- package/dist/convex/crm/calendarCronDispatch.js +83 -0
- package/dist/convex/crm/calendarSync.js +294 -0
- package/dist/convex/crm/companies.js +323 -0
- package/dist/convex/crm/contacts.js +346 -0
- package/dist/convex/crm/deals.js +481 -0
- package/dist/convex/crm/emailActions.js +158 -0
- package/dist/convex/crm/emailCron.js +210 -0
- package/dist/convex/crm/emailCronDispatch.js +76 -0
- package/dist/convex/crm/emailSync.js +260 -0
- package/dist/convex/crm/onboarding.js +185 -0
- package/dist/convex/crm/stats.js +75 -0
- package/dist/convex/crm/tasks.js +109 -0
- package/dist/convex/crons.js +25 -0
- package/dist/convex/integrations.js +183 -0
- package/dist/convex/lib/auditLog.js +109 -0
- package/dist/convex/lib/auth.js +372 -0
- package/dist/convex/lib/rbac.js +123 -0
- package/dist/convex/lib/workspace.js +171 -0
- package/dist/convex/organizations.js +192 -0
- package/dist/convex/schema.js +690 -0
- package/dist/convex/users.js +217 -0
- package/dist/convex/workspaces.js +603 -0
- package/dist/mcp-server/lib/convexClient.js +50 -0
- package/dist/mcp-server/lib/scopeEnforcement.js +76 -0
- package/dist/mcp-server/registry.js +116 -0
- package/dist/mcp-server/server.js +97 -0
- package/dist/mcp-server/tests/registry.test.js +163 -0
- package/dist/mcp-server/tests/scopeEnforcement.test.js +137 -0
- package/dist/mcp-server/tests/security.test.js +257 -0
- package/dist/mcp-server/tests/tools.test.js +272 -0
- package/dist/mcp-server/tools/activities.js +207 -0
- package/dist/mcp-server/tools/admin.js +190 -0
- package/dist/mcp-server/tools/companies.js +233 -0
- package/dist/mcp-server/tools/contacts.js +306 -0
- package/dist/mcp-server/tools/customFields.js +222 -0
- package/dist/mcp-server/tools/customObjects.js +235 -0
- package/dist/mcp-server/tools/deals.js +297 -0
- package/dist/mcp-server/tools/rbac.js +177 -0
- package/dist/mcp-server/tools/search.js +155 -0
- package/dist/mcp-server/tools/workflows.js +234 -0
- package/dist/mcp-server/transport/http.js +257 -0
- package/dist/mcp-server/transport/stdio.js +90 -0
- package/package.json +45 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VantageCRM MCP — Activities tools (5 tools)
|
|
4
|
+
*
|
|
5
|
+
* Tools: create_activity, get_activity, update_activity,
|
|
6
|
+
* list_activities, list_activities_by_type
|
|
7
|
+
*
|
|
8
|
+
* Note: NO delete_activity — activities are immutable audit trail (OQ-4).
|
|
9
|
+
* Scope: read for queries, write for mutations
|
|
10
|
+
* Ref: spec §3.5
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.ACTIVITY_TOOLS = void 0;
|
|
14
|
+
exports.create_activity = create_activity;
|
|
15
|
+
exports.get_activity = get_activity;
|
|
16
|
+
exports.update_activity = update_activity;
|
|
17
|
+
exports.list_activities = list_activities;
|
|
18
|
+
exports.list_activities_by_type = list_activities_by_type;
|
|
19
|
+
const zod_1 = require("zod");
|
|
20
|
+
const api_1 = require("../../convex/_generated/api");
|
|
21
|
+
const convexClient_1 = require("../lib/convexClient");
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Zod schemas
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
const ACTIVITY_TYPES = ['call', 'email', 'meeting', 'note', 'task'];
|
|
26
|
+
const CreateActivitySchema = zod_1.z.object({
|
|
27
|
+
workspaceId: zod_1.z.string().min(1),
|
|
28
|
+
type: zod_1.z.enum(ACTIVITY_TYPES),
|
|
29
|
+
subject: zod_1.z.string().min(1).max(500),
|
|
30
|
+
description: zod_1.z.string().max(10000).optional(),
|
|
31
|
+
contactId: zod_1.z.string().optional(),
|
|
32
|
+
dealId: zod_1.z.string().optional(),
|
|
33
|
+
companyId: zod_1.z.string().optional(),
|
|
34
|
+
occurredAt: zod_1.z.number().optional(),
|
|
35
|
+
dueAt: zod_1.z.number().optional(),
|
|
36
|
+
customFields: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
|
|
37
|
+
});
|
|
38
|
+
const GetActivitySchema = zod_1.z.object({
|
|
39
|
+
activityId: zod_1.z.string().min(1),
|
|
40
|
+
});
|
|
41
|
+
const UpdateActivitySchema = zod_1.z.object({
|
|
42
|
+
activityId: zod_1.z.string().min(1),
|
|
43
|
+
description: zod_1.z.string().max(10000).optional(),
|
|
44
|
+
dueAt: zod_1.z.number().optional(),
|
|
45
|
+
completedAt: zod_1.z.number().optional(),
|
|
46
|
+
customFields: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
|
|
47
|
+
});
|
|
48
|
+
const ListActivitiesSchema = zod_1.z.object({
|
|
49
|
+
workspaceId: zod_1.z.string().min(1),
|
|
50
|
+
contactId: zod_1.z.string().optional(),
|
|
51
|
+
dealId: zod_1.z.string().optional(),
|
|
52
|
+
companyId: zod_1.z.string().optional(),
|
|
53
|
+
limit: zod_1.z.number().int().min(1).max(100).default(20),
|
|
54
|
+
});
|
|
55
|
+
const ListActivitiesByTypeSchema = zod_1.z.object({
|
|
56
|
+
workspaceId: zod_1.z.string().min(1),
|
|
57
|
+
type: zod_1.z.enum(ACTIVITY_TYPES),
|
|
58
|
+
since: zod_1.z.number().optional(),
|
|
59
|
+
until: zod_1.z.number().optional(),
|
|
60
|
+
limit: zod_1.z.number().int().min(1).max(100).default(20),
|
|
61
|
+
});
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// Handlers
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
async function create_activity(rawArgs) {
|
|
66
|
+
const args = CreateActivitySchema.parse(rawArgs);
|
|
67
|
+
return (0, convexClient_1.withEnvelope)(() => (0, convexClient_1.getConvexClient)().mutation(api_1.api.crm.activities.create, {
|
|
68
|
+
workspaceId: args.workspaceId,
|
|
69
|
+
type: args.type,
|
|
70
|
+
subject: args.subject,
|
|
71
|
+
description: args.description,
|
|
72
|
+
contactId: args.contactId,
|
|
73
|
+
dealId: args.dealId,
|
|
74
|
+
companyId: args.companyId,
|
|
75
|
+
occurredAt: args.occurredAt,
|
|
76
|
+
dueAt: args.dueAt,
|
|
77
|
+
customFields: args.customFields,
|
|
78
|
+
}));
|
|
79
|
+
}
|
|
80
|
+
async function get_activity(rawArgs) {
|
|
81
|
+
const args = GetActivitySchema.parse(rawArgs);
|
|
82
|
+
return (0, convexClient_1.withEnvelope)(() => (0, convexClient_1.getConvexClient)().query(api_1.api.crm.activities.get, {
|
|
83
|
+
activityId: args.activityId,
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
async function update_activity(rawArgs) {
|
|
87
|
+
const args = UpdateActivitySchema.parse(rawArgs);
|
|
88
|
+
return (0, convexClient_1.withEnvelope)(() => (0, convexClient_1.getConvexClient)().mutation(api_1.api.crm.activities.update, {
|
|
89
|
+
activityId: args.activityId,
|
|
90
|
+
description: args.description,
|
|
91
|
+
dueAt: args.dueAt,
|
|
92
|
+
completedAt: args.completedAt,
|
|
93
|
+
customFields: args.customFields,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
async function list_activities(rawArgs) {
|
|
97
|
+
const args = ListActivitiesSchema.parse(rawArgs);
|
|
98
|
+
return (0, convexClient_1.withEnvelope)(() => (0, convexClient_1.getConvexClient)().query(api_1.api.crm.activities.list, {
|
|
99
|
+
workspaceId: args.workspaceId,
|
|
100
|
+
contactId: args.contactId,
|
|
101
|
+
dealId: args.dealId,
|
|
102
|
+
companyId: args.companyId,
|
|
103
|
+
limit: args.limit,
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
async function list_activities_by_type(rawArgs) {
|
|
107
|
+
const args = ListActivitiesByTypeSchema.parse(rawArgs);
|
|
108
|
+
// listByType is a client-side filter on top of list (Convex layer has list with type filter)
|
|
109
|
+
return (0, convexClient_1.withEnvelope)(async () => {
|
|
110
|
+
const all = await (0, convexClient_1.getConvexClient)().query(api_1.api.crm.activities.list, {
|
|
111
|
+
workspaceId: args.workspaceId,
|
|
112
|
+
limit: 200,
|
|
113
|
+
});
|
|
114
|
+
let results = all.filter((a) => a['type'] === args.type);
|
|
115
|
+
if (args.since !== undefined) {
|
|
116
|
+
results = results.filter((a) => a['occurredAt'] >= args.since);
|
|
117
|
+
}
|
|
118
|
+
if (args.until !== undefined) {
|
|
119
|
+
results = results.filter((a) => a['occurredAt'] <= args.until);
|
|
120
|
+
}
|
|
121
|
+
return results.slice(0, args.limit);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Tool definitions
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
exports.ACTIVITY_TOOLS = [
|
|
128
|
+
{
|
|
129
|
+
name: 'create_activity',
|
|
130
|
+
description: 'Create a CRM activity (call/email/meeting/note/task). Activities are immutable audit trail (OQ-4) — no delete.',
|
|
131
|
+
requiredScope: 'write',
|
|
132
|
+
inputSchema: {
|
|
133
|
+
type: 'object',
|
|
134
|
+
properties: {
|
|
135
|
+
workspaceId: { type: 'string' },
|
|
136
|
+
type: { type: 'string', enum: ['call', 'email', 'meeting', 'note', 'task'] },
|
|
137
|
+
subject: { type: 'string' },
|
|
138
|
+
description: { type: 'string' },
|
|
139
|
+
contactId: { type: 'string' },
|
|
140
|
+
dealId: { type: 'string' },
|
|
141
|
+
companyId: { type: 'string' },
|
|
142
|
+
occurredAt: { type: 'number' },
|
|
143
|
+
dueAt: { type: 'number' },
|
|
144
|
+
customFields: { type: 'object' },
|
|
145
|
+
},
|
|
146
|
+
required: ['workspaceId', 'type', 'subject'],
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: 'get_activity',
|
|
151
|
+
description: 'Retrieve an activity by ID',
|
|
152
|
+
requiredScope: 'read',
|
|
153
|
+
inputSchema: {
|
|
154
|
+
type: 'object',
|
|
155
|
+
properties: { activityId: { type: 'string' } },
|
|
156
|
+
required: ['activityId'],
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: 'update_activity',
|
|
161
|
+
description: 'Update mutable activity fields (description, dueAt, completedAt, customFields). Subject and type are immutable per OQ-4.',
|
|
162
|
+
requiredScope: 'write',
|
|
163
|
+
inputSchema: {
|
|
164
|
+
type: 'object',
|
|
165
|
+
properties: {
|
|
166
|
+
activityId: { type: 'string' },
|
|
167
|
+
description: { type: 'string' },
|
|
168
|
+
dueAt: { type: 'number' },
|
|
169
|
+
completedAt: { type: 'number' },
|
|
170
|
+
customFields: { type: 'object' },
|
|
171
|
+
},
|
|
172
|
+
required: ['activityId'],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: 'list_activities',
|
|
177
|
+
description: 'List activities by workspace/contact/deal/company',
|
|
178
|
+
requiredScope: 'read',
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: 'object',
|
|
181
|
+
properties: {
|
|
182
|
+
workspaceId: { type: 'string' },
|
|
183
|
+
contactId: { type: 'string' },
|
|
184
|
+
dealId: { type: 'string' },
|
|
185
|
+
companyId: { type: 'string' },
|
|
186
|
+
limit: { type: 'number' },
|
|
187
|
+
},
|
|
188
|
+
required: ['workspaceId'],
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: 'list_activities_by_type',
|
|
193
|
+
description: 'Filter activities by type and optional time range',
|
|
194
|
+
requiredScope: 'read',
|
|
195
|
+
inputSchema: {
|
|
196
|
+
type: 'object',
|
|
197
|
+
properties: {
|
|
198
|
+
workspaceId: { type: 'string' },
|
|
199
|
+
type: { type: 'string', enum: ['call', 'email', 'meeting', 'note', 'task'] },
|
|
200
|
+
since: { type: 'number', description: 'Unix ms timestamp' },
|
|
201
|
+
until: { type: 'number', description: 'Unix ms timestamp' },
|
|
202
|
+
limit: { type: 'number' },
|
|
203
|
+
},
|
|
204
|
+
required: ['workspaceId', 'type'],
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
];
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VantageCRM MCP — Admin tools (5 tools)
|
|
4
|
+
*
|
|
5
|
+
* Tools: list_audit_log, get_entity_history, get_actor_history,
|
|
6
|
+
* purge_archived_records, list_workspace_limits
|
|
7
|
+
*
|
|
8
|
+
* All admin tools require scope: admin
|
|
9
|
+
* Ref: spec §3.10
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ADMIN_TOOLS = void 0;
|
|
13
|
+
exports.list_audit_log = list_audit_log;
|
|
14
|
+
exports.get_entity_history = get_entity_history;
|
|
15
|
+
exports.get_actor_history = get_actor_history;
|
|
16
|
+
exports.purge_archived_records = purge_archived_records;
|
|
17
|
+
exports.list_workspace_limits = list_workspace_limits;
|
|
18
|
+
const zod_1 = require("zod");
|
|
19
|
+
const server_1 = require("convex/server");
|
|
20
|
+
const api_1 = require("../../convex/_generated/api");
|
|
21
|
+
const convexClient_1 = require("../lib/convexClient");
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Zod schemas
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
const ListAuditLogSchema = zod_1.z.object({
|
|
26
|
+
workspaceId: zod_1.z.string().min(1),
|
|
27
|
+
entityType: zod_1.z.string().optional(),
|
|
28
|
+
actorId: zod_1.z.string().optional(),
|
|
29
|
+
since: zod_1.z.number().optional(),
|
|
30
|
+
until: zod_1.z.number().optional(),
|
|
31
|
+
limit: zod_1.z.number().int().min(1).max(200).default(50),
|
|
32
|
+
});
|
|
33
|
+
const GetEntityHistorySchema = zod_1.z.object({
|
|
34
|
+
workspaceId: zod_1.z.string().min(1),
|
|
35
|
+
entityType: zod_1.z.string().min(1),
|
|
36
|
+
entityId: zod_1.z.string().min(1),
|
|
37
|
+
});
|
|
38
|
+
const GetActorHistorySchema = zod_1.z.object({
|
|
39
|
+
workspaceId: zod_1.z.string().min(1),
|
|
40
|
+
actorId: zod_1.z.string().min(1),
|
|
41
|
+
since: zod_1.z.number().optional(),
|
|
42
|
+
until: zod_1.z.number().optional(),
|
|
43
|
+
limit: zod_1.z.number().int().min(1).max(200).default(50),
|
|
44
|
+
});
|
|
45
|
+
const PurgeArchivedSchema = zod_1.z.object({
|
|
46
|
+
workspaceId: zod_1.z.string().min(1),
|
|
47
|
+
entityType: zod_1.z.enum(['contact', 'company', 'deal', 'custom_object_record']),
|
|
48
|
+
olderThanDays: zod_1.z.number().int().min(30).default(30),
|
|
49
|
+
});
|
|
50
|
+
const ListWorkspaceLimitsSchema = zod_1.z.object({
|
|
51
|
+
workspaceId: zod_1.z.string().min(1),
|
|
52
|
+
});
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Helpers
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
/** Query audit_log table via Convex HTTP — uses deals.summary as a proxy
|
|
57
|
+
* until a dedicated audit log query is exposed in V0.1.x.
|
|
58
|
+
* Returns stub data with clear attribution until Convex layer ships.
|
|
59
|
+
*/
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Handlers
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
async function list_audit_log(rawArgs) {
|
|
64
|
+
ListAuditLogSchema.parse(rawArgs);
|
|
65
|
+
// Convex layer V0.1.0 does not expose an audit log query via HTTP API yet.
|
|
66
|
+
// The audit_log table is written internally.
|
|
67
|
+
return {
|
|
68
|
+
success: false,
|
|
69
|
+
error: {
|
|
70
|
+
code: 'NOT_IMPLEMENTED',
|
|
71
|
+
message: 'list_audit_log: reserved for V0.2. Convex query crm.auditLog.list not yet exposed.',
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
async function get_entity_history(rawArgs) {
|
|
76
|
+
GetEntityHistorySchema.parse(rawArgs);
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
error: {
|
|
80
|
+
code: 'NOT_IMPLEMENTED',
|
|
81
|
+
message: 'get_entity_history: reserved for V0.2. Convex query crm.auditLog.byEntity not yet exposed.',
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function get_actor_history(rawArgs) {
|
|
86
|
+
GetActorHistorySchema.parse(rawArgs);
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
error: {
|
|
90
|
+
code: 'NOT_IMPLEMENTED',
|
|
91
|
+
message: 'get_actor_history: reserved for V0.2. Convex query crm.auditLog.byActor not yet exposed.',
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async function purge_archived_records(rawArgs) {
|
|
96
|
+
const args = PurgeArchivedSchema.parse(rawArgs);
|
|
97
|
+
// Hard delete of archived records >N days.
|
|
98
|
+
// 30-day grace is enforced server-side in convex/crm/admin.ts purgeArchivedRecords.
|
|
99
|
+
// anyApi is used since crm.admin is not yet in the generated types.
|
|
100
|
+
return (0, convexClient_1.withEnvelope)(() =>
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
102
|
+
(0, convexClient_1.getConvexClient)().mutation(server_1.anyApi.crm.admin.purgeArchivedRecords, {
|
|
103
|
+
workspaceId: args.workspaceId,
|
|
104
|
+
entityType: args.entityType,
|
|
105
|
+
olderThanDays: args.olderThanDays,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
async function list_workspace_limits(rawArgs) {
|
|
109
|
+
const args = ListWorkspaceLimitsSchema.parse(rawArgs);
|
|
110
|
+
// workspaceLimits — proxy to workspace context query which includes subscription info
|
|
111
|
+
return (0, convexClient_1.withEnvelope)(() => (0, convexClient_1.getConvexClient)().query(api_1.api.workspaces.getContext, {
|
|
112
|
+
workspaceId: args.workspaceId,
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// Tool definitions
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
exports.ADMIN_TOOLS = [
|
|
119
|
+
{
|
|
120
|
+
name: 'list_audit_log',
|
|
121
|
+
description: 'List audit log entries with filters (admin only)',
|
|
122
|
+
requiredScope: 'admin',
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: 'object',
|
|
125
|
+
properties: {
|
|
126
|
+
workspaceId: { type: 'string' },
|
|
127
|
+
entityType: { type: 'string' },
|
|
128
|
+
actorId: { type: 'string' },
|
|
129
|
+
since: { type: 'number' },
|
|
130
|
+
until: { type: 'number' },
|
|
131
|
+
limit: { type: 'number' },
|
|
132
|
+
},
|
|
133
|
+
required: ['workspaceId'],
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: 'get_entity_history',
|
|
138
|
+
description: 'Full audit history for a single entity record (admin only)',
|
|
139
|
+
requiredScope: 'admin',
|
|
140
|
+
inputSchema: {
|
|
141
|
+
type: 'object',
|
|
142
|
+
properties: {
|
|
143
|
+
workspaceId: { type: 'string' },
|
|
144
|
+
entityType: { type: 'string' },
|
|
145
|
+
entityId: { type: 'string' },
|
|
146
|
+
},
|
|
147
|
+
required: ['workspaceId', 'entityType', 'entityId'],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: 'get_actor_history',
|
|
152
|
+
description: 'All actions by a specific actor (user or agent) in a workspace (admin only)',
|
|
153
|
+
requiredScope: 'admin',
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: 'object',
|
|
156
|
+
properties: {
|
|
157
|
+
workspaceId: { type: 'string' },
|
|
158
|
+
actorId: { type: 'string' },
|
|
159
|
+
since: { type: 'number' },
|
|
160
|
+
until: { type: 'number' },
|
|
161
|
+
limit: { type: 'number' },
|
|
162
|
+
},
|
|
163
|
+
required: ['workspaceId', 'actorId'],
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'purge_archived_records',
|
|
168
|
+
description: 'Hard delete archived records older than N days (admin only, OQ-4 minimum 30 days grace)',
|
|
169
|
+
requiredScope: 'admin',
|
|
170
|
+
inputSchema: {
|
|
171
|
+
type: 'object',
|
|
172
|
+
properties: {
|
|
173
|
+
workspaceId: { type: 'string' },
|
|
174
|
+
entityType: { type: 'string', enum: ['contact', 'company', 'deal', 'custom_object_record'] },
|
|
175
|
+
olderThanDays: { type: 'number', minimum: 30, default: 30 },
|
|
176
|
+
},
|
|
177
|
+
required: ['workspaceId', 'entityType'],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'list_workspace_limits',
|
|
182
|
+
description: 'List workspace subscription limits and current usage (admin only)',
|
|
183
|
+
requiredScope: 'admin',
|
|
184
|
+
inputSchema: {
|
|
185
|
+
type: 'object',
|
|
186
|
+
properties: { workspaceId: { type: 'string' } },
|
|
187
|
+
required: ['workspaceId'],
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
];
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VantageCRM MCP — Companies tools (6 tools)
|
|
4
|
+
*
|
|
5
|
+
* Tools: create_company, get_company, update_company, list_companies,
|
|
6
|
+
* search_companies, delete_company
|
|
7
|
+
*
|
|
8
|
+
* Scope: read for queries, write for mutations
|
|
9
|
+
* Ref: spec §3.3
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.COMPANY_TOOLS = void 0;
|
|
13
|
+
exports.create_company = create_company;
|
|
14
|
+
exports.get_company = get_company;
|
|
15
|
+
exports.update_company = update_company;
|
|
16
|
+
exports.list_companies = list_companies;
|
|
17
|
+
exports.search_companies = search_companies;
|
|
18
|
+
exports.delete_company = delete_company;
|
|
19
|
+
const zod_1 = require("zod");
|
|
20
|
+
const api_1 = require("../../convex/_generated/api");
|
|
21
|
+
const convexClient_1 = require("../lib/convexClient");
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Zod schemas
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
const COMPANY_SIZE = ['1-10', '11-50', '51-200', '201-1000', '1000+'];
|
|
26
|
+
const CreateCompanySchema = zod_1.z.object({
|
|
27
|
+
workspaceId: zod_1.z.string().min(1),
|
|
28
|
+
name: zod_1.z.string().min(1).max(200),
|
|
29
|
+
domain: zod_1.z.string().max(200).optional(),
|
|
30
|
+
industry: zod_1.z.string().max(100).optional(),
|
|
31
|
+
size: zod_1.z.enum(COMPANY_SIZE).optional(),
|
|
32
|
+
website: zod_1.z.string().url().optional(),
|
|
33
|
+
phone: zod_1.z.string().max(30).optional(),
|
|
34
|
+
address: zod_1.z.string().max(500).optional(),
|
|
35
|
+
description: zod_1.z.string().max(5000).optional(),
|
|
36
|
+
tags: zod_1.z.array(zod_1.z.string()).max(20).optional(),
|
|
37
|
+
notes: zod_1.z.string().max(5000).optional(),
|
|
38
|
+
customFields: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
|
|
39
|
+
});
|
|
40
|
+
const GetCompanySchema = zod_1.z.object({
|
|
41
|
+
companyId: zod_1.z.string().min(1),
|
|
42
|
+
});
|
|
43
|
+
const UpdateCompanySchema = zod_1.z.object({
|
|
44
|
+
companyId: zod_1.z.string().min(1),
|
|
45
|
+
name: zod_1.z.string().min(1).max(200).optional(),
|
|
46
|
+
domain: zod_1.z.string().max(200).optional(),
|
|
47
|
+
industry: zod_1.z.string().max(100).optional(),
|
|
48
|
+
size: zod_1.z.enum(COMPANY_SIZE).optional(),
|
|
49
|
+
website: zod_1.z.string().url().optional(),
|
|
50
|
+
phone: zod_1.z.string().max(30).optional(),
|
|
51
|
+
address: zod_1.z.string().max(500).optional(),
|
|
52
|
+
description: zod_1.z.string().max(5000).optional(),
|
|
53
|
+
tags: zod_1.z.array(zod_1.z.string()).max(20).optional(),
|
|
54
|
+
notes: zod_1.z.string().max(5000).optional(),
|
|
55
|
+
customFields: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).optional(),
|
|
56
|
+
});
|
|
57
|
+
const ListCompaniesSchema = zod_1.z.object({
|
|
58
|
+
workspaceId: zod_1.z.string().min(1),
|
|
59
|
+
industry: zod_1.z.string().optional(),
|
|
60
|
+
limit: zod_1.z.number().int().min(1).max(100).default(20),
|
|
61
|
+
});
|
|
62
|
+
const SearchCompaniesSchema = zod_1.z.object({
|
|
63
|
+
workspaceId: zod_1.z.string().min(1),
|
|
64
|
+
query: zod_1.z.string().min(1).max(200),
|
|
65
|
+
limit: zod_1.z.number().int().min(1).max(50).default(10),
|
|
66
|
+
});
|
|
67
|
+
const DeleteCompanySchema = zod_1.z.object({
|
|
68
|
+
companyId: zod_1.z.string().min(1),
|
|
69
|
+
});
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Handlers
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
async function create_company(rawArgs) {
|
|
74
|
+
const args = CreateCompanySchema.parse(rawArgs);
|
|
75
|
+
return (0, convexClient_1.withEnvelope)(() =>
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
+
(0, convexClient_1.getConvexClient)().mutation(api_1.api.crm.companies.create, {
|
|
78
|
+
workspaceId: args.workspaceId,
|
|
79
|
+
name: args.name,
|
|
80
|
+
domain: args.domain,
|
|
81
|
+
industry: args.industry,
|
|
82
|
+
size: args.size,
|
|
83
|
+
website: args.website,
|
|
84
|
+
phone: args.phone,
|
|
85
|
+
address: args.address,
|
|
86
|
+
description: args.description,
|
|
87
|
+
tags: args.tags,
|
|
88
|
+
notes: args.notes,
|
|
89
|
+
customFields: args.customFields,
|
|
90
|
+
}));
|
|
91
|
+
}
|
|
92
|
+
async function get_company(rawArgs) {
|
|
93
|
+
const args = GetCompanySchema.parse(rawArgs);
|
|
94
|
+
return (0, convexClient_1.withEnvelope)(() =>
|
|
95
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
96
|
+
(0, convexClient_1.getConvexClient)().query(api_1.api.crm.companies.get, {
|
|
97
|
+
companyId: args.companyId,
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
async function update_company(rawArgs) {
|
|
101
|
+
const args = UpdateCompanySchema.parse(rawArgs);
|
|
102
|
+
return (0, convexClient_1.withEnvelope)(() =>
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
104
|
+
(0, convexClient_1.getConvexClient)().mutation(api_1.api.crm.companies.update, {
|
|
105
|
+
companyId: args.companyId,
|
|
106
|
+
name: args.name,
|
|
107
|
+
domain: args.domain,
|
|
108
|
+
industry: args.industry,
|
|
109
|
+
size: args.size,
|
|
110
|
+
website: args.website,
|
|
111
|
+
phone: args.phone,
|
|
112
|
+
address: args.address,
|
|
113
|
+
description: args.description,
|
|
114
|
+
tags: args.tags,
|
|
115
|
+
notes: args.notes,
|
|
116
|
+
customFields: args.customFields,
|
|
117
|
+
}));
|
|
118
|
+
}
|
|
119
|
+
async function list_companies(rawArgs) {
|
|
120
|
+
const args = ListCompaniesSchema.parse(rawArgs);
|
|
121
|
+
return (0, convexClient_1.withEnvelope)(() =>
|
|
122
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
123
|
+
(0, convexClient_1.getConvexClient)().query(api_1.api.crm.companies.list, {
|
|
124
|
+
workspaceId: args.workspaceId,
|
|
125
|
+
industry: args.industry,
|
|
126
|
+
limit: args.limit,
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
async function search_companies(rawArgs) {
|
|
130
|
+
const args = SearchCompaniesSchema.parse(rawArgs);
|
|
131
|
+
return (0, convexClient_1.withEnvelope)(() =>
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
133
|
+
(0, convexClient_1.getConvexClient)().query(api_1.api.crm.companies.search, {
|
|
134
|
+
workspaceId: args.workspaceId,
|
|
135
|
+
query: args.query,
|
|
136
|
+
}));
|
|
137
|
+
}
|
|
138
|
+
async function delete_company(rawArgs) {
|
|
139
|
+
const args = DeleteCompanySchema.parse(rawArgs);
|
|
140
|
+
return (0, convexClient_1.withEnvelope)(() =>
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
142
|
+
(0, convexClient_1.getConvexClient)().mutation(api_1.api.crm.companies.remove, {
|
|
143
|
+
companyId: args.companyId,
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
// ---------------------------------------------------------------------------
|
|
147
|
+
// Tool definitions
|
|
148
|
+
// ---------------------------------------------------------------------------
|
|
149
|
+
exports.COMPANY_TOOLS = [
|
|
150
|
+
{
|
|
151
|
+
name: 'create_company',
|
|
152
|
+
description: 'Create a company record in the CRM',
|
|
153
|
+
requiredScope: 'write',
|
|
154
|
+
inputSchema: {
|
|
155
|
+
type: 'object',
|
|
156
|
+
properties: {
|
|
157
|
+
workspaceId: { type: 'string' },
|
|
158
|
+
name: { type: 'string' },
|
|
159
|
+
domain: { type: 'string' },
|
|
160
|
+
industry: { type: 'string' },
|
|
161
|
+
size: { type: 'string', enum: ['1-10', '11-50', '51-200', '201-1000', '1000+'] },
|
|
162
|
+
website: { type: 'string' },
|
|
163
|
+
description: { type: 'string' },
|
|
164
|
+
customFields: { type: 'object' },
|
|
165
|
+
},
|
|
166
|
+
required: ['workspaceId', 'name'],
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: 'get_company',
|
|
171
|
+
description: 'Retrieve a company by ID',
|
|
172
|
+
requiredScope: 'read',
|
|
173
|
+
inputSchema: {
|
|
174
|
+
type: 'object',
|
|
175
|
+
properties: { companyId: { type: 'string' } },
|
|
176
|
+
required: ['companyId'],
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: 'update_company',
|
|
181
|
+
description: 'Update a company record',
|
|
182
|
+
requiredScope: 'write',
|
|
183
|
+
inputSchema: {
|
|
184
|
+
type: 'object',
|
|
185
|
+
properties: {
|
|
186
|
+
companyId: { type: 'string' },
|
|
187
|
+
name: { type: 'string' },
|
|
188
|
+
domain: { type: 'string' },
|
|
189
|
+
industry: { type: 'string' },
|
|
190
|
+
size: { type: 'string', enum: ['1-10', '11-50', '51-200', '201-1000', '1000+'] },
|
|
191
|
+
},
|
|
192
|
+
required: ['companyId'],
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: 'list_companies',
|
|
197
|
+
description: 'List companies with optional industry filter',
|
|
198
|
+
requiredScope: 'read',
|
|
199
|
+
inputSchema: {
|
|
200
|
+
type: 'object',
|
|
201
|
+
properties: {
|
|
202
|
+
workspaceId: { type: 'string' },
|
|
203
|
+
industry: { type: 'string' },
|
|
204
|
+
limit: { type: 'number' },
|
|
205
|
+
},
|
|
206
|
+
required: ['workspaceId'],
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: 'search_companies',
|
|
211
|
+
description: 'Full-text search companies',
|
|
212
|
+
requiredScope: 'read',
|
|
213
|
+
inputSchema: {
|
|
214
|
+
type: 'object',
|
|
215
|
+
properties: {
|
|
216
|
+
workspaceId: { type: 'string' },
|
|
217
|
+
query: { type: 'string' },
|
|
218
|
+
limit: { type: 'number' },
|
|
219
|
+
},
|
|
220
|
+
required: ['workspaceId', 'query'],
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: 'delete_company',
|
|
225
|
+
description: 'Soft delete a company (isArchived=true)',
|
|
226
|
+
requiredScope: 'write',
|
|
227
|
+
inputSchema: {
|
|
228
|
+
type: 'object',
|
|
229
|
+
properties: { companyId: { type: 'string' } },
|
|
230
|
+
required: ['companyId'],
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
];
|