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