@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.
Files changed (48) hide show
  1. package/README.md +260 -0
  2. package/dist/convex/crm/_helpers.js +24 -0
  3. package/dist/convex/crm/activities.js +220 -0
  4. package/dist/convex/crm/briefing.js +198 -0
  5. package/dist/convex/crm/calendarCron.js +92 -0
  6. package/dist/convex/crm/calendarCronDispatch.js +83 -0
  7. package/dist/convex/crm/calendarSync.js +294 -0
  8. package/dist/convex/crm/companies.js +323 -0
  9. package/dist/convex/crm/contacts.js +346 -0
  10. package/dist/convex/crm/deals.js +481 -0
  11. package/dist/convex/crm/emailActions.js +158 -0
  12. package/dist/convex/crm/emailCron.js +210 -0
  13. package/dist/convex/crm/emailCronDispatch.js +76 -0
  14. package/dist/convex/crm/emailSync.js +260 -0
  15. package/dist/convex/crm/onboarding.js +185 -0
  16. package/dist/convex/crm/stats.js +75 -0
  17. package/dist/convex/crm/tasks.js +109 -0
  18. package/dist/convex/crons.js +25 -0
  19. package/dist/convex/integrations.js +183 -0
  20. package/dist/convex/lib/auditLog.js +109 -0
  21. package/dist/convex/lib/auth.js +372 -0
  22. package/dist/convex/lib/rbac.js +123 -0
  23. package/dist/convex/lib/workspace.js +171 -0
  24. package/dist/convex/organizations.js +192 -0
  25. package/dist/convex/schema.js +690 -0
  26. package/dist/convex/users.js +217 -0
  27. package/dist/convex/workspaces.js +603 -0
  28. package/dist/mcp-server/lib/convexClient.js +50 -0
  29. package/dist/mcp-server/lib/scopeEnforcement.js +76 -0
  30. package/dist/mcp-server/registry.js +116 -0
  31. package/dist/mcp-server/server.js +97 -0
  32. package/dist/mcp-server/tests/registry.test.js +163 -0
  33. package/dist/mcp-server/tests/scopeEnforcement.test.js +137 -0
  34. package/dist/mcp-server/tests/security.test.js +257 -0
  35. package/dist/mcp-server/tests/tools.test.js +272 -0
  36. package/dist/mcp-server/tools/activities.js +207 -0
  37. package/dist/mcp-server/tools/admin.js +190 -0
  38. package/dist/mcp-server/tools/companies.js +233 -0
  39. package/dist/mcp-server/tools/contacts.js +306 -0
  40. package/dist/mcp-server/tools/customFields.js +222 -0
  41. package/dist/mcp-server/tools/customObjects.js +235 -0
  42. package/dist/mcp-server/tools/deals.js +297 -0
  43. package/dist/mcp-server/tools/rbac.js +177 -0
  44. package/dist/mcp-server/tools/search.js +155 -0
  45. package/dist/mcp-server/tools/workflows.js +234 -0
  46. package/dist/mcp-server/transport/http.js +257 -0
  47. package/dist/mcp-server/transport/stdio.js +90 -0
  48. package/package.json +45 -0
