@l4yercak3/cli 1.2.13 → 1.2.14

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.
@@ -0,0 +1,1313 @@
1
+ # L4YERCAK3 MCP Server Extension Guide
2
+
3
+ ## Purpose
4
+
5
+ This document outlines the MCP (Model Context Protocol) tools needed to enable Claude Code to effectively build mobile applications that integrate with the L4YERCAK3 backend. The goal is to expose read/write capabilities for core business objects so AI assistants can generate, test, and iterate on mobile app features.
6
+
7
+ ---
8
+
9
+ ## Current State
10
+
11
+ ### Existing MCP Tools
12
+
13
+ | Tool | Purpose | Status |
14
+ |------|---------|--------|
15
+ | `l4yercak3_check_auth_status` | Verify user authentication | ✅ Working |
16
+ | `l4yercak3_get_capabilities` | List available features by category | ✅ Working |
17
+ | `l4yercak3_list_organizations` | Get user's organizations | ✅ Working |
18
+ | `l4yercak3_switch_organization` | Change org context | ✅ Working |
19
+ | `l4yercak3_create_organization` | Create new org | ✅ Working |
20
+ | `l4yercak3_get_application` | Get connected app details | ✅ Working |
21
+ | `l4yercak3_list_applications` | List connected apps | ⚠️ Error |
22
+ | `l4yercak3_analyze_schema` | Analyze database schemas | ✅ Working |
23
+ | `l4yercak3_suggest_model_mappings` | Suggest L4YERCAK3 type mappings | ✅ Working |
24
+ | `l4yercak3_generate_api_client` | Generate TypeScript client | ✅ Working |
25
+ | `l4yercak3_generate_sync_adapter` | Generate sync code | ✅ Working |
26
+ | `l4yercak3_generate_webhook_handler` | Generate webhook handlers | ✅ Working |
27
+ | `l4yercak3_generate_env_template` | Generate .env template | ✅ Working |
28
+
29
+ ### What's Missing
30
+
31
+ The current MCP server is optimized for **code generation** but lacks **data access** capabilities. To build and test mobile apps effectively, Claude needs to:
32
+
33
+ 1. **Read real data** to understand schemas and test UI
34
+ 2. **Write test data** to verify functionality
35
+ 3. **Query relationships** between objects
36
+ 4. **Validate business logic** against actual backend behavior
37
+
38
+ ---
39
+
40
+ ## Required New MCP Tools
41
+
42
+ ### Priority 1: Core Data Access (Must Have)
43
+
44
+ These tools are essential for building any mobile app feature.
45
+
46
+ #### 1.1 Events Module
47
+
48
+ ```typescript
49
+ // l4yercak3_events_list
50
+ {
51
+ name: "l4yercak3_events_list",
52
+ description: "List events for the current organization. Returns published and draft events with pagination.",
53
+ parameters: {
54
+ status?: "draft" | "published" | "cancelled" | "completed",
55
+ limit?: number, // Default: 20, Max: 100
56
+ offset?: number, // For pagination
57
+ startDateAfter?: string, // ISO date - filter future events
58
+ startDateBefore?: string, // ISO date - filter past events
59
+ search?: string, // Search by name/description
60
+ },
61
+ returns: {
62
+ events: Array<{
63
+ id: string,
64
+ name: string,
65
+ description: string,
66
+ status: string,
67
+ startDate: string,
68
+ endDate: string,
69
+ venue: { name: string, address: string, city: string } | null,
70
+ imageUrl: string | null,
71
+ ticketCount: number,
72
+ attendeeCount: number,
73
+ }>,
74
+ total: number,
75
+ hasMore: boolean,
76
+ }
77
+ }
78
+
79
+ // l4yercak3_events_get
80
+ {
81
+ name: "l4yercak3_events_get",
82
+ description: "Get detailed information about a specific event including tickets, agenda, and sponsors.",
83
+ parameters: {
84
+ eventId: string, // Required
85
+ include?: Array<"tickets" | "agenda" | "sponsors" | "forms">,
86
+ },
87
+ returns: {
88
+ event: {
89
+ id: string,
90
+ name: string,
91
+ description: string,
92
+ status: string,
93
+ startDate: string,
94
+ endDate: string,
95
+ timezone: string,
96
+ venue: { ... } | null,
97
+ imageUrl: string | null,
98
+ bannerUrl: string | null,
99
+ // Included if requested:
100
+ tickets?: Array<{ id, name, price, currency, available, sold }>,
101
+ agenda?: Array<{ id, title, startTime, endTime, speaker, track }>,
102
+ sponsors?: Array<{ id, name, tier, logoUrl }>,
103
+ forms?: Array<{ id, name, type, fieldCount }>,
104
+ }
105
+ }
106
+ }
107
+
108
+ // l4yercak3_events_get_attendees
109
+ {
110
+ name: "l4yercak3_events_get_attendees",
111
+ description: "Get attendees for an event with their ticket and check-in status.",
112
+ parameters: {
113
+ eventId: string,
114
+ status?: "registered" | "checked_in" | "cancelled",
115
+ ticketId?: string, // Filter by ticket type
116
+ search?: string, // Search by name/email
117
+ limit?: number,
118
+ offset?: number,
119
+ },
120
+ returns: {
121
+ attendees: Array<{
122
+ id: string,
123
+ contactId: string,
124
+ name: string,
125
+ email: string,
126
+ ticketName: string,
127
+ ticketId: string,
128
+ status: string,
129
+ checkedInAt: string | null,
130
+ registeredAt: string,
131
+ formResponses?: Record<string, any>,
132
+ }>,
133
+ total: number,
134
+ hasMore: boolean,
135
+ }
136
+ }
137
+ ```
138
+
139
+ #### 1.2 Tickets Module
140
+
141
+ ```typescript
142
+ // l4yercak3_tickets_list
143
+ {
144
+ name: "l4yercak3_tickets_list",
145
+ description: "List ticket products for an event or all tickets in the organization.",
146
+ parameters: {
147
+ eventId?: string, // Filter by event
148
+ status?: "active" | "sold_out" | "hidden",
149
+ limit?: number,
150
+ offset?: number,
151
+ },
152
+ returns: {
153
+ tickets: Array<{
154
+ id: string,
155
+ eventId: string,
156
+ eventName: string,
157
+ name: string,
158
+ description: string,
159
+ price: number,
160
+ currency: string,
161
+ quantity: number,
162
+ sold: number,
163
+ available: number,
164
+ salesStart: string | null,
165
+ salesEnd: string | null,
166
+ status: string,
167
+ }>,
168
+ total: number,
169
+ hasMore: boolean,
170
+ }
171
+ }
172
+
173
+ // l4yercak3_tickets_get_purchased
174
+ {
175
+ name: "l4yercak3_tickets_get_purchased",
176
+ description: "Get purchased tickets for a contact or the current user.",
177
+ parameters: {
178
+ contactId?: string, // If omitted, returns current user's tickets
179
+ eventId?: string, // Filter by event
180
+ status?: "valid" | "used" | "refunded" | "expired",
181
+ limit?: number,
182
+ offset?: number,
183
+ },
184
+ returns: {
185
+ purchasedTickets: Array<{
186
+ id: string,
187
+ ticketId: string,
188
+ ticketName: string,
189
+ eventId: string,
190
+ eventName: string,
191
+ eventDate: string,
192
+ purchasedAt: string,
193
+ status: string,
194
+ qrCode: string, // QR code data for scanning
195
+ confirmationNumber: string,
196
+ price: number,
197
+ currency: string,
198
+ }>,
199
+ total: number,
200
+ }
201
+ }
202
+ ```
203
+
204
+ #### 1.3 CRM Module
205
+
206
+ ```typescript
207
+ // l4yercak3_crm_list_contacts
208
+ {
209
+ name: "l4yercak3_crm_list_contacts",
210
+ description: "List contacts in the CRM with filtering and search.",
211
+ parameters: {
212
+ type?: "individual" | "organization",
213
+ status?: "active" | "archived",
214
+ tags?: string[],
215
+ pipelineStage?: string,
216
+ search?: string, // Search name, email, phone
217
+ limit?: number,
218
+ offset?: number,
219
+ orderBy?: "name" | "createdAt" | "updatedAt",
220
+ orderDir?: "asc" | "desc",
221
+ },
222
+ returns: {
223
+ contacts: Array<{
224
+ id: string,
225
+ type: string,
226
+ firstName: string | null,
227
+ lastName: string | null,
228
+ displayName: string,
229
+ email: string | null,
230
+ phone: string | null,
231
+ organizationId: string | null,
232
+ organizationName: string | null,
233
+ tags: string[],
234
+ pipelineStage: string | null,
235
+ avatarUrl: string | null,
236
+ createdAt: string,
237
+ }>,
238
+ total: number,
239
+ hasMore: boolean,
240
+ }
241
+ }
242
+
243
+ // l4yercak3_crm_get_contact
244
+ {
245
+ name: "l4yercak3_crm_get_contact",
246
+ description: "Get detailed contact information including activities and linked objects.",
247
+ parameters: {
248
+ contactId: string,
249
+ include?: Array<"activities" | "notes" | "tickets" | "invoices" | "forms">,
250
+ },
251
+ returns: {
252
+ contact: {
253
+ id: string,
254
+ type: string,
255
+ firstName: string | null,
256
+ lastName: string | null,
257
+ displayName: string,
258
+ email: string | null,
259
+ phone: string | null,
260
+ address: { street, city, state, postalCode, country } | null,
261
+ organizationId: string | null,
262
+ organizationName: string | null,
263
+ tags: string[],
264
+ customFields: Record<string, any>,
265
+ pipelineStage: string | null,
266
+ avatarUrl: string | null,
267
+ createdAt: string,
268
+ updatedAt: string,
269
+ // Included if requested:
270
+ activities?: Array<{ id, type, subject, date, notes }>,
271
+ notes?: Array<{ id, content, createdAt, createdBy }>,
272
+ tickets?: Array<{ id, eventName, ticketName, status }>,
273
+ invoices?: Array<{ id, number, amount, status, dueDate }>,
274
+ forms?: Array<{ id, formName, submittedAt }>,
275
+ }
276
+ }
277
+ }
278
+
279
+ // l4yercak3_crm_create_contact
280
+ {
281
+ name: "l4yercak3_crm_create_contact",
282
+ description: "Create a new contact in the CRM.",
283
+ parameters: {
284
+ type: "individual" | "organization",
285
+ firstName?: string,
286
+ lastName?: string,
287
+ email?: string,
288
+ phone?: string,
289
+ organizationId?: string, // Link to parent organization
290
+ address?: { street?, city?, state?, postalCode?, country? },
291
+ tags?: string[],
292
+ customFields?: Record<string, any>,
293
+ pipelineStage?: string,
294
+ },
295
+ returns: {
296
+ contactId: string,
297
+ contact: { ... },
298
+ }
299
+ }
300
+
301
+ // l4yercak3_crm_update_contact
302
+ {
303
+ name: "l4yercak3_crm_update_contact",
304
+ description: "Update an existing contact.",
305
+ parameters: {
306
+ contactId: string,
307
+ firstName?: string,
308
+ lastName?: string,
309
+ email?: string,
310
+ phone?: string,
311
+ organizationId?: string,
312
+ address?: { ... },
313
+ tags?: string[],
314
+ customFields?: Record<string, any>,
315
+ pipelineStage?: string,
316
+ },
317
+ returns: {
318
+ success: boolean,
319
+ contact: { ... },
320
+ }
321
+ }
322
+
323
+ // l4yercak3_crm_list_organizations
324
+ {
325
+ name: "l4yercak3_crm_list_organizations",
326
+ description: "List organization contacts (companies, employers) in the CRM.",
327
+ parameters: {
328
+ status?: "active" | "archived",
329
+ industry?: string,
330
+ search?: string,
331
+ limit?: number,
332
+ offset?: number,
333
+ },
334
+ returns: {
335
+ organizations: Array<{
336
+ id: string,
337
+ name: string,
338
+ industry: string | null,
339
+ website: string | null,
340
+ email: string | null,
341
+ phone: string | null,
342
+ employeeCount: number,
343
+ address: { ... } | null,
344
+ createdAt: string,
345
+ }>,
346
+ total: number,
347
+ hasMore: boolean,
348
+ }
349
+ }
350
+ ```
351
+
352
+ #### 1.4 Forms Module
353
+
354
+ ```typescript
355
+ // l4yercak3_forms_list
356
+ {
357
+ name: "l4yercak3_forms_list",
358
+ description: "List forms in the organization.",
359
+ parameters: {
360
+ type?: "registration" | "survey" | "application" | "feedback",
361
+ eventId?: string,
362
+ status?: "draft" | "active" | "closed",
363
+ limit?: number,
364
+ offset?: number,
365
+ },
366
+ returns: {
367
+ forms: Array<{
368
+ id: string,
369
+ name: string,
370
+ type: string,
371
+ status: string,
372
+ eventId: string | null,
373
+ eventName: string | null,
374
+ fieldCount: number,
375
+ responseCount: number,
376
+ createdAt: string,
377
+ }>,
378
+ total: number,
379
+ hasMore: boolean,
380
+ }
381
+ }
382
+
383
+ // l4yercak3_forms_get
384
+ {
385
+ name: "l4yercak3_forms_get",
386
+ description: "Get form details including field definitions.",
387
+ parameters: {
388
+ formId: string,
389
+ },
390
+ returns: {
391
+ form: {
392
+ id: string,
393
+ name: string,
394
+ description: string,
395
+ type: string,
396
+ status: string,
397
+ eventId: string | null,
398
+ fields: Array<{
399
+ id: string,
400
+ type: "text" | "email" | "phone" | "select" | "multiselect" | "checkbox" | "date" | "file" | "number",
401
+ label: string,
402
+ required: boolean,
403
+ options?: string[],
404
+ placeholder?: string,
405
+ validation?: { min?, max?, pattern? },
406
+ conditionalOn?: { fieldId: string, value: any },
407
+ }>,
408
+ settings: {
409
+ submitButtonText: string,
410
+ confirmationMessage: string,
411
+ redirectUrl: string | null,
412
+ notifyEmails: string[],
413
+ },
414
+ createdAt: string,
415
+ updatedAt: string,
416
+ }
417
+ }
418
+ }
419
+
420
+ // l4yercak3_forms_get_responses
421
+ {
422
+ name: "l4yercak3_forms_get_responses",
423
+ description: "Get form submissions/responses.",
424
+ parameters: {
425
+ formId: string,
426
+ contactId?: string,
427
+ startDate?: string,
428
+ endDate?: string,
429
+ limit?: number,
430
+ offset?: number,
431
+ },
432
+ returns: {
433
+ responses: Array<{
434
+ id: string,
435
+ formId: string,
436
+ contactId: string | null,
437
+ contactName: string | null,
438
+ contactEmail: string | null,
439
+ data: Record<string, any>, // Field responses
440
+ submittedAt: string,
441
+ status: "submitted" | "reviewed" | "approved" | "rejected",
442
+ }>,
443
+ total: number,
444
+ hasMore: boolean,
445
+ }
446
+ }
447
+ ```
448
+
449
+ ### Priority 2: User & Auth Context (Important)
450
+
451
+ These tools provide user context needed for personalization.
452
+
453
+ ```typescript
454
+ // l4yercak3_get_current_user
455
+ {
456
+ name: "l4yercak3_get_current_user",
457
+ description: "Get the currently authenticated user's profile and permissions.",
458
+ parameters: {},
459
+ returns: {
460
+ user: {
461
+ id: string,
462
+ email: string,
463
+ firstName: string | null,
464
+ lastName: string | null,
465
+ displayName: string,
466
+ avatarUrl: string | null,
467
+ role: string,
468
+ permissions: string[],
469
+ preferences: {
470
+ language: string,
471
+ timezone: string,
472
+ theme: "light" | "dark" | "system",
473
+ },
474
+ organizations: Array<{
475
+ id: string,
476
+ name: string,
477
+ slug: string,
478
+ role: string,
479
+ isDefault: boolean,
480
+ }>,
481
+ currentOrganization: {
482
+ id: string,
483
+ name: string,
484
+ slug: string,
485
+ role: string,
486
+ } | null,
487
+ }
488
+ }
489
+ }
490
+
491
+ // l4yercak3_get_organization_details
492
+ {
493
+ name: "l4yercak3_get_organization_details",
494
+ description: "Get detailed information about an organization including settings and subscription.",
495
+ parameters: {
496
+ organizationId?: string, // If omitted, uses current org
497
+ },
498
+ returns: {
499
+ organization: {
500
+ id: string,
501
+ name: string,
502
+ slug: string,
503
+ businessName: string | null,
504
+ logo: string | null,
505
+ website: string | null,
506
+ industry: string | null,
507
+ address: { ... } | null,
508
+ subscription: {
509
+ plan: "free" | "pro" | "business" | "enterprise",
510
+ status: "active" | "trialing" | "past_due" | "cancelled",
511
+ trialEndsAt: string | null,
512
+ currentPeriodEnd: string | null,
513
+ },
514
+ settings: {
515
+ defaultCurrency: string,
516
+ defaultTimezone: string,
517
+ defaultLanguage: string,
518
+ },
519
+ features: string[], // Enabled features based on plan
520
+ memberCount: number,
521
+ createdAt: string,
522
+ }
523
+ }
524
+ }
525
+ ```
526
+
527
+ ### Priority 3: Invoicing & Payments (Nice to Have)
528
+
529
+ ```typescript
530
+ // l4yercak3_invoices_list
531
+ {
532
+ name: "l4yercak3_invoices_list",
533
+ description: "List invoices for the organization.",
534
+ parameters: {
535
+ contactId?: string,
536
+ status?: "draft" | "sent" | "paid" | "overdue" | "cancelled",
537
+ type?: "b2b" | "b2c",
538
+ startDate?: string,
539
+ endDate?: string,
540
+ limit?: number,
541
+ offset?: number,
542
+ },
543
+ returns: {
544
+ invoices: Array<{
545
+ id: string,
546
+ number: string,
547
+ contactId: string,
548
+ contactName: string,
549
+ type: string,
550
+ status: string,
551
+ amount: number,
552
+ currency: string,
553
+ dueDate: string,
554
+ paidAt: string | null,
555
+ lineItemCount: number,
556
+ createdAt: string,
557
+ }>,
558
+ total: number,
559
+ hasMore: boolean,
560
+ }
561
+ }
562
+
563
+ // l4yercak3_invoices_get
564
+ {
565
+ name: "l4yercak3_invoices_get",
566
+ description: "Get detailed invoice information.",
567
+ parameters: {
568
+ invoiceId: string,
569
+ },
570
+ returns: {
571
+ invoice: {
572
+ id: string,
573
+ number: string,
574
+ contactId: string,
575
+ contact: { name, email, address },
576
+ type: string,
577
+ status: string,
578
+ issueDate: string,
579
+ dueDate: string,
580
+ paidAt: string | null,
581
+ lineItems: Array<{
582
+ description: string,
583
+ quantity: number,
584
+ unitPrice: number,
585
+ amount: number,
586
+ }>,
587
+ subtotal: number,
588
+ tax: number,
589
+ taxRate: number,
590
+ total: number,
591
+ currency: string,
592
+ notes: string | null,
593
+ pdfUrl: string | null,
594
+ }
595
+ }
596
+ }
597
+
598
+ // l4yercak3_payments_list
599
+ {
600
+ name: "l4yercak3_payments_list",
601
+ description: "List payment transactions.",
602
+ parameters: {
603
+ contactId?: string,
604
+ status?: "pending" | "succeeded" | "failed" | "refunded",
605
+ startDate?: string,
606
+ endDate?: string,
607
+ limit?: number,
608
+ offset?: number,
609
+ },
610
+ returns: {
611
+ payments: Array<{
612
+ id: string,
613
+ amount: number,
614
+ currency: string,
615
+ status: string,
616
+ method: "card" | "bank_transfer" | "paypal",
617
+ contactId: string,
618
+ contactName: string,
619
+ invoiceId: string | null,
620
+ invoiceNumber: string | null,
621
+ description: string,
622
+ processedAt: string,
623
+ }>,
624
+ total: number,
625
+ hasMore: boolean,
626
+ }
627
+ }
628
+ ```
629
+
630
+ ### Priority 4: Check-in & Scanning (Mobile-Specific)
631
+
632
+ ```typescript
633
+ // l4yercak3_checkin_scan
634
+ {
635
+ name: "l4yercak3_checkin_scan",
636
+ description: "Validate and check-in an attendee by scanning their ticket QR code.",
637
+ parameters: {
638
+ qrCode: string, // The scanned QR code data
639
+ eventId: string, // Event context for validation
640
+ },
641
+ returns: {
642
+ valid: boolean,
643
+ status: "success" | "already_checked_in" | "invalid" | "wrong_event" | "expired",
644
+ message: string,
645
+ attendee?: {
646
+ id: string,
647
+ name: string,
648
+ email: string,
649
+ ticketName: string,
650
+ checkedInAt: string,
651
+ photoUrl: string | null,
652
+ },
653
+ }
654
+ }
655
+
656
+ // l4yercak3_checkin_manual
657
+ {
658
+ name: "l4yercak3_checkin_manual",
659
+ description: "Manually check-in an attendee by name or email lookup.",
660
+ parameters: {
661
+ eventId: string,
662
+ search: string, // Name or email to search
663
+ },
664
+ returns: {
665
+ matches: Array<{
666
+ attendeeId: string,
667
+ name: string,
668
+ email: string,
669
+ ticketName: string,
670
+ status: "registered" | "checked_in",
671
+ checkedInAt: string | null,
672
+ }>,
673
+ }
674
+ }
675
+
676
+ // l4yercak3_checkin_confirm
677
+ {
678
+ name: "l4yercak3_checkin_confirm",
679
+ description: "Confirm check-in for a specific attendee (after manual lookup).",
680
+ parameters: {
681
+ attendeeId: string,
682
+ eventId: string,
683
+ },
684
+ returns: {
685
+ success: boolean,
686
+ attendee: {
687
+ id: string,
688
+ name: string,
689
+ checkedInAt: string,
690
+ },
691
+ }
692
+ }
693
+ ```
694
+
695
+ ### Priority 5: Certificates (Professional Use)
696
+
697
+ ```typescript
698
+ // l4yercak3_certificates_list
699
+ {
700
+ name: "l4yercak3_certificates_list",
701
+ description: "List certificates issued to a contact or for an event.",
702
+ parameters: {
703
+ contactId?: string,
704
+ eventId?: string,
705
+ type?: "cme" | "cle" | "cpe" | "attendance" | "completion",
706
+ limit?: number,
707
+ offset?: number,
708
+ },
709
+ returns: {
710
+ certificates: Array<{
711
+ id: string,
712
+ type: string,
713
+ title: string,
714
+ recipientId: string,
715
+ recipientName: string,
716
+ eventId: string | null,
717
+ eventName: string | null,
718
+ credits: number | null,
719
+ creditType: string | null,
720
+ issuedAt: string,
721
+ expiresAt: string | null,
722
+ verificationUrl: string,
723
+ pdfUrl: string,
724
+ }>,
725
+ total: number,
726
+ hasMore: boolean,
727
+ }
728
+ }
729
+
730
+ // l4yercak3_certificates_verify
731
+ {
732
+ name: "l4yercak3_certificates_verify",
733
+ description: "Verify a certificate by its verification code.",
734
+ parameters: {
735
+ verificationCode: string,
736
+ },
737
+ returns: {
738
+ valid: boolean,
739
+ certificate?: {
740
+ id: string,
741
+ type: string,
742
+ title: string,
743
+ recipientName: string,
744
+ issuedAt: string,
745
+ expiresAt: string | null,
746
+ credits: number | null,
747
+ creditType: string | null,
748
+ issuerOrganization: string,
749
+ },
750
+ message?: string, // If invalid
751
+ }
752
+ }
753
+ ```
754
+
755
+ ---
756
+
757
+ ## Implementation Guidelines
758
+
759
+ ### Authentication
760
+
761
+ All MCP tools should use the existing authentication flow:
762
+
763
+ ```typescript
764
+ // Every tool should validate auth first
765
+ const authStatus = await checkAuthStatus();
766
+ if (!authStatus.authenticated) {
767
+ return {
768
+ error: "Not authenticated",
769
+ loginInstructions: "Run 'l4yercak3 login' in terminal",
770
+ };
771
+ }
772
+ ```
773
+
774
+ ### Organization Context
775
+
776
+ Tools that access org-scoped data should:
777
+
778
+ 1. Use the current organization from auth context
779
+ 2. Optionally accept `organizationId` parameter to override
780
+ 3. Validate user has access to the specified org
781
+
782
+ ```typescript
783
+ // Pattern for org-scoped tools
784
+ parameters: {
785
+ organizationId?: string, // Optional override
786
+ // ... other params
787
+ }
788
+
789
+ // In handler:
790
+ const orgId = args.organizationId || authContext.currentOrganizationId;
791
+ if (!orgId) {
792
+ return { error: "No organization selected. Use l4yercak3_switch_organization first." };
793
+ }
794
+ ```
795
+
796
+ ### Error Handling
797
+
798
+ Return structured errors:
799
+
800
+ ```typescript
801
+ // Success
802
+ { success: true, data: { ... } }
803
+
804
+ // Client error (4xx equivalent)
805
+ { error: "Contact not found", code: "NOT_FOUND" }
806
+
807
+ // Validation error
808
+ { error: "Invalid email format", code: "VALIDATION_ERROR", field: "email" }
809
+
810
+ // Permission error
811
+ { error: "Access denied", code: "FORBIDDEN" }
812
+
813
+ // Server error (5xx equivalent)
814
+ { error: "Internal server error", code: "INTERNAL_ERROR" }
815
+ ```
816
+
817
+ ### Pagination Pattern
818
+
819
+ Use consistent pagination:
820
+
821
+ ```typescript
822
+ parameters: {
823
+ limit?: number, // Default: 20, Max: 100
824
+ offset?: number, // Default: 0
825
+ }
826
+
827
+ returns: {
828
+ items: [...],
829
+ total: number,
830
+ hasMore: boolean,
831
+ // Optionally:
832
+ nextOffset?: number,
833
+ }
834
+ ```
835
+
836
+ ### Backend Mapping
837
+
838
+ Map MCP tools to existing Convex functions:
839
+
840
+ | MCP Tool | Convex Function |
841
+ |----------|-----------------|
842
+ | `l4yercak3_events_list` | `eventsOntology.getEvents` |
843
+ | `l4yercak3_crm_list_contacts` | `crmOntology.getContacts` |
844
+ | `l4yercak3_forms_get_responses` | `formsOntology.getFormResponses` |
845
+
846
+ Reference the existing HTTP API routes in `convex/http.ts` and the ontology files for the correct query/mutation signatures.
847
+
848
+ ---
849
+
850
+ ## Testing Checklist
851
+
852
+ For each new MCP tool:
853
+
854
+ - [ ] Tool appears in `l4yercak3_get_capabilities` output
855
+ - [ ] Tool works without organizationId (uses current org)
856
+ - [ ] Tool works with explicit organizationId
857
+ - [ ] Tool returns proper error for unauthenticated requests
858
+ - [ ] Tool returns proper error for unauthorized org access
859
+ - [ ] Pagination works correctly (limit, offset, hasMore)
860
+ - [ ] Search/filter parameters work as expected
861
+ - [ ] Response matches documented schema
862
+ - [ ] Tool is usable by Claude Code to build mobile features
863
+
864
+ ---
865
+
866
+ ## File Locations
867
+
868
+ | Component | Path |
869
+ |-----------|------|
870
+ | MCP Server Entry | `packages/cli/src/mcp/server.ts` |
871
+ | Tool Definitions | `packages/cli/src/mcp/tools/` |
872
+ | Convex HTTP Routes | `convex/http.ts` |
873
+ | Ontology Files | `convex/*Ontology.ts` |
874
+ | API v1 Routes | `convex/api/v1/` |
875
+ | Schema Definitions | `convex/schema/` |
876
+
877
+ ---
878
+
879
+ ## Questions?
880
+
881
+ Contact the mobile app development team or refer to the existing MCP tool implementations for patterns and examples.
882
+
883
+ ---
884
+
885
+ ---
886
+
887
+ ## Priority 0: AI Agent & Chat System (HIGHEST PRIORITY)
888
+
889
+ This is the **killer feature** for mobile. Users should be able to chat with the AI assistant directly from their phone, execute business tasks via natural language, and approve/reject tool executions on the go.
890
+
891
+ ### Architecture Overview
892
+
893
+ The L4YERCAK3 AI system consists of:
894
+
895
+ 1. **AI Conversations** - Chat sessions between user and AI assistant
896
+ 2. **AI Messages** - Individual messages in conversations
897
+ 3. **AI Tool Registry** - 40+ tools the AI can execute (CRM, Events, Forms, Projects, etc.)
898
+ 4. **AI Tool Executions** - Human-in-the-loop approval workflow for tool calls
899
+ 5. **AI Work Items** - Preview/approve workflow for batch operations
900
+ 6. **AI Settings** - Per-org model selection, budgets, approval modes
901
+
902
+ ### 0.1 Conversation Management
903
+
904
+ ```typescript
905
+ // l4yercak3_ai_create_conversation
906
+ {
907
+ name: "l4yercak3_ai_create_conversation",
908
+ description: "Create a new AI conversation session.",
909
+ parameters: {},
910
+ returns: {
911
+ conversationId: string,
912
+ createdAt: string,
913
+ }
914
+ }
915
+
916
+ // l4yercak3_ai_list_conversations
917
+ {
918
+ name: "l4yercak3_ai_list_conversations",
919
+ description: "List AI conversations for the current user.",
920
+ parameters: {
921
+ status?: "active" | "archived",
922
+ limit?: number,
923
+ offset?: number,
924
+ },
925
+ returns: {
926
+ conversations: Array<{
927
+ id: string,
928
+ title: string | null,
929
+ status: string,
930
+ modelName: string | null,
931
+ messageCount: number,
932
+ createdAt: string,
933
+ updatedAt: string,
934
+ }>,
935
+ total: number,
936
+ hasMore: boolean,
937
+ }
938
+ }
939
+
940
+ // l4yercak3_ai_get_conversation
941
+ {
942
+ name: "l4yercak3_ai_get_conversation",
943
+ description: "Get a conversation with its messages.",
944
+ parameters: {
945
+ conversationId: string,
946
+ messageLimit?: number, // Default: 50
947
+ messageOffset?: number,
948
+ },
949
+ returns: {
950
+ conversation: {
951
+ id: string,
952
+ title: string | null,
953
+ status: string,
954
+ modelId: string | null,
955
+ modelName: string | null,
956
+ messageCount: number,
957
+ createdAt: string,
958
+ updatedAt: string,
959
+ },
960
+ messages: Array<{
961
+ id: string,
962
+ role: "system" | "user" | "assistant" | "tool",
963
+ content: string,
964
+ modelId: string | null,
965
+ toolCalls: Array<{
966
+ id: string,
967
+ name: string,
968
+ arguments: object,
969
+ result: any | null,
970
+ status: "success" | "failed",
971
+ error: string | null,
972
+ }> | null,
973
+ timestamp: string,
974
+ }>,
975
+ hasMoreMessages: boolean,
976
+ }
977
+ }
978
+
979
+ // l4yercak3_ai_archive_conversation
980
+ {
981
+ name: "l4yercak3_ai_archive_conversation",
982
+ description: "Archive a conversation (soft delete).",
983
+ parameters: {
984
+ conversationId: string,
985
+ },
986
+ returns: {
987
+ success: boolean,
988
+ }
989
+ }
990
+ ```
991
+
992
+ ### 0.2 Chat Messaging (Core Feature)
993
+
994
+ ```typescript
995
+ // l4yercak3_ai_send_message
996
+ {
997
+ name: "l4yercak3_ai_send_message",
998
+ description: "Send a message to the AI assistant and get a response. This is the main chat endpoint. The AI may propose tool executions that require approval.",
999
+ parameters: {
1000
+ conversationId?: string, // If omitted, creates new conversation
1001
+ message: string, // User's message
1002
+ selectedModel?: string, // Override model (e.g., "anthropic/claude-3-5-sonnet")
1003
+ attachments?: Array<{ // For multimodal (images, files)
1004
+ type: "image" | "file",
1005
+ url: string,
1006
+ mimeType: string,
1007
+ fileName?: string,
1008
+ }>,
1009
+ },
1010
+ returns: {
1011
+ conversationId: string,
1012
+ message: string, // AI's response
1013
+ toolCalls: Array<{
1014
+ id: string,
1015
+ name: string,
1016
+ arguments: object,
1017
+ result: any | null,
1018
+ status: "success" | "failed" | "pending_approval",
1019
+ error: string | null,
1020
+ }>,
1021
+ usage: {
1022
+ prompt_tokens: number,
1023
+ completion_tokens: number,
1024
+ total_tokens: number,
1025
+ },
1026
+ cost: number, // Cost in USD
1027
+ pendingApprovals: number, // Number of tool executions awaiting approval
1028
+ }
1029
+ }
1030
+
1031
+ // l4yercak3_ai_stream_message (FUTURE - for real-time streaming)
1032
+ {
1033
+ name: "l4yercak3_ai_stream_message",
1034
+ description: "Send a message with streaming response. Returns a stream ID to poll for chunks.",
1035
+ parameters: {
1036
+ conversationId?: string,
1037
+ message: string,
1038
+ selectedModel?: string,
1039
+ },
1040
+ returns: {
1041
+ streamId: string,
1042
+ conversationId: string,
1043
+ }
1044
+ }
1045
+
1046
+ // l4yercak3_ai_get_stream_chunk (FUTURE)
1047
+ {
1048
+ name: "l4yercak3_ai_get_stream_chunk",
1049
+ description: "Get the next chunk of a streaming response.",
1050
+ parameters: {
1051
+ streamId: string,
1052
+ },
1053
+ returns: {
1054
+ chunk: string | null,
1055
+ isComplete: boolean,
1056
+ toolCalls: Array<...> | null, // Populated when complete
1057
+ }
1058
+ }
1059
+ ```
1060
+
1061
+ ### 0.3 Tool Execution Approval (Human-in-the-Loop)
1062
+
1063
+ ```typescript
1064
+ // l4yercak3_ai_list_pending_approvals
1065
+ {
1066
+ name: "l4yercak3_ai_list_pending_approvals",
1067
+ description: "Get all tool executions awaiting user approval.",
1068
+ parameters: {
1069
+ conversationId?: string, // Filter to specific conversation
1070
+ limit?: number,
1071
+ offset?: number,
1072
+ },
1073
+ returns: {
1074
+ pendingApprovals: Array<{
1075
+ id: string,
1076
+ conversationId: string,
1077
+ toolName: string,
1078
+ parameters: object,
1079
+ proposalMessage: string, // AI's explanation of what it wants to do
1080
+ status: "proposed",
1081
+ createdAt: string,
1082
+ }>,
1083
+ total: number,
1084
+ }
1085
+ }
1086
+
1087
+ // l4yercak3_ai_approve_tool
1088
+ {
1089
+ name: "l4yercak3_ai_approve_tool",
1090
+ description: "Approve a proposed tool execution. The tool will execute and results will be fed back to the AI.",
1091
+ parameters: {
1092
+ executionId: string,
1093
+ approvalType: "approve" | "approve_always", // approve_always = don't ask again for this tool
1094
+ },
1095
+ returns: {
1096
+ success: boolean,
1097
+ result: any, // Tool execution result
1098
+ error: string | null,
1099
+ aiResponse: string | null, // AI's follow-up response after seeing result
1100
+ }
1101
+ }
1102
+
1103
+ // l4yercak3_ai_reject_tool
1104
+ {
1105
+ name: "l4yercak3_ai_reject_tool",
1106
+ description: "Reject a proposed tool execution. Optionally provide feedback to the AI.",
1107
+ parameters: {
1108
+ executionId: string,
1109
+ feedback?: string, // Optional: tell AI why you rejected
1110
+ },
1111
+ returns: {
1112
+ success: boolean,
1113
+ aiResponse: string | null, // AI's response to rejection/feedback
1114
+ }
1115
+ }
1116
+
1117
+ // l4yercak3_ai_cancel_tool
1118
+ {
1119
+ name: "l4yercak3_ai_cancel_tool",
1120
+ description: "Cancel/dismiss a proposed tool execution without feedback to AI.",
1121
+ parameters: {
1122
+ executionId: string,
1123
+ },
1124
+ returns: {
1125
+ success: boolean,
1126
+ }
1127
+ }
1128
+ ```
1129
+
1130
+ ### 0.4 Work Items (Batch Operations)
1131
+
1132
+ ```typescript
1133
+ // l4yercak3_ai_list_work_items
1134
+ {
1135
+ name: "l4yercak3_ai_list_work_items",
1136
+ description: "Get AI work items (batch operations) awaiting approval or in progress.",
1137
+ parameters: {
1138
+ status?: "preview" | "approved" | "executing" | "completed" | "failed" | "cancelled",
1139
+ conversationId?: string,
1140
+ limit?: number,
1141
+ offset?: number,
1142
+ },
1143
+ returns: {
1144
+ workItems: Array<{
1145
+ id: string,
1146
+ type: string, // "crm_create_organization", "contact_sync", etc.
1147
+ name: string, // User-friendly name
1148
+ status: string,
1149
+ previewData: Array<any> | null, // What will happen (for preview status)
1150
+ results: any | null, // What happened (for completed status)
1151
+ progress: {
1152
+ total: number,
1153
+ completed: number,
1154
+ failed: number,
1155
+ } | null,
1156
+ createdAt: string,
1157
+ completedAt: string | null,
1158
+ }>,
1159
+ total: number,
1160
+ hasMore: boolean,
1161
+ }
1162
+ }
1163
+
1164
+ // l4yercak3_ai_approve_work_item
1165
+ {
1166
+ name: "l4yercak3_ai_approve_work_item",
1167
+ description: "Approve a work item to execute the batch operation.",
1168
+ parameters: {
1169
+ workItemId: string,
1170
+ },
1171
+ returns: {
1172
+ success: boolean,
1173
+ status: string, // New status after approval
1174
+ }
1175
+ }
1176
+
1177
+ // l4yercak3_ai_cancel_work_item
1178
+ {
1179
+ name: "l4yercak3_ai_cancel_work_item",
1180
+ description: "Cancel a work item.",
1181
+ parameters: {
1182
+ workItemId: string,
1183
+ },
1184
+ returns: {
1185
+ success: boolean,
1186
+ }
1187
+ }
1188
+ ```
1189
+
1190
+ ### 0.5 AI Settings & Models
1191
+
1192
+ ```typescript
1193
+ // l4yercak3_ai_get_settings
1194
+ {
1195
+ name: "l4yercak3_ai_get_settings",
1196
+ description: "Get AI settings for the current organization.",
1197
+ parameters: {},
1198
+ returns: {
1199
+ enabled: boolean,
1200
+ tier: "standard" | "privacy-enhanced" | "private-llm" | null,
1201
+ llm: {
1202
+ enabledModels: Array<{
1203
+ modelId: string,
1204
+ name: string,
1205
+ isDefault: boolean,
1206
+ customLabel: string | null,
1207
+ }>,
1208
+ defaultModelId: string | null,
1209
+ temperature: number,
1210
+ maxTokens: number,
1211
+ },
1212
+ budget: {
1213
+ monthlyBudgetUsd: number | null,
1214
+ currentMonthSpend: number,
1215
+ remainingBudget: number | null,
1216
+ },
1217
+ humanInLoopEnabled: boolean,
1218
+ toolApprovalMode: "all" | "dangerous" | "none",
1219
+ autoRecovery: {
1220
+ enabled: boolean,
1221
+ maxRetries: number,
1222
+ } | null,
1223
+ }
1224
+ }
1225
+
1226
+ // l4yercak3_ai_list_models
1227
+ {
1228
+ name: "l4yercak3_ai_list_models",
1229
+ description: "List available AI models the user can select.",
1230
+ parameters: {
1231
+ includeDisabled?: boolean, // Include models not enabled for org
1232
+ },
1233
+ returns: {
1234
+ models: Array<{
1235
+ modelId: string, // "anthropic/claude-3-5-sonnet"
1236
+ name: string, // "Claude 3.5 Sonnet"
1237
+ provider: string, // "anthropic"
1238
+ isEnabled: boolean, // Enabled for this org
1239
+ isDefault: boolean, // Is org's default model
1240
+ isSystemDefault: boolean, // Is platform-recommended
1241
+ pricing: {
1242
+ promptPerMToken: number,
1243
+ completionPerMToken: number,
1244
+ },
1245
+ capabilities: {
1246
+ toolCalling: boolean,
1247
+ multimodal: boolean,
1248
+ vision: boolean,
1249
+ },
1250
+ contextLength: number,
1251
+ }>,
1252
+ }
1253
+ }
1254
+
1255
+ // l4yercak3_ai_set_default_model
1256
+ {
1257
+ name: "l4yercak3_ai_set_default_model",
1258
+ description: "Set the default AI model for the organization.",
1259
+ parameters: {
1260
+ modelId: string,
1261
+ },
1262
+ returns: {
1263
+ success: boolean,
1264
+ model: { modelId, name, provider },
1265
+ }
1266
+ }
1267
+ ```
1268
+
1269
+ ### 0.6 Available AI Tools Reference
1270
+
1271
+ The AI assistant has access to 40+ tools across these categories:
1272
+
1273
+ | Category | Ready Tools | Placeholder Tools |
1274
+ |----------|-------------|-------------------|
1275
+ | **Meta** | `request_feature` | - |
1276
+ | **OAuth** | `check_oauth_connection` | - |
1277
+ | **CRM** | `manage_crm`, `sync_contacts`, `send_bulk_crm_email`, `create_contact` | `search_contacts`, `update_contact`, `tag_contacts` |
1278
+ | **Events** | `create_event` | `list_events`, `update_event`, `register_attendee` |
1279
+ | **Projects** | `manage_projects` | - |
1280
+ | **Benefits** | `manage_benefits` | - |
1281
+ | **Forms** | `create_form`, `manage_forms` | `list_forms`, `publish_form`, `get_form_responses` |
1282
+ | **Products** | `create_product` | `list_products`, `set_product_price` |
1283
+ | **Payments** | - | `create_invoice`, `send_invoice`, `process_payment` |
1284
+ | **Tickets** | - | `create_ticket`, `update_ticket_status`, `list_tickets` |
1285
+ | **Workflows** | - | `create_workflow`, `enable_workflow` |
1286
+ | **Media** | - | `upload_media`, `search_media` |
1287
+ | **Templates** | - | `create_template`, `send_email_from_template` |
1288
+ | **Publishing** | - | `create_page`, `publish_page` |
1289
+ | **Checkout** | - | `create_checkout_page` |
1290
+ | **Certificates** | - | `generate_certificate` |
1291
+ | **Settings** | - | `update_organization_settings`, `configure_ai_models` |
1292
+
1293
+ **Tool Statuses:**
1294
+ - **ready**: Fully implemented, executes immediately (with approval if enabled)
1295
+ - **placeholder**: Returns tutorial steps for manual completion
1296
+ - **beta**: Implemented but may have limitations
1297
+
1298
+ ### Mobile-Specific Considerations for AI Chat
1299
+
1300
+ 1. **Push Notifications**: When AI proposes a tool execution, send push notification
1301
+ 2. **Quick Actions**: Pre-built quick action buttons for common tasks
1302
+ 3. **Voice Input**: Support voice-to-text for hands-free messaging
1303
+ 4. **Offline Queue**: Queue messages when offline, sync when connected
1304
+ 5. **Attachment Support**: Camera/photo library integration for multimodal
1305
+ 6. **Haptic Feedback**: Vibrate on new AI response or approval request
1306
+
1307
+ ---
1308
+
1309
+ **Document Version:** 1.1
1310
+ **Created:** 2025-01-07
1311
+ **Updated:** 2025-01-07
1312
+ **Author:** Claude Code (AI Assistant)
1313
+ **For:** L4YERCAK3 MCP Development Team
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@l4yercak3/cli",
3
- "version": "1.2.13",
3
+ "version": "1.2.14",
4
4
  "description": "Icing on the L4yercak3 - The sweet finishing touch for your Layer Cake integration",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -351,10 +351,33 @@ async function handleSpread() {
351
351
  console.log(chalk.gray(' • Delete an existing key at https://app.l4yercak3.com?openWindow=integrations&panel=api-keys'));
352
352
  console.log(chalk.gray(' • Upgrade your plan at https://app.l4yercak3.com?openWindow=store\n'));
353
353
  process.exit(0);
354
- } else if (error.code === 'SESSION_EXPIRED') {
354
+ } else if (error.code === 'API_KEY_ALREADY_LINKED') {
355
+ console.log(chalk.yellow(`\n ⚠️ ${error.message}`));
356
+ if (error.suggestion) {
357
+ console.log(chalk.gray(` ${error.suggestion}`));
358
+ }
359
+ console.log(chalk.cyan('\n Each API key can only be connected to one application.'));
360
+ console.log(chalk.gray(' Generate a new API key for this project.\n'));
361
+
362
+ // Offer to generate a new key
363
+ const { generateNew } = await inquirer.prompt([
364
+ {
365
+ type: 'confirm',
366
+ name: 'generateNew',
367
+ message: 'Generate a new API key for this project?',
368
+ default: true,
369
+ },
370
+ ]);
371
+
372
+ if (generateNew) {
373
+ apiKey = await generateNewApiKey(organizationId);
374
+ } else {
375
+ process.exit(0);
376
+ }
377
+ } else if (error.code === 'SESSION_EXPIRED' || error.code === 'INVALID_SESSION') {
355
378
  console.log(chalk.red(`\n ❌ Session expired. Please run "l4yercak3 login" again.\n`));
356
379
  process.exit(1);
357
- } else if (error.code === 'NOT_AUTHORIZED') {
380
+ } else if (error.code === 'NOT_AUTHORIZED' || error.code === 'UNAUTHORIZED') {
358
381
  console.log(chalk.red(`\n ❌ You don't have permission to manage API keys for this organization.\n`));
359
382
  process.exit(1);
360
383
  } else {