@matimo/gmail 0.1.0-alpha.4

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,1258 @@
1
+ # Matimo Gmail Tools Ecosystem
2
+
3
+ Complete guide to Gmail tools in Matimo: OAuth2 setup, YAML architecture, tool ecosystem, and integration patterns.
4
+
5
+ ## 📋 Table of Contents
6
+
7
+ - [Ecosystem Overview](#ecosystem-overview)
8
+ - [YAML-Based Tool Architecture](#yaml-based-tool-architecture)
9
+ - [Quick Start](#quick-start)
10
+ - [Available Tools](#available-tools)
11
+ - [Integration Patterns](#integration-patterns)
12
+ - [Advanced Usage](#advanced-usage)
13
+ - [Security & Best Practices](#security--best-practices)
14
+
15
+ ## Ecosystem Overview
16
+
17
+ ### What is the Gmail Tool Ecosystem?
18
+
19
+ The Gmail tools are part of Matimo's universal AI tools ecosystem. Unlike traditional libraries where each tool requires custom code, **Gmail tools are defined once in YAML and work everywhere**:
20
+
21
+ ```
22
+ ┌─────────────────────────────────────────────────────────────┐
23
+ │ YAML Tool Definition │
24
+ │ (tools/gmail/send-email/definition.yaml) │
25
+ │ - What the tool does │
26
+ │ - Input parameters & validation │
27
+ │ - Authentication requirements │
28
+ │ - Output schema │
29
+ │ - Execution configuration (command/HTTP) │
30
+ └─────────────────────────────────────────────────────────────┘
31
+
32
+ ┌───────────────────┴────────────────────┐
33
+ ↓ ↓
34
+ SDK API MCP Server (comming soon)
35
+ (JavaScript) (Claude)
36
+ ↓ ↓
37
+ - matimo.execute() - Claude can use
38
+ - LangChain tools natively
39
+ - CrewAI agents
40
+ - Custom code
41
+ ```
42
+
43
+ **Key Principle: Define Once, Use Everywhere**
44
+
45
+ - ✅ One YAML file per tool
46
+ - ✅ Works with any framework (LangChain, CrewAI, custom code)
47
+ - ✅ No code changes needed to add/modify tools
48
+ - ✅ Scales to 1000s of tools
49
+
50
+ ### Why YAML?
51
+
52
+ YAML keeps tool definitions **maintainable, readable, and contributor-friendly**:
53
+
54
+ ```yaml
55
+ # Human-readable
56
+ name: send-email
57
+ description: Send an email via Gmail
58
+
59
+ # Parameters clearly defined
60
+ parameters:
61
+ to:
62
+ type: string
63
+ description: Recipient email address
64
+ required: true
65
+ subject:
66
+ type: string
67
+ required: true
68
+ body:
69
+ type: string
70
+ required: true
71
+
72
+ # Auth declared once (used everywhere)
73
+ authentication:
74
+ type: oauth2
75
+ provider: google
76
+
77
+ # Execution details (HTTP call)
78
+ execution:
79
+ type: http
80
+ method: POST
81
+ url: https://www.googleapis.com/gmail/v1/users/me/messages/send
82
+ headers:
83
+ Authorization: 'Bearer {GMAIL_ACCESS_TOKEN}'
84
+
85
+ # Output schema for validation
86
+ output_schema:
87
+ type: object
88
+ properties:
89
+ id:
90
+ type: string
91
+ description: Message ID
92
+ ```
93
+
94
+ ### How Matimo Uses YAML
95
+
96
+ 1. **Load & Parse** - YAML → Tool object
97
+ 2. **Validate** - Check parameters against schema
98
+ 3. **Execute** - Run HTTP request with auth
99
+ 4. **Transform** - Apply parameter encodings (MIME, base64, etc.)
100
+ 5. **Return** - Validate output against schema
101
+
102
+ This is what makes Matimo **framework-agnostic** and **scalable**.
103
+
104
+ ## YAML-Based Tool Architecture
105
+
106
+ ### File Structure
107
+
108
+ ```
109
+ tools/gmail/
110
+ ├── README.md # This file
111
+ ├── send-email/
112
+ │ ├── definition.yaml # Tool definition
113
+ ├── list-messages/
114
+ │ ├── definition.yaml
115
+ ├── create-draft/
116
+ │ ├── definition.yaml
117
+ ├── get-message/
118
+ │ ├── definition.yaml
119
+ └── delete-message/
120
+ ├── definition.yaml
121
+ ```
122
+
123
+ ### Anatomy of a Tool Definition (YAML)
124
+
125
+ Every tool has these sections:
126
+
127
+ #### 1. **Metadata**
128
+
129
+ ```yaml
130
+ name: send-email
131
+ version: '1.0.0'
132
+ description: Send an email via Gmail
133
+ tags: [email, gmail, messaging]
134
+ ```
135
+
136
+ #### 2. **Parameters** (Input Schema)
137
+
138
+ ```yaml
139
+ parameters:
140
+ to:
141
+ type: string
142
+ description: Recipient email address
143
+ required: true
144
+ example: 'user@example.com'
145
+
146
+ subject:
147
+ type: string
148
+ required: true
149
+ example: 'Hello World'
150
+
151
+ body:
152
+ type: string
153
+ required: true
154
+ example: 'This is the email body'
155
+
156
+ cc:
157
+ type: string
158
+ required: false # Optional
159
+ example: 'cc@example.com'
160
+
161
+ is_html:
162
+ type: boolean
163
+ required: false
164
+ default: false
165
+ ```
166
+
167
+ #### 3. **Authentication** (Credentials)
168
+
169
+ ```yaml
170
+ authentication:
171
+ type: oauth2 # How to authenticate
172
+ provider: google # Which service
173
+ scopes: # Permissions needed
174
+ - gmail.readonly # Read emails
175
+ - gmail.send # Send emails
176
+ - gmail.compose # Create drafts
177
+ ```
178
+
179
+ Matimo auto-injects tokens from environment:
180
+
181
+ ```typescript
182
+ // No explicit token passing - Matimo handles it!
183
+ await matimo.execute('gmail-send-email', {
184
+ to: 'user@example.com',
185
+ subject: 'Hello',
186
+ body: 'Message',
187
+ // GMAIL_ACCESS_TOKEN auto-added from process.env
188
+ });
189
+ ```
190
+
191
+ #### 4. **Execution** (How to run the tool)
192
+
193
+ ```yaml
194
+ execution:
195
+ type: http # Command or HTTP
196
+ method: POST # HTTP method
197
+ url: https://www.googleapis.com/... # API endpoint
198
+
199
+ headers:
200
+ Authorization: 'Bearer {GMAIL_ACCESS_TOKEN}' # Auth header
201
+ Content-Type: application/json
202
+
203
+ body:
204
+ # Parameter encoding: Convert params to Gmail's format
205
+ # Gmail requires MIME message in base64url
206
+ message:
207
+ raw: '{raw}' # Special encoding directive
208
+ ```
209
+
210
+ #### 5. **Parameter Encoding** (Transformation)
211
+
212
+ ```yaml
213
+ parameter_encoding:
214
+ - source: [to, subject, body, cc, bcc, is_html]
215
+ target: raw
216
+ encoding: mime_rfc2822_base64url # Convert to MIME format
217
+ ```
218
+
219
+ This is how Matimo handles complex transformations:
220
+
221
+ - 🔄 **mime_rfc2822_base64url** - Encode email as MIME message
222
+ - 🔗 **url_encoded** - URL-encode form data
223
+ - 📦 **json_compact** - Minify JSON
224
+
225
+ #### 6. **Output Schema** (Result Validation)
226
+
227
+ ```yaml
228
+ output_schema:
229
+ type: object
230
+ properties:
231
+ id:
232
+ type: string
233
+ description: 'Gmail message ID'
234
+ threadId:
235
+ type: string
236
+ description: 'Thread ID for grouping conversations'
237
+ required: [id, threadId]
238
+ ```
239
+
240
+ ### Why This Architecture Matters
241
+
242
+ | Aspect | Benefit |
243
+ | ---------------- | --------------------------------------------------- |
244
+ | **Declarative** | Tool behavior defined in human-readable YAML |
245
+ | **Validated** | Schema validation at load time + execution time |
246
+ | **Reusable** | Same YAML works with any framework (SDK, MCP, REST) |
247
+ | **Maintainable** | Update tool = edit YAML, no code changes needed |
248
+ | **Scalable** | Add 1000s of tools without changing core code |
249
+ | **Secure** | Auth tokens never in source code or YAML |
250
+ | **Transparent** | LLMs can see tool definitions and understand them |
251
+
252
+ ## Provider YAML Architecture
253
+
254
+ ### Why Provider YAML?
255
+
256
+ In addition to individual tool definitions, Matimo uses **Provider YAML** files to centralize OAuth2 configuration and shared settings across all tools for a single provider (in this case, Google).
257
+
258
+ ```
259
+ tools/gmail/
260
+ ├── definition.yaml # ← PROVIDER YAML (Google OAuth2 config)
261
+ │ All Gmail tools reference this
262
+ ├── send-email/
263
+ │ ├── definition.yaml # Individual tool definition
264
+ │ └── ...
265
+ ├── create-draft/
266
+ │ ├── definition.yaml
267
+ │ └── ...
268
+ └── list-messages/
269
+ ├── definition.yaml
270
+ └── ...
271
+ ```
272
+
273
+ ### Provider YAML: `tools/gmail/definition.yaml`
274
+
275
+ The provider-level YAML file serves multiple purposes:
276
+
277
+ **1. Centralize OAuth2 Configuration**
278
+
279
+ ```yaml
280
+ name: google-provider
281
+ type: provider
282
+
283
+ provider:
284
+ name: google
285
+ displayName: Google
286
+
287
+ # OAuth2 endpoints - used by all Google-dependent tools
288
+ endpoints:
289
+ authorizationUrl: https://accounts.google.com/o/oauth2/v2/auth
290
+ tokenUrl: https://oauth2.googleapis.com/token
291
+ revokeUrl: https://oauth2.googleapis.com/revoke
292
+ ```
293
+
294
+ **Benefits:**
295
+
296
+ - ✅ **Single source of truth** - All Gmail tools reference these endpoints
297
+ - ✅ **Override capability** - Users can change endpoints via environment variables
298
+ - ✅ **Extensibility** - Easy to add new Google-dependent tools
299
+ - ✅ **Maintainability** - If Google changes endpoints, update once
300
+
301
+ **2. Define Standard Scopes**
302
+
303
+ The provider file defines OAuth2 scopes required by Gmail tools:
304
+
305
+ ```yaml
306
+ # From definition.yaml
307
+ scopes:
308
+ - gmail.readonly # Read emails
309
+ - gmail.send # Send emails
310
+ - gmail.compose # Create drafts
311
+ - gmail.modify # Delete/modify emails
312
+ ```
313
+
314
+ Each individual tool declares which scopes it needs:
315
+
316
+ ```yaml
317
+ # In send-email/definition.yaml
318
+ authentication:
319
+ type: oauth2
320
+ provider: google
321
+ scopes:
322
+ - gmail.send # This tool needs to send emails
323
+ ```
324
+
325
+ **3. Configuration Override Pattern**
326
+
327
+ The provider YAML enables this priority system:
328
+
329
+ ```
330
+ Priority (High → Low):
331
+ 1. Runtime configuration (programmatic)
332
+ 2. Environment variables: OAUTH_GOOGLE_AUTH_URL, etc.
333
+ 3. Provider YAML: definition.yaml
334
+ ```
335
+
336
+ Example - Change endpoints for custom proxy:
337
+
338
+ ```bash
339
+ # Option A: Environment variable (highest priority)
340
+ export OAUTH_GOOGLE_AUTH_URL="https://my-proxy.example.com/auth"
341
+
342
+ # Option B: Edit definition.yaml (lowest priority)
343
+ # endpoints:
344
+ # authorizationUrl: https://my-proxy.example.com/auth
345
+ ```
346
+
347
+ ### How Tool Definition References Provider
348
+
349
+ Each individual tool declares its dependency on the provider:
350
+
351
+ **send-email/definition.yaml:**
352
+
353
+ ```yaml
354
+ name: gmail-send-email
355
+ version: '1.0.0'
356
+
357
+ authentication:
358
+ type: oauth2
359
+ provider: google # ← References the provider
360
+ scopes:
361
+ - gmail.send # Specific scopes for this tool
362
+ - gmail.compose
363
+
364
+ execution:
365
+ type: http
366
+ url: https://www.googleapis.com/gmail/v1/users/me/messages/send
367
+ headers:
368
+ # Uses GMAIL_ACCESS_TOKEN from provider's OAuth2 flow
369
+ Authorization: 'Bearer {GMAIL_ACCESS_TOKEN}'
370
+ ```
371
+
372
+ **Matimo's Resolution:**
373
+
374
+ 1. Load tool: `gmail-send-email`
375
+ 2. Read `authentication.provider: google`
376
+ 3. Find provider YAML: `tools/gmail/definition.yaml`
377
+ 4. Load OAuth2 endpoints and scopes from provider
378
+ 5. Merge with tool-specific requirements
379
+ 6. Ready to execute!
380
+
381
+ ### Multi-Provider Scenario
382
+
383
+ When Matimo has tools from multiple providers, provider YAML keeps them isolated:
384
+
385
+ ```
386
+ tools/
387
+ ├── gmail/
388
+ │ ├── definition.yaml # ← Provider: Google
389
+ │ ├── send-email/
390
+ │ ├── create-draft/
391
+ │ └── list-messages/
392
+
393
+ ├── slack/
394
+ │ ├── definition.yaml # ← Provider: Slack
395
+ │ ├── send-message/
396
+ │ ├── post-channel/
397
+ │ └── get-users/
398
+
399
+ └── github/
400
+ ├── definition.yaml # ← Provider: GitHub
401
+ ├── create-issue/
402
+ ├── list-repos/
403
+ └── create-pr/
404
+ ```
405
+
406
+ Each provider has:
407
+
408
+ - ✅ Its own OAuth2 endpoints
409
+ - ✅ Its own scopes/permissions
410
+ - ✅ Its own credentials (CLIENT_ID, CLIENT_SECRET)
411
+ - ✅ Its own authentication flow
412
+
413
+ Matimo loads all providers and their tools - **no code changes needed**.
414
+
415
+ ### Why Not Hardcode in Code?
416
+
417
+ ❌ **Bad approach:**
418
+
419
+ ```typescript
420
+ // Tools/Gmail.ts - Code changes for each provider
421
+ if (provider === 'google') {
422
+ authUrl = 'https://accounts.google.com/...';
423
+ scopes = ['gmail.readonly', 'gmail.send'];
424
+ }
425
+ if (provider === 'slack') {
426
+ authUrl = 'https://slack.com/oauth...';
427
+ scopes = ['chat:write', 'users:read'];
428
+ }
429
+ ```
430
+
431
+ **Problems:**
432
+
433
+ - Non-technical contributors can't add providers
434
+ - Code must be modified for each provider
435
+ - Doesn't scale to 100s of providers
436
+ - Risk of bugs during refactoring
437
+
438
+ ✅ **Good approach (Matimo):**
439
+
440
+ ```yaml
441
+ # tools/gmail/definition.yaml
442
+ provider: google
443
+ endpoints:
444
+ authorizationUrl: https://accounts.google.com/...
445
+ scopes:
446
+ - gmail.readonly
447
+ - gmail.send
448
+ ```
449
+
450
+ **Benefits:**
451
+
452
+ - Maintainers submit YAML, not code
453
+ - Matimo loads all providers dynamically
454
+ - Scales to 1000s of providers
455
+ - Single deployment handles all tools
456
+ - Contributors can add providers without code knowledge
457
+
458
+ ### Real-World Example: Adding GitHub Tools
459
+
460
+ To add GitHub tools to Matimo:
461
+
462
+ **Step 1:** Create provider file:
463
+
464
+ ```bash
465
+ tools/github/definition.yaml
466
+ ```
467
+
468
+ **Step 2:** Define GitHub OAuth2 endpoints:
469
+
470
+ ```yaml
471
+ name: github-provider
472
+ type: provider
473
+ provider:
474
+ name: github
475
+ endpoints:
476
+ authorizationUrl: https://github.com/login/oauth/authorize
477
+ tokenUrl: https://github.com/login/oauth/access_token
478
+ ```
479
+
480
+ **Step 3:** Add tool definitions:
481
+
482
+ ```bash
483
+ tools/github/create-issue/definition.yaml
484
+ tools/github/list-repos/definition.yaml
485
+ tools/github/create-pr/definition.yaml
486
+ ```
487
+
488
+ **Step 4:** Each tool references provider:
489
+
490
+ ```yaml
491
+ # In create-issue/definition.yaml
492
+ authentication:
493
+ type: oauth2
494
+ provider: github # ← Links to github/definition.yaml
495
+ scopes:
496
+ - repo
497
+ - issues
498
+ ```
499
+
500
+ **Done!** No code changes needed. Matimo automatically:
501
+
502
+ - ✅ Loads the provider
503
+ - ✅ Loads all GitHub tools
504
+ - ✅ Sets up OAuth2 with GitHub endpoints
505
+ - ✅ Makes tools available to SDK, MCP, REST API
506
+
507
+ This is the **"Define Once, Use Everywhere"** principle in action!
508
+
509
+ ## Quick Start
510
+
511
+ Get started with Gmail tools in 5 minutes.
512
+
513
+ ### 1️⃣ Get OAuth Token (2 minutes)
514
+
515
+ #### Easiest: Google OAuth Playground
516
+
517
+ 1. **Visit** https://developers.google.com/oauthplayground
518
+ 2. **Configure** (⚙️ settings, top right):
519
+ - ☑️ Check "Use your own OAuth credentials"
520
+ - Enter **Client ID** (from [Google Cloud Console](https://console.cloud.google.com/apis/credentials))
521
+ - Enter **Client Secret**
522
+ 3. **Select Scopes** (left panel):
523
+ ```
524
+ https://www.googleapis.com/auth/gmail.readonly # Read emails
525
+ https://www.googleapis.com/auth/gmail.send # Send emails
526
+ https://www.googleapis.com/auth/gmail.compose # Create drafts
527
+ ```
528
+ 4. **Authorize & Copy Token**:
529
+ - Click "Authorize APIs"
530
+ - Grant permission
531
+ - Copy the **Access Token** (starts with `ya29.a0...`)
532
+
533
+ #### Production: Set Up Your Own OAuth App
534
+
535
+ 1. Go to https://console.cloud.google.com
536
+ 2. Create project: "My Gmail App"
537
+ 3. Enable **Gmail API**:
538
+ - Search "Gmail API"
539
+ - Click "Enable"
540
+ 4. Create **OAuth 2.0 Credentials**:
541
+ - Credentials → "Create Credentials" → "OAuth 2.0 Client ID"
542
+ - App type: **Desktop app** (testing) or **Web application** (production)
543
+ - Add redirect URIs:
544
+ ```
545
+ http://localhost:3000/callback
546
+ http://localhost:3000/auth/gmail/callback
547
+ ```
548
+ - Download JSON credentials
549
+
550
+ ### 2️⃣ Set Environment Variable (1 minute)
551
+
552
+ #### Option A: `.env` file (Recommended)
553
+
554
+ ```bash
555
+ # Create .env in your project root
556
+ cat > .env << EOF
557
+ GMAIL_ACCESS_TOKEN=ya29.a0AfH6SMBx...your-token...
558
+ EOF
559
+
560
+ # Add to .gitignore
561
+ echo ".env" >> .gitignore
562
+ ```
563
+
564
+ #### Option B: Export in shell
565
+
566
+ ```bash
567
+ export GMAIL_ACCESS_TOKEN="ya29.a0AfH6SMBx...your-token..."
568
+ ```
569
+
570
+ ### 3️⃣ Test It! (2 minutes)
571
+
572
+ ```bash
573
+ cd /Users/sajesh/My\ Work\ Directory/matimo/examples/tools
574
+
575
+ # Install dependencies
576
+ pnpm install
577
+
578
+ # Run factory pattern test
579
+ pnpm run gmail:factory --email:youremail@gmail.com
580
+ ```
581
+
582
+ **Expected output:**
583
+
584
+ ```
585
+ 📬 Example 1: List Your Recent Messages
586
+ ✅ Found 5 recent messages
587
+
588
+ 📧 Example 2: Send Email
589
+ ✅ Email sent successfully!
590
+
591
+ ✏️ Example 3: Create Draft
592
+ ✅ Draft created successfully!
593
+ ```
594
+
595
+ ## Available Tools
596
+
597
+ ### Overview
598
+
599
+ | Tool | Purpose | Input | Output |
600
+ | ---------------------- | ---------------------- | ------------------------------------ | -------------------------- |
601
+ | `gmail-list-messages` | List emails from inbox | `maxResults`, `query`, `labelIds` | `messages[]` |
602
+ | `gmail-get-message` | Get full email details | `message_id`, `format` | `id`, `payload`, `headers` |
603
+ | `gmail-send-email` | Send email | `to`, `subject`, `body`, `cc`, `bcc` | `id` |
604
+ | `gmail-create-draft` | Create draft email | `to`, `subject`, `body`, `cc`, `bcc` | `id` |
605
+ | `gmail-delete-message` | Delete email | `message_id` | `success` |
606
+
607
+ ### Tool Reference
608
+
609
+ #### 1. gmail-list-messages
610
+
611
+ **Description:** List recent emails from your inbox with optional filtering.
612
+
613
+ **Parameters:**
614
+
615
+ ```typescript
616
+ {
617
+ query?: string; // Gmail search syntax
618
+ // Examples:
619
+ // "from:alice@example.com"
620
+ // "subject:meeting"
621
+ // "is:unread"
622
+ // "is:starred"
623
+ maxResults?: number; // 1-500 (default: 10)
624
+ pageToken?: string; // For pagination
625
+ labelIds?: string[]; // Filter by labels
626
+ // Common: ["INBOX", "SENT", "DRAFT"]
627
+ includeSpamTrash?: boolean; // Include spam/trash
628
+ }
629
+ ```
630
+
631
+ **Returns:**
632
+
633
+ ```typescript
634
+ {
635
+ messages: Array<{
636
+ id: string; // Gmail message ID
637
+ threadId: string; // For conversation grouping
638
+ snippet: string; // Email preview
639
+ }>,
640
+ resultSizeEstimate: number;
641
+ }
642
+ ```
643
+
644
+ **Example:**
645
+
646
+ ```typescript
647
+ const result = await matimo.execute('gmail-list-messages', {
648
+ maxResults: 5,
649
+ query: 'from:alice@example.com',
650
+ });
651
+ ```
652
+
653
+ ---
654
+
655
+ #### 2. gmail-send-email
656
+
657
+ **Description:** Send an email via Gmail.
658
+
659
+ **Parameters:**
660
+
661
+ ```typescript
662
+ {
663
+ to: string; // Required: Recipient email
664
+ subject: string; // Required: Email subject
665
+ body: string; // Required: Email body
666
+ cc?: string; // Optional: CC recipient(s)
667
+ bcc?: string; // Optional: BCC recipient(s)
668
+ is_html?: boolean; // Optional: HTML body (default: false)
669
+ }
670
+ ```
671
+
672
+ **Returns:**
673
+
674
+ ```typescript
675
+ {
676
+ id: string; // Sent message ID
677
+ threadId: string; // Thread ID
678
+ labelIds: string[]; // ["SENT"]
679
+ }
680
+ ```
681
+
682
+ **How It Works:**
683
+
684
+ 1. Matimo converts `to`, `subject`, `body` → MIME message
685
+ 2. Encodes as base64url (required by Gmail API)
686
+ 3. Sends via POST to Gmail API
687
+ 4. Returns message ID
688
+
689
+ **Example:**
690
+
691
+ ```typescript
692
+ const result = await matimo.execute('gmail-send-email', {
693
+ to: 'user@example.com',
694
+ subject: 'Hello from Matimo',
695
+ body: 'This email was sent via Gmail tools!',
696
+ is_html: false,
697
+ });
698
+ ```
699
+
700
+ ---
701
+
702
+ #### 3. gmail-create-draft
703
+
704
+ **Description:** Create a draft email (not sent).
705
+
706
+ **Parameters:**
707
+
708
+ ```typescript
709
+ {
710
+ to: string; // Required: Draft recipient
711
+ subject: string; // Required: Draft subject
712
+ body: string; // Required: Draft body
713
+ cc?: string; // Optional: CC recipient(s)
714
+ bcc?: string; // Optional: BCC recipient(s)
715
+ is_html?: boolean; // Optional: HTML body (default: false)
716
+ }
717
+ ```
718
+
719
+ **Returns:**
720
+
721
+ ```typescript
722
+ {
723
+ id: string; // Draft ID
724
+ message: {
725
+ id: string;
726
+ threadId: string;
727
+ labelIds: string[]; // ["DRAFT"]
728
+ }
729
+ }
730
+ ```
731
+
732
+ **Use Case:** AI agents generating email content for review before sending.
733
+
734
+ **Example:**
735
+
736
+ ```typescript
737
+ const result = await matimo.execute('gmail-create-draft', {
738
+ to: 'user@example.com',
739
+ subject: 'Weekly Summary',
740
+ body: 'Generated by AI agent...',
741
+ is_html: true,
742
+ });
743
+ // User can manually review and send from Gmail
744
+ ```
745
+
746
+ ---
747
+
748
+ #### 4. gmail-get-message
749
+
750
+ **Description:** Get full details of a specific email.
751
+
752
+ **Parameters:**
753
+
754
+ ```typescript
755
+ {
756
+ message_id: string; // Required: Email ID (from list-messages)
757
+ format?: string; // Optional: "minimal" | "full" | "raw"
758
+ // Default: "full"
759
+ }
760
+ ```
761
+
762
+ **Returns:**
763
+
764
+ ```typescript
765
+ {
766
+ id: string;
767
+ threadId: string;
768
+ labelIds: string[];
769
+ snippet: string;
770
+ payload: {
771
+ mimeType: string;
772
+ headers: Array<{
773
+ name: string; // "Subject", "From", etc.
774
+ value: string;
775
+ }>,
776
+ parts?: Array<...>; // Email parts (attachments, etc.)
777
+ body: {
778
+ size: number;
779
+ data?: string; // Base64 encoded body (if format=full)
780
+ }
781
+ }
782
+ }
783
+ ```
784
+
785
+ **Example:**
786
+
787
+ ```typescript
788
+ const result = await matimo.execute('gmail-get-message', {
789
+ message_id: '18b8f4a2a1c5e3d2',
790
+ format: 'full',
791
+ });
792
+ ```
793
+
794
+ ---
795
+
796
+ #### 5. gmail-delete-message
797
+
798
+ **Description:** Delete an email (moves to trash).
799
+
800
+ **Parameters:**
801
+
802
+ ```typescript
803
+ {
804
+ message_id: string; // Required: Email ID to delete
805
+ }
806
+ ```
807
+
808
+ **Returns:**
809
+
810
+ ```typescript
811
+ {
812
+ success: boolean;
813
+ message_id: string;
814
+ }
815
+ ```
816
+
817
+ **Example:**
818
+
819
+ ```typescript
820
+ const result = await matimo.execute('gmail-delete-message', {
821
+ message_id: '18b8f4a2a1c5e3d2',
822
+ });
823
+ ```
824
+
825
+ ## Integration Patterns
826
+
827
+ ### Pattern 1: Factory Pattern (Direct SDK)
828
+
829
+ Use when you have explicit parameters:
830
+
831
+ ```typescript
832
+ import { MatimoInstance } from 'matimo';
833
+ import path from 'path';
834
+
835
+ const matimo = await MatimoInstance.init(path.join(__dirname, 'tools'));
836
+
837
+ // Tool executes, token auto-injected from GMAIL_ACCESS_TOKEN env var
838
+ const result = await matimo.execute('gmail-send-email', {
839
+ to: 'user@example.com',
840
+ subject: 'Hello',
841
+ body: 'Message',
842
+ });
843
+ ```
844
+
845
+ **When to use:** Scripts, cron jobs, simple automation
846
+
847
+ ---
848
+
849
+ ### Pattern 2: Decorator Pattern (LangChain Decorators)
850
+
851
+ Use when building agent frameworks:
852
+
853
+ ```typescript
854
+ import { tool } from 'langchain';
855
+
856
+ class EmailAgent {
857
+ @tool('gmail-send-email')
858
+ async sendEmail(to: string, subject: string, body: string) {
859
+ return undefined; // Matimo intercepts and executes
860
+ }
861
+ }
862
+ ```
863
+
864
+ **When to use:** Framework integration, reusable agents
865
+
866
+ ---
867
+
868
+ ### Pattern 3: AI Agent Pattern (OpenAI + LangChain)
869
+
870
+ Use when you want LLM to decide which tool to use:
871
+
872
+ ```typescript
873
+ import { createAgent } from 'langchain';
874
+ import { ChatOpenAI } from '@langchain/openai';
875
+
876
+ const agent = await createAgent({
877
+ model: new ChatOpenAI({ modelName: 'gpt-4o-mini' }),
878
+ tools: gmailTools,
879
+ });
880
+
881
+ // Natural language request
882
+ await agent.invoke({
883
+ messages: [
884
+ {
885
+ role: 'user',
886
+ content: 'Send me a test email',
887
+ },
888
+ ],
889
+ });
890
+ // Agent decides which tool to use and calls it!
891
+ ```
892
+
893
+ **When to use:** Autonomous agents, natural language interfaces
894
+
895
+ ---
896
+
897
+ ## Advanced Usage
898
+
899
+ ### Gmail Search Query Syntax
900
+
901
+ Use powerful Gmail search in `list-messages`:
902
+
903
+ ```typescript
904
+ // Single condition
905
+ await matimo.execute('gmail-list-messages', {
906
+ query: 'from:alice@example.com',
907
+ maxResults: 10,
908
+ });
909
+
910
+ // Multiple conditions
911
+ await matimo.execute('gmail-list-messages', {
912
+ query: 'from:alice@example.com subject:meeting is:unread',
913
+ maxResults: 10,
914
+ });
915
+ ```
916
+
917
+ **Common search operators:**
918
+
919
+ ```
920
+ from:alice@example.com # From specific sender
921
+ to:bob@example.com # To specific recipient
922
+ subject:meeting # Keywords in subject
923
+ body:coffee # Keywords in body
924
+ has:attachment # Has attachments
925
+ is:unread # Unread emails
926
+ is:starred # Starred emails
927
+ is:important # Marked important
928
+ label:work # With specific label
929
+ before:2024/01/01 # Before date
930
+ after:2023/12/01 # After date
931
+ filename:pdf # Specific attachment type
932
+ ```
933
+
934
+ ---
935
+
936
+ ### Pagination
937
+
938
+ For large email lists, use pagination:
939
+
940
+ ```typescript
941
+ let pageToken: string | undefined = undefined;
942
+ let allMessages = [];
943
+
944
+ while (true) {
945
+ const result = await matimo.execute('gmail-list-messages', {
946
+ maxResults: 100,
947
+ pageToken: pageToken,
948
+ });
949
+
950
+ allMessages = allMessages.concat(result.messages);
951
+
952
+ if (!result.nextPageToken) break;
953
+ pageToken = result.nextPageToken;
954
+ }
955
+
956
+ console.log(`Total messages: ${allMessages.length}`);
957
+ ```
958
+
959
+ ---
960
+
961
+ ### HTML Emails
962
+
963
+ Send formatted HTML emails:
964
+
965
+ ```typescript
966
+ await matimo.execute('gmail-send-email', {
967
+ to: 'user@example.com',
968
+ subject: 'HTML Email Example',
969
+ body: `
970
+ <h1>Hello!</h1>
971
+ <p>This is an <strong>HTML</strong> email.</p>
972
+ <a href="https://example.com">Click here</a>
973
+ `,
974
+ is_html: true, // Enable HTML parsing
975
+ });
976
+ ```
977
+
978
+ ---
979
+
980
+ ### Multiple Recipients
981
+
982
+ Send to CC/BCC recipients:
983
+
984
+ ```typescript
985
+ await matimo.execute('gmail-send-email', {
986
+ to: 'primary@example.com',
987
+ cc: 'cc1@example.com,cc2@example.com', // Comma-separated
988
+ bcc: 'bcc@example.com',
989
+ subject: 'Team Update',
990
+ body: 'Status update for the team',
991
+ });
992
+ ```
993
+
994
+ ---
995
+
996
+ ### How Parameter Encoding Works
997
+
998
+ Gmail requires emails in MIME format (base64url). Matimo handles this automatically via YAML:
999
+
1000
+ **Your code:**
1001
+
1002
+ ```typescript
1003
+ await matimo.execute('gmail-send-email', {
1004
+ to: 'user@example.com',
1005
+ subject: 'Hello',
1006
+ body: 'Message',
1007
+ });
1008
+ ```
1009
+
1010
+ **What Matimo does:**
1011
+
1012
+ ```
1013
+ 1. Read parameters: to, subject, body
1014
+ 2. Build MIME message:
1015
+ From: <your-account>
1016
+ To: user@example.com
1017
+ Subject: Hello
1018
+
1019
+ Message
1020
+
1021
+ 3. Encode as base64url (required by Gmail API)
1022
+ 4. Send as: POST /send with {message: {raw: "base64string"}}
1023
+ ```
1024
+
1025
+ **This is defined in YAML:**
1026
+
1027
+ ```yaml
1028
+ parameter_encoding:
1029
+ - source: [to, subject, body, cc, bcc, is_html]
1030
+ target: raw
1031
+ encoding: mime_rfc2822_base64url # Handles all the above
1032
+ ```
1033
+
1034
+ ---
1035
+
1036
+ ## Security & Best Practices
1037
+
1038
+ ### "Missing GMAIL_ACCESS_TOKEN"
1039
+
1040
+ **Problem:** Error when trying to use Gmail tools without token.
1041
+
1042
+ **Solution:**
1043
+
1044
+ ```bash
1045
+ # Check if environment variable is set
1046
+ echo $GMAIL_ACCESS_TOKEN
1047
+
1048
+ # Set it if missing
1049
+ export GMAIL_ACCESS_TOKEN=ya29.a0AfH6SMBx...
1050
+ ```
1051
+
1052
+ ### "Invalid Credentials (401)"
1053
+
1054
+ **Problem:** Gmail API returns 401 Unauthorized.
1055
+
1056
+ **Possible causes:**
1057
+
1058
+ 1. Token is expired (access tokens expire after ~1 hour)
1059
+ 2. Token has wrong scopes
1060
+ 3. Token is for wrong Google account
1061
+ 4. Application not authorized in Google Cloud
1062
+
1063
+ **Solution:**
1064
+
1065
+ 1. Get a fresh token (especially if > 1 hour old)
1066
+ 2. Check scopes match your app's needs
1067
+ 3. Re-authenticate with the correct account
1068
+ 4. Verify app is authorized in Google Cloud Console
1069
+
1070
+ ### "Permission Denied (403)"
1071
+
1072
+ **Problem:** Gmail API returns 403 Forbidden.
1073
+
1074
+ **Possible causes:**
1075
+
1076
+ 1. Token missing required scope
1077
+ 2. Trying to access another user's mailbox
1078
+ 3. Gmail API not enabled in Cloud project
1079
+ 4. Rate limit exceeded
1080
+
1081
+ **Solution:**
1082
+
1083
+ 1. Add required scopes when getting token
1084
+ 2. Ensure token is for the account you're accessing
1085
+ 3. Enable Gmail API in Cloud Console
1086
+ 4. Wait before retrying (rate limited)
1087
+
1088
+ ### "Invalid Token Format"
1089
+
1090
+ **Problem:** Error when passing token parameter.
1091
+
1092
+ **Solution:**
1093
+ Ensure token is a string and properly passed:
1094
+
1095
+ ```typescript
1096
+ // ✅ Correct
1097
+ GMAIL_ACCESS_TOKEN: process.env.GMAIL_ACCESS_TOKEN;
1098
+
1099
+ // ❌ Wrong
1100
+ GMAIL_ACCESS_TOKEN: undefined; // Missing env var
1101
+ GMAIL_ACCESS_TOKEN: {
1102
+ token: 'ya29...';
1103
+ } // Object instead of string
1104
+ ```
1105
+
1106
+ ## Security Best Practices
1107
+
1108
+ ### ✅ DO
1109
+
1110
+ - Store tokens in environment variables
1111
+ - Use `.env` files locally (not in git)
1112
+ - Rotate tokens regularly
1113
+ - Use minimum required scopes
1114
+ - Implement server-side token refresh (Phase 3)
1115
+ - Log token refresh events
1116
+ - Monitor token usage for suspicious activity
1117
+
1118
+ ### ❌ DON'T
1119
+
1120
+ - Hardcode tokens in source files
1121
+ - Commit `.env` files to git
1122
+ - Share tokens between users
1123
+ - Use full account access when limited scope available
1124
+ - Log full tokens (log truncated: `ya29.a0...`)
1125
+ - Expose tokens in error messages
1126
+ - Store tokens in localStorage (browser)
1127
+ - Use same token for multiple apps
1128
+
1129
+ ## Troubleshooting
1130
+
1131
+ # Use in script
1132
+
1133
+ pnpm exec ts-node examples/gmail-oauth-usage.ts
1134
+
1135
+ # Or use in Node REPL
1136
+
1137
+ node
1138
+
1139
+ > process.env.GMAIL_ACCESS_TOKEN
1140
+ > // Use in matimo.execute()
1141
+
1142
+ ````
1143
+
1144
+ ## API Reference
1145
+
1146
+ ### send-email
1147
+
1148
+ Sends an email via Gmail API.
1149
+
1150
+ **Parameters:**
1151
+ - `to` (required): Recipient email(s), comma-separated
1152
+ - `subject` (required): Email subject
1153
+ - `body` (required): Email body (plain text or HTML)
1154
+ - `cc` (optional): CC recipients
1155
+ - `bcc` (optional): BCC recipients
1156
+ - `is_html` (optional): Treat body as HTML (default: false)
1157
+ - `GMAIL_ACCESS_TOKEN` (required): OAuth access token
1158
+
1159
+ **Response:**
1160
+ ```typescript
1161
+ {
1162
+ id: string; // Message ID
1163
+ threadId: string; // Thread ID
1164
+ labelIds: string[]; // Applied labels
1165
+ }
1166
+ ````
1167
+
1168
+ ### list-messages
1169
+
1170
+ Lists emails from your mailbox.
1171
+
1172
+ **Parameters:**
1173
+
1174
+ - `query` (optional): Search query (e.g., "from:user@example.com")
1175
+ - `maxResults` (optional): Max messages to return (1-500)
1176
+ - `pageToken` (optional): Token for pagination
1177
+ - `labelIds` (optional): Filter by label IDs
1178
+ - `includeSpamTrash` (optional): Include spam/trash
1179
+ - `GMAIL_ACCESS_TOKEN` (required): OAuth access token
1180
+
1181
+ **Response:**
1182
+
1183
+ ```typescript
1184
+ {
1185
+ messages: Array<{ id: string; threadId: string }>;
1186
+ nextPageToken?: string; // For pagination
1187
+ resultSizeEstimate: number;
1188
+ }
1189
+ ```
1190
+
1191
+ ### get-message
1192
+
1193
+ Gets a specific message with full details.
1194
+
1195
+ **Parameters:**
1196
+
1197
+ - `message_id` (required): Message ID to retrieve
1198
+ - `format` (optional): Response format ("minimal" | "full" | "raw")
1199
+ - `GMAIL_ACCESS_TOKEN` (required): OAuth access token
1200
+
1201
+ **Response:**
1202
+
1203
+ ```typescript
1204
+ {
1205
+ id: string;
1206
+ threadId: string;
1207
+ headers: Record<string, string>;
1208
+ body: { data?: string };
1209
+ attachments?: any[];
1210
+ }
1211
+ ```
1212
+
1213
+ ### create-draft
1214
+
1215
+ Creates a draft email.
1216
+
1217
+ **Parameters:**
1218
+
1219
+ - `to` (required): Draft recipient
1220
+ - `subject` (required): Draft subject
1221
+ - `body` (required): Draft body
1222
+ - `cc` (optional): CC recipients
1223
+ - `bcc` (optional): BCC recipients
1224
+ - `is_html` (optional): Treat body as HTML
1225
+ - `GMAIL_ACCESS_TOKEN` (required): OAuth access token
1226
+
1227
+ **Response:**
1228
+
1229
+ ```typescript
1230
+ {
1231
+ id: string; // Draft ID
1232
+ }
1233
+ ```
1234
+
1235
+ ### delete-message
1236
+
1237
+ Permanently deletes a message.
1238
+
1239
+ **Parameters:**
1240
+
1241
+ - `message_id` (required): Message ID to delete
1242
+ - `GMAIL_ACCESS_TOKEN` (required): OAuth access token
1243
+
1244
+ **Response:**
1245
+
1246
+ ```typescript
1247
+ {
1248
+ success: boolean;
1249
+ }
1250
+ ```
1251
+
1252
+ ## Additional Resources
1253
+
1254
+ - [Gmail API Documentation](https://developers.google.com/gmail/api)
1255
+ - [Gmail API Authentication Guide](https://developers.google.com/gmail/api/auth/about-auth)
1256
+ - [OAuth 2.0 Playground](https://developers.google.com/oauthplayground)
1257
+ - [Google Cloud Console](https://console.cloud.google.com/)
1258
+ - [Matimo Documentation](../../README.md)