@@ -0,0 +1,192 @@
1
+ "use strict";
2
+ /**
3
+ * Organization management functions
4
+ *
5
+ * Handles syncing Clerk organizations to Convex
6
+ * and organization-specific operations
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.updatePlan = exports.updateSettings = exports.getUserOrganizations = exports.getMembers = exports.getBySlug = exports.getByClerkId = exports.getCurrent = void 0;
10
+ const values_1 = require("convex/values");
11
+ const server_1 = require("./_generated/server");
12
+ const auth_1 = require("./lib/auth");
13
+ /**
14
+ * Get the current organization (if in org context)
15
+ */
16
+ exports.getCurrent = (0, server_1.query)({
17
+ args: {},
18
+ handler: async (ctx) => {
19
+ const workspace = await (0, auth_1.getWorkspaceContext)(ctx);
20
+ const currentOrgId = workspace.orgId;
21
+ if (!currentOrgId) {
22
+ return null;
23
+ }
24
+ return await ctx.db
25
+ .query('organizations')
26
+ .withIndex('by_clerk_id', (q) => q.eq('clerkId', currentOrgId))
27
+ .first();
28
+ },
29
+ });
30
+ /**
31
+ * Get organization by Clerk ID
32
+ */
33
+ exports.getByClerkId = (0, server_1.query)({
34
+ args: { clerkId: values_1.v.string() },
35
+ handler: async (ctx, { clerkId }) => {
36
+ return await ctx.db
37
+ .query('organizations')
38
+ .withIndex('by_clerk_id', (q) => q.eq('clerkId', clerkId))
39
+ .first();
40
+ },
41
+ });
42
+ /**
43
+ * Get organization by slug
44
+ */
45
+ exports.getBySlug = (0, server_1.query)({
46
+ args: { slug: values_1.v.string() },
47
+ handler: async (ctx, { slug }) => {
48
+ return await ctx.db
49
+ .query('organizations')
50
+ .withIndex('by_slug', (q) => q.eq('slug', slug))
51
+ .first();
52
+ },
53
+ });
54
+ /**
55
+ * Get all members of an organization
56
+ */
57
+ exports.getMembers = (0, server_1.query)({
58
+ args: { orgId: values_1.v.id('organizations') },
59
+ handler: async (ctx, { orgId }) => {
60
+ const memberships = await ctx.db
61
+ .query('memberships')
62
+ .withIndex('by_org', (q) => q.eq('orgId', orgId))
63
+ .collect();
64
+ // Get user details for each membership
65
+ const members = await Promise.all(memberships.map(async (membership) => {
66
+ const user = await ctx.db.get(membership.userId);
67
+ return {
68
+ ...membership,
69
+ user: user
70
+ ? {
71
+ _id: user._id,
72
+ name: user.name,
73
+ email: user.email,
74
+ avatarUrl: user.avatarUrl,
75
+ }
76
+ : null,
77
+ };
78
+ }));
79
+ return members;
80
+ },
81
+ });
82
+ /**
83
+ * Get organizations a user belongs to
84
+ */
85
+ exports.getUserOrganizations = (0, server_1.query)({
86
+ args: {},
87
+ handler: async (ctx) => {
88
+ const identity = await ctx.auth.getUserIdentity();
89
+ if (!identity)
90
+ return [];
91
+ // Find user
92
+ const user = await ctx.db
93
+ .query('users')
94
+ .withIndex('by_clerk_id', (q) => q.eq('clerkId', identity.subject))
95
+ .first();
96
+ if (!user)
97
+ return [];
98
+ // Get memberships
99
+ const memberships = await ctx.db
100
+ .query('memberships')
101
+ .withIndex('by_user', (q) => q.eq('userId', user._id))
102
+ .collect();
103
+ // Get org details
104
+ const orgs = await Promise.all(memberships.map(async (membership) => {
105
+ const org = await ctx.db.get(membership.orgId);
106
+ return org
107
+ ? {
108
+ ...org,
109
+ role: membership.role,
110
+ membershipId: membership._id,
111
+ }
112
+ : null;
113
+ }));
114
+ return orgs.filter(Boolean);
115
+ },
116
+ });
117
+ /**
118
+ * Update organization settings (admin only)
119
+ */
120
+ exports.updateSettings = (0, server_1.mutation)({
121
+ args: {
122
+ orgId: values_1.v.id('organizations'),
123
+ settings: values_1.v.object({
124
+ defaultModel: values_1.v.optional(values_1.v.string()),
125
+ allowPersonalTools: values_1.v.optional(values_1.v.boolean()),
126
+ requireApprovalForPublic: values_1.v.optional(values_1.v.boolean()),
127
+ }),
128
+ },
129
+ handler: async (ctx, { orgId, settings }) => {
130
+ const workspace = await (0, auth_1.getWorkspaceContext)(ctx);
131
+ // Verify user is org admin
132
+ const user = await ctx.db
133
+ .query('users')
134
+ .withIndex('by_clerk_id', (q) => q.eq('clerkId', workspace.userId))
135
+ .first();
136
+ if (!user)
137
+ throw new Error('User not found');
138
+ const membership = await ctx.db
139
+ .query('memberships')
140
+ .withIndex('by_user_org', (q) => q.eq('userId', user._id).eq('orgId', orgId))
141
+ .first();
142
+ if (!membership || membership.role !== 'org:admin') {
143
+ throw new Error('Only organization admins can update settings');
144
+ }
145
+ const org = await ctx.db.get(orgId);
146
+ if (!org)
147
+ throw new Error('Organization not found');
148
+ const currentSettings = org.settings || {};
149
+ const newSettings = { ...currentSettings, ...settings };
150
+ await ctx.db.patch(orgId, {
151
+ settings: newSettings,
152
+ updatedAt: Date.now(),
153
+ });
154
+ return { success: true };
155
+ },
156
+ });
157
+ /**
158
+ * Update organization plan (platform admin only)
159
+ */
160
+ exports.updatePlan = (0, server_1.mutation)({
161
+ args: {
162
+ orgId: values_1.v.id('organizations'),
163
+ plan: values_1.v.string(),
164
+ usageLimits: values_1.v.optional(values_1.v.object({
165
+ maxChatsPerMonth: values_1.v.optional(values_1.v.number()),
166
+ maxFlowExecutionsPerMonth: values_1.v.optional(values_1.v.number()),
167
+ maxMembers: values_1.v.optional(values_1.v.number()),
168
+ })),
169
+ },
170
+ handler: async (ctx, { orgId, plan, usageLimits }) => {
171
+ const identity = await ctx.auth.getUserIdentity();
172
+ if (!identity)
173
+ throw new Error('Not authenticated');
174
+ // Check if user is platform admin
175
+ const user = await ctx.db
176
+ .query('users')
177
+ .withIndex('by_clerk_id', (q) => q.eq('clerkId', identity.subject))
178
+ .first();
179
+ if (!user || user.role !== 'admin') {
180
+ throw new Error('Only platform admins can update plans');
181
+ }
182
+ const updates = {
183
+ plan,
184
+ updatedAt: Date.now(),
185
+ };
186
+ if (usageLimits) {
187
+ updates.usageLimits = usageLimits;
188
+ }
189
+ await ctx.db.patch(orgId, updates);
190
+ return { success: true };
191
+ },
192
+ });