#
tokens: 22111/50000 2/85 files (page 3/3)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 3 of 3. Use http://codebase.md/nylas-samples/nylas-api-mcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTION.md
├── nylas-code-samples
│   ├── Auth
│   │   ├── AdminConsent-Bulk
│   │   │   └── index.md
│   │   ├── AppPermission-Bulk
│   │   │   └── index.md
│   │   ├── auth.md
│   │   ├── connected-accounts.md
│   │   ├── Connectors
│   │   │   ├── ews.md
│   │   │   ├── google.md
│   │   │   ├── icloud.md
│   │   │   ├── imap.md
│   │   │   ├── index.md
│   │   │   ├── ms.md
│   │   │   ├── virtual-cal.md
│   │   │   └── yahoo.md
│   │   ├── Hosted
│   │   │   └── index.md
│   │   ├── Native-Custom
│   │   │   ├── index.md
│   │   │   └── virtual-cals-custom.md
│   │   └── Providers
│   │       ├── google-imported.md
│   │       ├── google-pubsub.md
│   │       ├── google.md
│   │       ├── ms-imported.md
│   │       └── ms.md
│   ├── Calendar
│   │   ├── Availability
│   │   │   └── index.md
│   │   ├── calendar-apis.md
│   │   ├── Calendars
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── Events
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── google.md
│   │   ├── ms.md
│   │   ├── Recurring
│   │   │   └── index.md
│   │   └── Virtual-Calendars
│   │       └── index.md
│   ├── Coda
│   │   ├── index.md
│   │   ├── testing.md
│   │   └── webhooks.md
│   ├── Contacts
│   │   ├── index.md
│   │   ├── read.md
│   │   ├── webhooks.md
│   │   └── write.md
│   ├── Email
│   │   ├── Drafts
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   └── write.md
│   │   ├── Files-Attachments
│   │   │   ├── index.md
│   │   │   └── read.md
│   │   ├── Labels-Folders
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── Messages
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── Outbox
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   ├── Search
│   │   │   ├── index.md
│   │   │   └── read.md
│   │   ├── Threads
│   │   │   ├── index.md
│   │   │   ├── read.md
│   │   │   ├── webhooks.md
│   │   │   └── write.md
│   │   └── Tracking
│   │       ├── index.md
│   │       └── webhooks.md
│   ├── Start
│   │   ├── api-import.md
│   │   ├── Dashboard-Import
│   │   │   └── index.md
│   │   ├── index.md
│   │   └── manual.md
│   └── Webhooks
│       ├── index.md
│       └── new-pubsub-note.md
├── package-lock.json
├── package.json
├── README.md
├── src
│   ├── index.ts
│   ├── prompts
│   │   └── index.ts
│   ├── resources
│   │   ├── code-samples.ts
│   │   ├── docs.ts
│   │   ├── endpoints.ts
│   │   └── index.ts
│   └── tools
│       └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/src/resources/endpoints.ts:
--------------------------------------------------------------------------------

```typescript
   1 | import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
   2 | 
   3 | /**
   4 |  * Register resources for Nylas API endpoints
   5 |  */
   6 | export function registerEndpointResources(server: McpServer) {
   7 |   // Register a resource that lists all available endpoints
   8 |   server.resource(
   9 |     "nylas-endpoints",
  10 |     "nylas://endpoints",
  11 |     async (uri) => ({
  12 |       contents: [{
  13 |         uri: uri.href,
  14 |         text: `# Nylas API Endpoints
  15 | 
  16 | This resource provides documentation for Nylas API endpoints organized by category.
  17 | 
  18 | ## Authentication
  19 | 
  20 | - [Authentication](nylas://endpoints/auth)
  21 | - [Connected Accounts](nylas://endpoints/connected-accounts)
  22 | 
  23 | ## Email
  24 | 
  25 | - [Messages](nylas://endpoints/messages)
  26 | - [Threads](nylas://endpoints/threads)
  27 | - [Drafts](nylas://endpoints/drafts)
  28 | - [Files & Attachments](nylas://endpoints/attachments)
  29 | - [Folders & Labels](nylas://endpoints/folders)
  30 | - [Search](nylas://endpoints/search)
  31 | 
  32 | ## Calendar
  33 | 
  34 | - [Calendars](nylas://endpoints/calendars)
  35 | - [Events](nylas://endpoints/events)
  36 | - [Availability](nylas://endpoints/availability)
  37 | - [Free/Busy](nylas://endpoints/free-busy)
  38 | 
  39 | ## Contacts
  40 | 
  41 | - [Contacts](nylas://endpoints/contacts)
  42 | 
  43 | ## Webhooks
  44 | 
  45 | - [Webhooks](nylas://endpoints/webhooks)`,
  46 |         mimeType: "text/markdown"
  47 |       }]
  48 |     })
  49 |   );
  50 | 
  51 |   // Register a resource for specific endpoint categories
  52 |   server.resource(
  53 |     "endpoint-category",
  54 |     new ResourceTemplate("nylas://endpoints/{category}", { list: undefined }),
  55 |     async (uri, { category }) => {
  56 |       // Convert category to string if it's an array
  57 |       const categoryStr = typeof category === 'string' ? category : category[0];
  58 |       
  59 |       // Map of categories to their endpoint documentation
  60 |       const categories: Record<string, string> = {
  61 |         "messages": `# Messages Endpoints
  62 | 
  63 | ## Overview
  64 | 
  65 | The Messages endpoints allow you to read, send, and manage email messages.
  66 | 
  67 | ## Endpoints
  68 | 
  69 | ### List Messages
  70 | 
  71 | \`GET /v3/grants/{grant_id}/messages\`
  72 | 
  73 | Retrieves a list of messages from a user's mailbox.
  74 | 
  75 | **Parameters:**
  76 | - \`grant_id\` (path): The ID of the grant
  77 | - \`limit\` (query): Maximum number of messages to return (default: 10, max: 100)
  78 | - \`offset\` (query): Pagination offset
  79 | - \`sort\` (query): Sort order (default: "-date")
  80 | - \`view\` (query): View type ("ids", "count", "expanded")
  81 | - \`thread_id\` (query): Filter by thread ID
  82 | - \`received_after\` (query): Filter by received date (Unix timestamp)
  83 | - \`received_before\` (query): Filter by received date (Unix timestamp)
  84 | - \`in\` (query): Filter by folder/label ID
  85 | 
  86 | **Response:**
  87 | - \`data\`: Array of message objects
  88 | - \`next_cursor\`: Cursor for pagination
  89 | - \`has_more\`: Boolean indicating if more results exist
  90 | 
  91 | ### Get Message
  92 | 
  93 | \`GET /v3/grants/{grant_id}/messages/{message_id}\`
  94 | 
  95 | Retrieves a specific message by ID.
  96 | 
  97 | **Parameters:**
  98 | - \`grant_id\` (path): The ID of the grant
  99 | - \`message_id\` (path): The ID of the message
 100 | 
 101 | **Response:**
 102 | - Message object with full details
 103 | 
 104 | ### Send Message
 105 | 
 106 | \`POST /v3/grants/{grant_id}/messages\`
 107 | 
 108 | Sends a new email message.
 109 | 
 110 | **Parameters:**
 111 | - \`grant_id\` (path): The ID of the grant
 112 | 
 113 | **Request Body:**
 114 | - \`subject\`: Email subject
 115 | - \`to\`: Array of recipient objects
 116 | - \`cc\` (optional): Array of CC recipient objects
 117 | - \`bcc\` (optional): Array of BCC recipient objects
 118 | - \`body\`: Email body content
 119 | - \`file_ids\` (optional): Array of file IDs to attach
 120 | 
 121 | **Response:**
 122 | - Created message object
 123 | 
 124 | ### Update Message
 125 | 
 126 | \`PUT /v3/grants/{grant_id}/messages/{message_id}\`
 127 | 
 128 | Updates a message's properties.
 129 | 
 130 | **Parameters:**
 131 | - \`grant_id\` (path): The ID of the grant
 132 | - \`message_id\` (path): The ID of the message
 133 | 
 134 | **Request Body:**
 135 | - \`unread\` (optional): Boolean indicating read/unread state
 136 | - \`starred\` (optional): Boolean indicating starred state
 137 | - \`folder_id\` (optional): ID of the folder to move the message to
 138 | 
 139 | **Response:**
 140 | - Updated message object
 141 | 
 142 | ### Delete Message
 143 | 
 144 | \`DELETE /v3/grants/{grant_id}/messages/{message_id}\`
 145 | 
 146 | Moves a message to the trash folder.
 147 | 
 148 | **Parameters:**
 149 | - \`grant_id\` (path): The ID of the grant
 150 | - \`message_id\` (path): The ID of the message
 151 | 
 152 | **Response:**
 153 | - \`status\`: Success status`,
 154 | 
 155 |         "threads": `# Threads Endpoints
 156 | 
 157 | ## Overview
 158 | 
 159 | The Threads endpoints allow you to read and manage email threads (conversations).
 160 | 
 161 | ## Endpoints
 162 | 
 163 | ### List Threads
 164 | 
 165 | \`GET /v3/grants/{grant_id}/threads\`
 166 | 
 167 | Retrieves a list of threads from a user's mailbox.
 168 | 
 169 | **Parameters:**
 170 | - \`grant_id\` (path): The ID of the grant
 171 | - \`limit\` (query): Maximum number of threads to return (default: 10, max: 100)
 172 | - \`offset\` (query): Pagination offset
 173 | - \`view\` (query): View type ("ids", "count", "expanded")
 174 | - \`received_after\` (query): Filter by received date (Unix timestamp)
 175 | - \`received_before\` (query): Filter by received date (Unix timestamp)
 176 | - \`in\` (query): Filter by folder/label ID
 177 | 
 178 | **Response:**
 179 | - \`data\`: Array of thread objects
 180 | - \`next_cursor\`: Cursor for pagination
 181 | - \`has_more\`: Boolean indicating if more results exist
 182 | 
 183 | ### Get Thread
 184 | 
 185 | \`GET /v3/grants/{grant_id}/threads/{thread_id}\`
 186 | 
 187 | Retrieves a specific thread by ID.
 188 | 
 189 | **Parameters:**
 190 | - \`grant_id\` (path): The ID of the grant
 191 | - \`thread_id\` (path): The ID of the thread
 192 | 
 193 | **Response:**
 194 | - Thread object with full details including messages
 195 | 
 196 | ### Update Thread
 197 | 
 198 | \`PUT /v3/grants/{grant_id}/threads/{thread_id}\`
 199 | 
 200 | Updates a thread's properties.
 201 | 
 202 | **Parameters:**
 203 | - \`grant_id\` (path): The ID of the grant
 204 | - \`thread_id\` (path): The ID of the thread
 205 | 
 206 | **Request Body:**
 207 | - \`unread\` (optional): Boolean indicating read/unread state
 208 | - \`starred\` (optional): Boolean indicating starred state
 209 | - \`folder_id\` (optional): ID of the folder to move the thread to
 210 | 
 211 | **Response:**
 212 | - Updated thread object`,
 213 | 
 214 |         "drafts": `# Drafts Endpoints
 215 | 
 216 | ## Overview
 217 | 
 218 | The Drafts endpoints allow you to create, read, update, and send email drafts.
 219 | 
 220 | ## Endpoints
 221 | 
 222 | ### List Drafts
 223 | 
 224 | \`GET /v3/grants/{grant_id}/drafts\`
 225 | 
 226 | Retrieves a list of drafts from a user's mailbox.
 227 | 
 228 | **Parameters:**
 229 | - \`grant_id\` (path): The ID of the grant
 230 | - \`limit\` (query): Maximum number of drafts to return (default: 10, max: 100)
 231 | - \`offset\` (query): Pagination offset
 232 | 
 233 | **Response:**
 234 | - \`data\`: Array of draft objects
 235 | - \`next_cursor\`: Cursor for pagination
 236 | - \`has_more\`: Boolean indicating if more results exist
 237 | 
 238 | ### Get Draft
 239 | 
 240 | \`GET /v3/grants/{grant_id}/drafts/{draft_id}\`
 241 | 
 242 | Retrieves a specific draft by ID.
 243 | 
 244 | **Parameters:**
 245 | - \`grant_id\` (path): The ID of the grant
 246 | - \`draft_id\` (path): The ID of the draft
 247 | 
 248 | **Response:**
 249 | - Draft object with full details
 250 | 
 251 | ### Create Draft
 252 | 
 253 | \`POST /v3/grants/{grant_id}/drafts\`
 254 | 
 255 | Creates a new email draft.
 256 | 
 257 | **Parameters:**
 258 | - \`grant_id\` (path): The ID of the grant
 259 | 
 260 | **Request Body:**
 261 | - \`subject\`: Email subject
 262 | - \`to\` (optional): Array of recipient objects
 263 | - \`cc\` (optional): Array of CC recipient objects
 264 | - \`bcc\` (optional): Array of BCC recipient objects
 265 | - \`body\` (optional): Email body content
 266 | - \`file_ids\` (optional): Array of file IDs to attach
 267 | 
 268 | **Response:**
 269 | - Created draft object
 270 | 
 271 | ### Update Draft
 272 | 
 273 | \`PUT /v3/grants/{grant_id}/drafts/{draft_id}\`
 274 | 
 275 | Updates an existing draft.
 276 | 
 277 | **Parameters:**
 278 | - \`grant_id\` (path): The ID of the grant
 279 | - \`draft_id\` (path): The ID of the draft
 280 | 
 281 | **Request Body:**
 282 | - \`subject\` (optional): Email subject
 283 | - \`to\` (optional): Array of recipient objects
 284 | - \`cc\` (optional): Array of CC recipient objects
 285 | - \`bcc\` (optional): Array of BCC recipient objects
 286 | - \`body\` (optional): Email body content
 287 | - \`file_ids\` (optional): Array of file IDs to attach
 288 | 
 289 | **Response:**
 290 | - Updated draft object
 291 | 
 292 | ### Delete Draft
 293 | 
 294 | \`DELETE /v3/grants/{grant_id}/drafts/{draft_id}\`
 295 | 
 296 | Deletes a draft.
 297 | 
 298 | **Parameters:**
 299 | - \`grant_id\` (path): The ID of the grant
 300 | - \`draft_id\` (path): The ID of the draft
 301 | 
 302 | **Response:**
 303 | - \`status\`: Success status
 304 | 
 305 | ### Send Draft
 306 | 
 307 | \`POST /v3/grants/{grant_id}/drafts/{draft_id}/send\`
 308 | 
 309 | Sends an existing draft.
 310 | 
 311 | **Parameters:**
 312 | - \`grant_id\` (path): The ID of the grant
 313 | - \`draft_id\` (path): The ID of the draft
 314 | 
 315 | **Response:**
 316 | - Sent message object`,
 317 | 
 318 |         "attachments": `# Files & Attachments Endpoints
 319 | 
 320 | ## Overview
 321 | 
 322 | The Files & Attachments endpoints allow you to upload, download, and manage files attached to emails.
 323 | 
 324 | ## Endpoints
 325 | 
 326 | ### List Files
 327 | 
 328 | \`GET /v3/grants/{grant_id}/files\`
 329 | 
 330 | Retrieves a list of files attached to emails.
 331 | 
 332 | **Parameters:**
 333 | - \`grant_id\` (path): The ID of the grant
 334 | - \`limit\` (query): Maximum number of files to return (default: 10, max: 100)
 335 | - \`offset\` (query): Pagination offset
 336 | - \`message_id\` (query): Filter by message ID
 337 | 
 338 | **Response:**
 339 | - \`data\`: Array of file objects
 340 | - \`next_cursor\`: Cursor for pagination
 341 | - \`has_more\`: Boolean indicating if more results exist
 342 | 
 343 | ### Get File
 344 | 
 345 | \`GET /v3/grants/{grant_id}/files/{file_id}\`
 346 | 
 347 | Retrieves metadata for a specific file.
 348 | 
 349 | **Parameters:**
 350 | - \`grant_id\` (path): The ID of the grant
 351 | - \`file_id\` (path): The ID of the file
 352 | 
 353 | **Response:**
 354 | - File object with metadata
 355 | 
 356 | ### Download File
 357 | 
 358 | \`GET /v3/grants/{grant_id}/files/{file_id}/download\`
 359 | 
 360 | Downloads the content of a file.
 361 | 
 362 | **Parameters:**
 363 | - \`grant_id\` (path): The ID of the grant
 364 | - \`file_id\` (path): The ID of the file
 365 | 
 366 | **Response:**
 367 | - Binary file content with appropriate Content-Type header
 368 | 
 369 | ### Upload File
 370 | 
 371 | \`POST /v3/grants/{grant_id}/files\`
 372 | 
 373 | Uploads a new file to be attached to emails.
 374 | 
 375 | **Parameters:**
 376 | - \`grant_id\` (path): The ID of the grant
 377 | 
 378 | **Request Body:**
 379 | - Multipart form data with file content
 380 | 
 381 | **Response:**
 382 | - Uploaded file object with ID for attachment`,
 383 | 
 384 |         "folders": `# Folders & Labels Endpoints
 385 | 
 386 | ## Overview
 387 | 
 388 | The Folders & Labels endpoints allow you to manage email organization structures.
 389 | 
 390 | ## Endpoints
 391 | 
 392 | ### List Folders
 393 | 
 394 | \`GET /v3/grants/{grant_id}/folders\`
 395 | 
 396 | Retrieves a list of folders from a user's mailbox.
 397 | 
 398 | **Parameters:**
 399 | - \`grant_id\` (path): The ID of the grant
 400 | 
 401 | **Response:**
 402 | - \`data\`: Array of folder objects
 403 | 
 404 | ### Get Folder
 405 | 
 406 | \`GET /v3/grants/{grant_id}/folders/{folder_id}\`
 407 | 
 408 | Retrieves a specific folder by ID.
 409 | 
 410 | **Parameters:**
 411 | - \`grant_id\` (path): The ID of the grant
 412 | - \`folder_id\` (path): The ID of the folder
 413 | 
 414 | **Response:**
 415 | - Folder object with details
 416 | 
 417 | ### Create Folder
 418 | 
 419 | \`POST /v3/grants/{grant_id}/folders\`
 420 | 
 421 | Creates a new folder.
 422 | 
 423 | **Parameters:**
 424 | - \`grant_id\` (path): The ID of the grant
 425 | 
 426 | **Request Body:**
 427 | - \`name\`: Folder name
 428 | - \`parent_id\` (optional): Parent folder ID for nested folders
 429 | 
 430 | **Response:**
 431 | - Created folder object
 432 | 
 433 | ### Update Folder
 434 | 
 435 | \`PUT /v3/grants/{grant_id}/folders/{folder_id}\`
 436 | 
 437 | Updates a folder's properties.
 438 | 
 439 | **Parameters:**
 440 | - \`grant_id\` (path): The ID of the grant
 441 | - \`folder_id\` (path): The ID of the folder
 442 | 
 443 | **Request Body:**
 444 | - \`name\` (optional): New folder name
 445 | - \`parent_id\` (optional): New parent folder ID
 446 | 
 447 | **Response:**
 448 | - Updated folder object
 449 | 
 450 | ### Delete Folder
 451 | 
 452 | \`DELETE /v3/grants/{grant_id}/folders/{folder_id}\`
 453 | 
 454 | Deletes a folder.
 455 | 
 456 | **Parameters:**
 457 | - \`grant_id\` (path): The ID of the grant
 458 | - \`folder_id\` (path): The ID of the folder
 459 | 
 460 | **Response:**
 461 | - \`status\`: Success status`,
 462 | 
 463 |         "search": `# Search Endpoints
 464 | 
 465 | ## Overview
 466 | 
 467 | The Search endpoints allow you to search for emails by various criteria.
 468 | 
 469 | ## Endpoints
 470 | 
 471 | ### Search Messages
 472 | 
 473 | \`GET /v3/grants/{grant_id}/messages/search\`
 474 | 
 475 | Searches for messages matching specific criteria.
 476 | 
 477 | **Parameters:**
 478 | - \`grant_id\` (path): The ID of the grant
 479 | - \`q\` (query): Search query string
 480 | - \`limit\` (query): Maximum number of results to return (default: 10, max: 100)
 481 | - \`offset\` (query): Pagination offset
 482 | - \`in\` (query): Filter by folder/label ID
 483 | - \`date_gt\` (query): Filter by date greater than (Unix timestamp)
 484 | - \`date_lt\` (query): Filter by date less than (Unix timestamp)
 485 | 
 486 | **Response:**
 487 | - \`data\`: Array of matching message objects
 488 | - \`next_cursor\`: Cursor for pagination
 489 | - \`has_more\`: Boolean indicating if more results exist
 490 | 
 491 | ### Search Threads
 492 | 
 493 | \`GET /v3/grants/{grant_id}/threads/search\`
 494 | 
 495 | Searches for threads matching specific criteria.
 496 | 
 497 | **Parameters:**
 498 | - \`grant_id\` (path): The ID of the grant
 499 | - \`q\` (query): Search query string
 500 | - \`limit\` (query): Maximum number of results to return (default: 10, max: 100)
 501 | - \`offset\` (query): Pagination offset
 502 | - \`in\` (query): Filter by folder/label ID
 503 | - \`date_gt\` (query): Filter by date greater than (Unix timestamp)
 504 | - \`date_lt\` (query): Filter by date less than (Unix timestamp)
 505 | 
 506 | **Response:**
 507 | - \`data\`: Array of matching thread objects
 508 | - \`next_cursor\`: Cursor for pagination
 509 | - \`has_more\`: Boolean indicating if more results exist`,
 510 | 
 511 |         "calendars": `# Calendars Endpoints
 512 | 
 513 | ## Overview
 514 | 
 515 | The Calendars endpoints allow you to read and manage calendar containers.
 516 | 
 517 | ## Endpoints
 518 | 
 519 | ### List Calendars
 520 | 
 521 | \`GET /v3/grants/{grant_id}/calendars\`
 522 | 
 523 | Retrieves a list of calendars for a user.
 524 | 
 525 | **Parameters:**
 526 | - \`grant_id\` (path): The ID of the grant
 527 | 
 528 | **Response:**
 529 | - \`data\`: Array of calendar objects
 530 | 
 531 | ### Get Calendar
 532 | 
 533 | \`GET /v3/grants/{grant_id}/calendars/{calendar_id}\`
 534 | 
 535 | Retrieves a specific calendar by ID.
 536 | 
 537 | **Parameters:**
 538 | - \`grant_id\` (path): The ID of the grant
 539 | - \`calendar_id\` (path): The ID of the calendar
 540 | 
 541 | **Response:**
 542 | - Calendar object with details
 543 | 
 544 | ### Create Calendar
 545 | 
 546 | \`POST /v3/grants/{grant_id}/calendars\`
 547 | 
 548 | Creates a new calendar.
 549 | 
 550 | **Parameters:**
 551 | - \`grant_id\` (path): The ID of the grant
 552 | 
 553 | **Request Body:**
 554 | - \`name\`: Calendar name
 555 | - \`description\` (optional): Calendar description
 556 | - \`location\` (optional): Calendar location
 557 | - \`timezone\` (optional): Calendar timezone
 558 | - \`metadata\` (optional): Custom metadata
 559 | 
 560 | **Response:**
 561 | - Created calendar object
 562 | 
 563 | ### Update Calendar
 564 | 
 565 | \`PUT /v3/grants/{grant_id}/calendars/{calendar_id}\`
 566 | 
 567 | Updates a calendar's properties.
 568 | 
 569 | **Parameters:**
 570 | - \`grant_id\` (path): The ID of the grant
 571 | - \`calendar_id\` (path): The ID of the calendar
 572 | 
 573 | **Request Body:**
 574 | - \`name\` (optional): New calendar name
 575 | - \`description\` (optional): New calendar description
 576 | - \`location\` (optional): New calendar location
 577 | - \`timezone\` (optional): New calendar timezone
 578 | - \`metadata\` (optional): Updated custom metadata
 579 | 
 580 | **Response:**
 581 | - Updated calendar object
 582 | 
 583 | ### Delete Calendar
 584 | 
 585 | \`DELETE /v3/grants/{grant_id}/calendars/{calendar_id}\`
 586 | 
 587 | Deletes a calendar.
 588 | 
 589 | **Parameters:**
 590 | - \`grant_id\` (path): The ID of the grant
 591 | - \`calendar_id\` (path): The ID of the calendar
 592 | 
 593 | **Response:**
 594 | - \`status\`: Success status`,
 595 | 
 596 |         "events": `# Events Endpoints
 597 | 
 598 | ## Overview
 599 | 
 600 | The Events endpoints allow you to read, create, update, and delete calendar events.
 601 | 
 602 | ## Endpoints
 603 | 
 604 | ### List Events
 605 | 
 606 | \`GET /v3/grants/{grant_id}/events\`
 607 | 
 608 | Retrieves a list of events from a user's calendars.
 609 | 
 610 | **Parameters:**
 611 | - \`grant_id\` (path): The ID of the grant
 612 | - \`calendar_id\` (query): Filter by calendar ID
 613 | - \`limit\` (query): Maximum number of events to return (default: 10, max: 100)
 614 | - \`offset\` (query): Pagination offset
 615 | - \`start_time\` (query): Filter by start time (Unix timestamp)
 616 | - \`end_time\` (query): Filter by end time (Unix timestamp)
 617 | - \`show_cancelled\` (query): Include cancelled events (default: false)
 618 | 
 619 | **Response:**
 620 | - \`data\`: Array of event objects
 621 | - \`next_cursor\`: Cursor for pagination
 622 | - \`has_more\`: Boolean indicating if more results exist
 623 | 
 624 | ### Get Event
 625 | 
 626 | \`GET /v3/grants/{grant_id}/events/{event_id}\`
 627 | 
 628 | Retrieves a specific event by ID.
 629 | 
 630 | **Parameters:**
 631 | - \`grant_id\` (path): The ID of the grant
 632 | - \`event_id\` (path): The ID of the event
 633 | 
 634 | **Response:**
 635 | - Event object with full details
 636 | 
 637 | ### Create Event
 638 | 
 639 | \`POST /v3/grants/{grant_id}/events\`
 640 | 
 641 | Creates a new calendar event.
 642 | 
 643 | **Parameters:**
 644 | - \`grant_id\` (path): The ID of the grant
 645 | 
 646 | **Request Body:**
 647 | - \`calendar_id\`: Calendar ID to create the event in
 648 | - \`title\`: Event title
 649 | - \`start_time\`: Event start time (Unix timestamp)
 650 | - \`end_time\`: Event end time (Unix timestamp)
 651 | - \`description\` (optional): Event description
 652 | - \`location\` (optional): Event location
 653 | - \`participants\` (optional): Array of participant objects
 654 | - \`conferencing\` (optional): Conferencing details
 655 | - \`busy\` (optional): Whether the event shows as busy (default: true)
 656 | - \`reminders\` (optional): Array of reminder objects
 657 | - \`recurrence\` (optional): Recurrence rule
 658 | 
 659 | **Response:**
 660 | - Created event object
 661 | 
 662 | ### Update Event
 663 | 
 664 | \`PUT /v3/grants/{grant_id}/events/{event_id}\`
 665 | 
 666 | Updates an existing event.
 667 | 
 668 | **Parameters:**
 669 | - \`grant_id\` (path): The ID of the grant
 670 | - \`event_id\` (path): The ID of the event
 671 | 
 672 | **Request Body:**
 673 | - \`calendar_id\` (optional): Calendar ID to move the event to
 674 | - \`title\` (optional): New event title
 675 | - \`start_time\` (optional): New event start time (Unix timestamp)
 676 | - \`end_time\` (optional): New event end time (Unix timestamp)
 677 | - \`description\` (optional): New event description
 678 | - \`location\` (optional): New event location
 679 | - \`participants\` (optional): Updated array of participant objects
 680 | - \`conferencing\` (optional): Updated conferencing details
 681 | - \`busy\` (optional): Whether the event shows as busy
 682 | - \`reminders\` (optional): Updated array of reminder objects
 683 | - \`recurrence\` (optional): Updated recurrence rule
 684 | 
 685 | **Response:**
 686 | - Updated event object
 687 | 
 688 | ### Delete Event
 689 | 
 690 | \`DELETE /v3/grants/{grant_id}/events/{event_id}\`
 691 | 
 692 | Deletes an event.
 693 | 
 694 | **Parameters:**
 695 | - \`grant_id\` (path): The ID of the grant
 696 | - \`event_id\` (path): The ID of the event
 697 | 
 698 | **Response:**
 699 | - \`status\`: Success status`,
 700 | 
 701 |         "availability": `# Availability Endpoints
 702 | 
 703 | ## Overview
 704 | 
 705 | The Availability endpoints allow you to find free/busy information and available times.
 706 | 
 707 | ## Endpoints
 708 | 
 709 | ### Get Availability
 710 | 
 711 | \`POST /v3/grants/{grant_id}/calendars/availability\`
 712 | 
 713 | Finds available time slots across multiple participants' calendars.
 714 | 
 715 | **Parameters:**
 716 | - \`grant_id\` (path): The ID of the grant
 717 | 
 718 | **Request Body:**
 719 | - \`start_time\`: Start of the time range to check (Unix timestamp)
 720 | - \`end_time\`: End of the time range to check (Unix timestamp)
 721 | - \`duration_minutes\`: Length of the slots to find
 722 | - \`participants\`: Array of participant objects with emails
 723 | - \`interval_minutes\` (optional): Interval between potential slots (default: 15)
 724 | - \`availability_rule\` (optional): Rule for determining availability ("any" or "all", default: "all")
 725 | - \`buffer_minutes\` (optional): Buffer time between meetings (default: 0)
 726 | - \`working_hours\` (optional): Working hours constraints
 727 | - \`open_hours\` (optional): Open hours constraints
 728 | 
 729 | **Response:**
 730 | - \`time_slots\`: Array of available time slot objects
 731 | - \`timezone\`: Timezone used for calculations`,
 732 | 
 733 |         "free-busy": `# Free/Busy Endpoints
 734 | 
 735 | ## Overview
 736 | 
 737 | The Free/Busy endpoints allow you to check when users are free or busy.
 738 | 
 739 | ## Endpoints
 740 | 
 741 | ### Get Free/Busy
 742 | 
 743 | \`POST /v3/grants/{grant_id}/calendars/free-busy\`
 744 | 
 745 | Retrieves free/busy information for users.
 746 | 
 747 | **Parameters:**
 748 | - \`grant_id\` (path): The ID of the grant
 749 | 
 750 | **Request Body:**
 751 | - \`start_time\`: Start of the time range to check (Unix timestamp)
 752 | - \`end_time\`: End of the time range to check (Unix timestamp)
 753 | - \`emails\`: Array of email addresses to check
 754 | 
 755 | **Response:**
 756 | - \`free_busy\`: Object mapping emails to arrays of busy time periods`,
 757 | 
 758 |         "contacts": `# Contacts Endpoints
 759 | 
 760 | ## Overview
 761 | 
 762 | The Contacts endpoints allow you to read, create, update, and delete contact information.
 763 | 
 764 | ## Endpoints
 765 | 
 766 | ### List Contacts
 767 | 
 768 | \`GET /v3/grants/{grant_id}/contacts\`
 769 | 
 770 | Retrieves a list of contacts.
 771 | 
 772 | **Parameters:**
 773 | - \`grant_id\` (path): The ID of the grant
 774 | - \`limit\` (query): Maximum number of contacts to return (default: 10, max: 100)
 775 | - \`offset\` (query): Pagination offset
 776 | - \`email\` (query): Filter by email address
 777 | - \`phone_number\` (query): Filter by phone number
 778 | - \`source\` (query): Filter by source of the contact
 779 | 
 780 | **Response:**
 781 | - \`data\`: Array of contact objects
 782 | - \`next_cursor\`: Cursor for pagination
 783 | - \`has_more\`: Boolean indicating if more results exist
 784 | 
 785 | ### Get Contact
 786 | 
 787 | \`GET /v3/grants/{grant_id}/contacts/{contact_id}\`
 788 | 
 789 | Retrieves a specific contact by ID.
 790 | 
 791 | **Parameters:**
 792 | - \`grant_id\` (path): The ID of the grant
 793 | - \`contact_id\` (path): The ID of the contact
 794 | 
 795 | **Response:**
 796 | - Contact object with full details
 797 | 
 798 | ### Create Contact
 799 | 
 800 | \`POST /v3/grants/{grant_id}/contacts\`
 801 | 
 802 | Creates a new contact.
 803 | 
 804 | **Parameters:**
 805 | - \`grant_id\` (path): The ID of the grant
 806 | 
 807 | **Request Body:**
 808 | - \`given_name\` (optional): First name
 809 | - \`middle_name\` (optional): Middle name
 810 | - \`surname\` (optional): Last name
 811 | - \`nickname\` (optional): Nickname
 812 | - \`emails\` (optional): Array of email objects
 813 | - \`phone_numbers\` (optional): Array of phone number objects
 814 | - \`physical_addresses\` (optional): Array of address objects
 815 | - \`web_pages\` (optional): Array of web page objects
 816 | - \`notes\` (optional): Notes about the contact
 817 | - \`job_title\` (optional): Job title
 818 | - \`company_name\` (optional): Company name
 819 | - \`picture\` (optional): Profile picture URL
 820 | - \`birthday\` (optional): Birthday (Unix timestamp)
 821 | 
 822 | **Response:**
 823 | - Created contact object
 824 | 
 825 | ### Update Contact
 826 | 
 827 | \`PUT /v3/grants/{grant_id}/contacts/{contact_id}\`
 828 | 
 829 | Updates an existing contact.
 830 | 
 831 | **Parameters:**
 832 | - \`grant_id\` (path): The ID of the grant
 833 | - \`contact_id\` (path): The ID of the contact
 834 | 
 835 | **Request Body:**
 836 | - \`given_name\` (optional): Updated first name
 837 | - \`middle_name\` (optional): Updated middle name
 838 | - \`surname\` (optional): Updated last name
 839 | - \`nickname\` (optional): Updated nickname
 840 | - \`emails\` (optional): Updated array of email objects
 841 | - \`phone_numbers\` (optional): Updated array of phone number objects
 842 | - \`physical_addresses\` (optional): Updated array of address objects
 843 | - \`web_pages\` (optional): Updated array of web page objects
 844 | - \`notes\` (optional): Updated notes about the contact
 845 | - \`job_title\` (optional): Updated job title
 846 | - \`company_name\` (optional): Updated company name
 847 | - \`picture\` (optional): Updated profile picture URL
 848 | - \`birthday\` (optional): Updated birthday (Unix timestamp)
 849 | 
 850 | **Response:**
 851 | - Updated contact object
 852 | 
 853 | ### Delete Contact
 854 | 
 855 | \`DELETE /v3/grants/{grant_id}/contacts/{contact_id}\`
 856 | 
 857 | Deletes a contact.
 858 | 
 859 | **Parameters:**
 860 | - \`grant_id\` (path): The ID of the grant
 861 | - \`contact_id\` (path): The ID of the contact
 862 | 
 863 | **Response:**
 864 | - \`status\`: Success status`,
 865 | 
 866 |         "webhooks": `# Webhooks Endpoints
 867 | 
 868 | ## Overview
 869 | 
 870 | The Webhooks endpoints allow you to set up real-time notifications for changes to user data.
 871 | 
 872 | ## Endpoints
 873 | 
 874 | ### List Webhooks
 875 | 
 876 | \`GET /v3/applications/{application_id}/webhooks\`
 877 | 
 878 | Retrieves a list of webhooks for an application.
 879 | 
 880 | **Parameters:**
 881 | - \`application_id\` (path): The ID of the application
 882 | - \`limit\` (query): Maximum number of webhooks to return (default: 10, max: 100)
 883 | - \`offset\` (query): Pagination offset
 884 | 
 885 | **Response:**
 886 | - \`data\`: Array of webhook objects
 887 | - \`next_cursor\`: Cursor for pagination
 888 | - \`has_more\`: Boolean indicating if more results exist
 889 | 
 890 | ### Get Webhook
 891 | 
 892 | \`GET /v3/applications/{application_id}/webhooks/{webhook_id}\`
 893 | 
 894 | Retrieves a specific webhook by ID.
 895 | 
 896 | **Parameters:**
 897 | - \`application_id\` (path): The ID of the application
 898 | - \`webhook_id\` (path): The ID of the webhook
 899 | 
 900 | **Response:**
 901 | - Webhook object with full details
 902 | 
 903 | ### Create Webhook
 904 | 
 905 | \`POST /v3/applications/{application_id}/webhooks\`
 906 | 
 907 | Creates a new webhook.
 908 | 
 909 | **Parameters:**
 910 | - \`application_id\` (path): The ID of the application
 911 | 
 912 | **Request Body:**
 913 | - \`webhook_url\`: URL to send webhook events to
 914 | - \`description\` (optional): Description of the webhook
 915 | - \`trigger_types\`: Array of event types to trigger the webhook
 916 | - \`webhook_secret\` (optional): Secret for securing webhook payloads
 917 | - \`grant_id\` (optional): Specific grant ID to monitor (omit for all grants)
 918 | 
 919 | **Response:**
 920 | - Created webhook object
 921 | 
 922 | ### Update Webhook
 923 | 
 924 | \`PUT /v3/applications/{application_id}/webhooks/{webhook_id}\`
 925 | 
 926 | Updates an existing webhook.
 927 | 
 928 | **Parameters:**
 929 | - \`application_id\` (path): The ID of the application
 930 | - \`webhook_id\` (path): The ID of the webhook
 931 | 
 932 | **Request Body:**
 933 | - \`webhook_url\` (optional): Updated URL to send webhook events to
 934 | - \`description\` (optional): Updated description of the webhook
 935 | - \`trigger_types\` (optional): Updated array of event types to trigger the webhook
 936 | - \`webhook_secret\` (optional): Updated secret for securing webhook payloads
 937 | - \`status\` (optional): Updated status ("active" or "disabled")
 938 | 
 939 | **Response:**
 940 | - Updated webhook object
 941 | 
 942 | ### Delete Webhook
 943 | 
 944 | \`DELETE /v3/applications/{application_id}/webhooks/{webhook_id}\`
 945 | 
 946 | Deletes a webhook.
 947 | 
 948 | **Parameters:**
 949 | - \`application_id\` (path): The ID of the application
 950 | - \`webhook_id\` (path): The ID of the webhook
 951 | 
 952 | **Response:**
 953 | - \`status\`: Success status
 954 | 
 955 | ### Rotate Webhook Secret
 956 | 
 957 | \`POST /v3/applications/{application_id}/webhooks/{webhook_id}/rotate-secret\`
 958 | 
 959 | Generates a new secret for a webhook.
 960 | 
 961 | **Parameters:**
 962 | - \`application_id\` (path): The ID of the application
 963 | - \`webhook_id\` (path): The ID of the webhook
 964 | 
 965 | **Response:**
 966 | - \`webhook_secret\`: The new webhook secret`,
 967 |         
 968 |         "auth": `# Authentication Endpoints
 969 | 
 970 | ## Overview
 971 | 
 972 | The Authentication endpoints allow you to initiate the OAuth flow and manage authentication tokens.
 973 | 
 974 | ## Endpoints
 975 | 
 976 | ### Generate Authentication URL
 977 | 
 978 | \`GET /v3/connect/oauth/authorize\`
 979 | 
 980 | Generates a URL to redirect users to for authentication.
 981 | 
 982 | **Parameters:**
 983 | - \`client_id\` (query): Your application's client ID
 984 | - \`redirect_uri\` (query): URL to redirect to after authentication
 985 | - \`response_type\` (query): Authentication response type (default: "code")
 986 | - \`scopes\` (query): Comma-separated list of permission scopes
 987 | - \`state\` (query): Optional state parameter for security
 988 | - \`provider\` (query, optional): Email provider ("google", "microsoft", etc.)
 989 | - \`login_hint\` (query, optional): User's email address for pre-filling
 990 | 
 991 | **Response:**
 992 | - Redirect to the authentication URL
 993 | 
 994 | ### Exchange Code for Token
 995 | 
 996 | \`POST /v3/connect/oauth/token\`
 997 | 
 998 | Exchanges an authentication code for an access token.
 999 | 
1000 | **Request Body:**
1001 | - \`client_id\`: Your application's client ID
1002 | - \`client_secret\`: Your application's client secret
1003 | - \`grant_type\`: Type of grant (use "authorization_code")
1004 | - \`code\`: The authorization code received from the redirect
1005 | - \`redirect_uri\`: The same redirect URI used in the authorization request
1006 | 
1007 | **Response:**
1008 | - \`access_token\`: The access token for API requests
1009 | - \`token_type\`: Type of token (usually "bearer")
1010 | - \`expires_in\`: Time until token expiration (in seconds)
1011 | - \`refresh_token\`: Token for obtaining a new access token
1012 | - \`scope\`: Granted permission scopes
1013 | - \`grant_id\`: ID of the newly created grant
1014 | 
1015 | ### Refresh Token
1016 | 
1017 | \`POST /v3/connect/oauth/token\`
1018 | 
1019 | Refreshes an expired access token.
1020 | 
1021 | **Request Body:**
1022 | - \`client_id\`: Your application's client ID
1023 | - \`client_secret\`: Your application's client secret
1024 | - \`grant_type\`: Type of grant (use "refresh_token")
1025 | - \`refresh_token\`: The refresh token received previously
1026 | 
1027 | **Response:**
1028 | - \`access_token\`: New access token for API requests
1029 | - \`token_type\`: Type of token (usually "bearer")
1030 | - \`expires_in\`: Time until token expiration (in seconds)
1031 | - \`refresh_token\`: New refresh token
1032 | - \`scope\`: Granted permission scopes`,
1033 | 
1034 |         "connected-accounts": `# Connected Accounts Endpoints
1035 | 
1036 | ## Overview
1037 | 
1038 | The Connected Accounts endpoints allow you to manage user accounts connected to your application.
1039 | 
1040 | ## Endpoints
1041 | 
1042 | ### List Grants
1043 | 
1044 | \`GET /v3/applications/{application_id}/grants\`
1045 | 
1046 | Retrieves a list of grants (connected accounts) for your application.
1047 | 
1048 | **Parameters:**
1049 | - \`application_id\` (path): The ID of your application
1050 | - \`limit\` (query): Maximum number of grants to return (default: 10, max: 100)
1051 | - \`offset\` (query): Pagination offset
1052 | - \`provider\` (query, optional): Filter by provider
1053 | - \`email\` (query, optional): Filter by email address
1054 | 
1055 | **Response:**
1056 | - \`data\`: Array of grant objects
1057 | - \`next_cursor\`: Cursor for pagination
1058 | - \`has_more\`: Boolean indicating if more results exist
1059 | 
1060 | ### Get Grant
1061 | 
1062 | \`GET /v3/applications/{application_id}/grants/{grant_id}\`
1063 | 
1064 | Retrieves a specific grant by ID.
1065 | 
1066 | **Parameters:**
1067 | - \`application_id\` (path): The ID of your application
1068 | - \`grant_id\` (path): The ID of the grant
1069 | 
1070 | **Response:**
1071 | - Grant object with full details
1072 | 
1073 | ### Delete Grant
1074 | 
1075 | \`DELETE /v3/applications/{application_id}/grants/{grant_id}\`
1076 | 
1077 | Revokes a grant, disconnecting the user's account.
1078 | 
1079 | **Parameters:**
1080 | - \`application_id\` (path): The ID of your application
1081 | - \`grant_id\` (path): The ID of the grant
1082 | 
1083 | **Response:**
1084 | - \`status\`: Success status
1085 | 
1086 | ### Update Grant
1087 | 
1088 | \`PUT /v3/applications/{application_id}/grants/{grant_id}\`
1089 | 
1090 | Updates properties of a grant.
1091 | 
1092 | **Parameters:**
1093 | - \`application_id\` (path): The ID of your application
1094 | - \`grant_id\` (path): The ID of the grant
1095 | 
1096 | **Request Body:**
1097 | - \`status\` (optional): New status ("active" or "disabled")
1098 | - \`ip_restrictions\` (optional): IP address restrictions
1099 | - \`scopes\` (optional): Updated permission scopes
1100 | 
1101 | **Response:**
1102 | - Updated grant object`
1103 |       };
1104 |       
1105 |       // Return the content for the requested category, or a not found message
1106 |       const content = categories[categoryStr] || `# Category Not Found\n\nThe requested endpoint category "${categoryStr}" is not available.`;
1107 |       
1108 |       return {
1109 |         contents: [{
1110 |           uri: uri.href,
1111 |           text: content,
1112 |           mimeType: "text/markdown"
1113 |         }]
1114 |       };
1115 |     }
1116 |   );
1117 | }
```

--------------------------------------------------------------------------------
/src/tools/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { z } from "zod";
  3 | 
  4 | /**
  5 |  * Register all tools with the MCP server
  6 |  */
  7 | export function registerTools(server: McpServer) {
  8 |   // Register code generation tools
  9 |   registerCodeGenerationTools(server);
 10 |   
 11 |   // Register API explorer tools
 12 |   registerApiExplorerTools(server);
 13 | }
 14 | 
 15 | /**
 16 |  * Register code generation tools
 17 |  */
 18 | function registerCodeGenerationTools(server: McpServer) {
 19 |   // Tool to generate authentication code for a specific language
 20 |   server.tool(
 21 |     "generate-auth-code",
 22 |     {
 23 |       language: z.enum(["node", "python", "java", "ruby", "curl"]),
 24 |       clientId: z.string().optional(),
 25 |       clientSecret: z.string().optional(),
 26 |       redirectUri: z.string().optional(),
 27 |       scopes: z.array(z.string()).optional()
 28 |     },
 29 |     async ({ language, clientId, clientSecret, redirectUri, scopes }) => {
 30 |       const normalizedLanguage = normalizeLanguage(language);
 31 |       const placeholderClientId = clientId || "YOUR_CLIENT_ID";
 32 |       const placeholderClientSecret = clientSecret || "YOUR_CLIENT_SECRET";
 33 |       const placeholderRedirectUri = redirectUri || "YOUR_REDIRECT_URI";
 34 |       const placeholderScopes = scopes || ["email", "calendar", "contacts"];
 35 |       
 36 |       // Map of languages to their authentication code templates
 37 |       const templates: Record<string, string> = {
 38 |         "Node": `
 39 | // Authentication with Nylas API using Node.js
 40 | import { Nylas } from '@nylas/nylas-js';
 41 | 
 42 | // Initialize Nylas client
 43 | Nylas.config({
 44 |   clientId: "${placeholderClientId}",
 45 |   clientSecret: "${placeholderClientSecret}",
 46 | });
 47 | 
 48 | // Generate OAuth URL to redirect the user to
 49 | const authUrl = Nylas.urlForAuthentication({
 50 |   redirectURI: "${placeholderRedirectUri}",
 51 |   scopes: ${JSON.stringify(placeholderScopes)},
 52 | });
 53 | 
 54 | console.log("Redirect the user to:", authUrl);
 55 | 
 56 | // After the user is redirected back to your redirect URI:
 57 | // Exchange the authorization code for an access token
 58 | async function exchangeCodeForToken(code) {
 59 |   try {
 60 |     const tokenData = await Nylas.exchangeCodeForToken(code);
 61 |     console.log("Access token:", tokenData.accessToken);
 62 |     console.log("Grant ID:", tokenData.grantId);
 63 |     
 64 |     // Now you can use this token to make API calls
 65 |     return tokenData;
 66 |   } catch (error) {
 67 |     console.error("Error exchanging code for token:", error);
 68 |   }
 69 | }
 70 | 
 71 | // Call this function with the code from the URL parameter
 72 | // exchangeCodeForToken(codeFromUrl);
 73 | `,
 74 | 
 75 |         "Python": `
 76 | # Authentication with Nylas API using Python
 77 | from nylas import Client
 78 | import os
 79 | 
 80 | # Initialize Nylas client
 81 | nylas = Client(
 82 |     client_id="${placeholderClientId}",
 83 |     client_secret="${placeholderClientSecret}"
 84 | )
 85 | 
 86 | # Generate OAuth URL to redirect the user to
 87 | auth_url = nylas.authentication_url(
 88 |     redirect_uri="${placeholderRedirectUri}",
 89 |     scopes=${placeholderScopes}
 90 | )
 91 | 
 92 | print("Redirect the user to:", auth_url)
 93 | 
 94 | # After the user is redirected back to your redirect URI:
 95 | # Exchange the authorization code for an access token
 96 | def exchange_code_for_token(code):
 97 |     try:
 98 |         token_data = nylas.exchange_code_for_token(code)
 99 |         print("Access token:", token_data['access_token'])
100 |         print("Grant ID:", token_data['grant_id'])
101 |         
102 |         # Now you can use this token to make API calls
103 |         return token_data
104 |     except Exception as e:
105 |         print("Error exchanging code for token:", e)
106 | 
107 | # Call this function with the code from the URL parameter
108 | # exchange_code_for_token(code_from_url)
109 | `,
110 | 
111 |         "Java": `
112 | // Authentication with Nylas API using Java
113 | import com.nylas.NylasClient;
114 | import com.nylas.models.*;
115 | 
116 | public class NylasAuth {
117 |     public static void main(String[] args) {
118 |         // Initialize Nylas client
119 |         NylasClient nylas = new NylasClient.Builder("${placeholderClientId}")
120 |             .clientSecret("${placeholderClientSecret}")
121 |             .build();
122 |             
123 |         // Generate OAuth URL to redirect the user to
124 |         String authUrl = nylas.auth().urlForAuthentication(
125 |             "${placeholderRedirectUri}", 
126 |             ${placeholderScopes.map(scope => '"' + scope + '"').join(", ")}
127 |         );
128 |         
129 |         System.out.println("Redirect the user to: " + authUrl);
130 |         
131 |         // After the user is redirected back to your redirect URI:
132 |         // Exchange the authorization code for an access token
133 |         String code = "CODE_FROM_URL_PARAMETER";
134 |         
135 |         try {
136 |             TokenResponse tokenData = nylas.auth().exchangeCodeForToken(code);
137 |             System.out.println("Access token: " + tokenData.getAccessToken());
138 |             System.out.println("Grant ID: " + tokenData.getGrantId());
139 |             
140 |             // Now you can use this token to make API calls
141 |         } catch (Exception e) {
142 |             System.err.println("Error exchanging code for token: " + e.getMessage());
143 |         }
144 |     }
145 | }
146 | `,
147 | 
148 |         "Ruby": `
149 | # Authentication with Nylas API using Ruby
150 | require 'nylas'
151 | 
152 | # Initialize Nylas client
153 | nylas = Nylas::Client.new(
154 |   client_id: "${placeholderClientId}",
155 |   client_secret: "${placeholderClientSecret}"
156 | )
157 | 
158 | # Generate OAuth URL to redirect the user to
159 | auth_url = nylas.auth.authorize_url(
160 |   redirect_uri: "${placeholderRedirectUri}",
161 |   scopes: ${JSON.stringify(placeholderScopes)}
162 | )
163 | 
164 | puts "Redirect the user to: #{auth_url}"
165 | 
166 | # After the user is redirected back to your redirect URI:
167 | # Exchange the authorization code for an access token
168 | def exchange_code_for_token(code)
169 |   begin
170 |     token_data = nylas.auth.exchange_code_for_token(code)
171 |     puts "Access token: #{token_data.access_token}"
172 |     puts "Grant ID: #{token_data.grant_id}"
173 |     
174 |     # Now you can use this token to make API calls
175 |     return token_data
176 |   rescue => e
177 |     puts "Error exchanging code for token: #{e.message}"
178 |   end
179 | end
180 | 
181 | # Call this function with the code from the URL parameter
182 | # exchange_code_for_token(code_from_url)
183 | `,
184 | 
185 |         "curl": `
186 | # Authentication with Nylas API using curl
187 | 
188 | # Step 1: Generate an authorization URL (typically done in your backend)
189 | # Users will be redirected to this URL to authorize your application
190 | 
191 | # Step 2: After authorization, the user is redirected to your redirect URI with a code
192 | # For example: ${placeholderRedirectUri}?code=AUTHORIZATION_CODE
193 | 
194 | # Step 3: Exchange the authorization code for an access token
195 | curl --request POST \\
196 |   --url "https://api.us.nylas.com/v3/connect/oauth/token" \\
197 |   --header "Content-Type: application/json" \\
198 |   --data '{
199 |     "client_id": "${placeholderClientId}",
200 |     "client_secret": "${placeholderClientSecret}",
201 |     "grant_type": "authorization_code",
202 |     "code": "AUTHORIZATION_CODE_FROM_REDIRECT",
203 |     "redirect_uri": "${placeholderRedirectUri}"
204 |   }'
205 | 
206 | # Response will contain access_token, refresh_token, grant_id, etc.
207 | 
208 | # Step 4: Use the access token to make API calls
209 | curl --request GET \\
210 |   --url "https://api.us.nylas.com/v3/grants/GRANT_ID/messages?limit=10" \\
211 |   --header "Content-Type: application/json" \\
212 |   --header "Authorization: Bearer ACCESS_TOKEN"
213 | `
214 |       };
215 |       
216 |       // Get the template for the requested language, or provide an error message
217 |       const template = templates[normalizedLanguage] || 
218 |         `Code generation is not available for ${language}. Available languages are: Node.js, Python, Java, Ruby, and curl.`;
219 |       
220 |       return {
221 |         content: [
222 |           {
223 |             type: "text",
224 |             text: template
225 |           }
226 |         ]
227 |       };
228 |     }
229 |   );
230 |   
231 |   // Tool to generate code for a specific API endpoint
232 |   server.tool(
233 |     "generate-endpoint-code",
234 |     {
235 |       language: z.enum(["node", "python", "java", "ruby", "curl"]),
236 |       endpoint: z.string(),
237 |       method: z.enum(["GET", "POST", "PUT", "DELETE"]).optional(),
238 |       params: z.record(z.any()).optional()
239 |     },
240 |     async ({ language, endpoint, method = "GET", params = {} }) => {
241 |       const normalizedLanguage = normalizeLanguage(language);
242 |       const endpointPath = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
243 |       
244 |       // Construct the endpoint with path parameters
245 |       let formattedEndpoint = endpointPath;
246 |       
247 |       // Replace path parameters with values from params
248 |       Object.keys(params).forEach(key => {
249 |         if (formattedEndpoint.includes(`{${key}}`)) {
250 |           formattedEndpoint = formattedEndpoint.replace(`{${key}}`, params[key]);
251 |           delete params[key]; // Remove used path parameters
252 |         }
253 |       });
254 |       
255 |       // Map of languages to their API code templates
256 |       const templates: Record<string, string> = {
257 |         "Node": `
258 | // ${method} ${endpointPath} using Nylas Node.js SDK
259 | import 'dotenv/config';
260 | import Nylas from '@nylas/nylas-js';
261 | 
262 | // Initialize the Nylas client
263 | const nylas = new Nylas({
264 |   apiKey: process.env.NYLAS_API_KEY
265 | });
266 | 
267 | async function callNylasApi() {
268 |   try {
269 |     ${generateNodeCode(method, formattedEndpoint, params)}
270 |     
271 |     console.log(response);
272 |     return response;
273 |   } catch (error) {
274 |     console.error('Error calling Nylas API:', error);
275 |   }
276 | }
277 | 
278 | callNylasApi();
279 | `,
280 | 
281 |         "Python": `
282 | # ${method} ${endpointPath} using Nylas Python SDK
283 | from dotenv import load_dotenv
284 | load_dotenv()
285 | 
286 | import os
287 | from nylas import Client
288 | 
289 | # Initialize the Nylas client
290 | nylas = Client(
291 |     api_key=os.environ.get('NYLAS_API_KEY')
292 | )
293 | 
294 | ${generatePythonCode(method, formattedEndpoint, params)}
295 | 
296 | print(response)
297 | `,
298 | 
299 |         "Java": `
300 | // ${method} ${endpointPath} using Nylas Java SDK
301 | import com.nylas.NylasClient;
302 | import com.nylas.models.*;
303 | 
304 | public class NylasApiExample {
305 |     public static void main(String[] args) {
306 |         try {
307 |             // Initialize the Nylas client
308 |             NylasClient nylas = new NylasClient.Builder(System.getenv("NYLAS_API_KEY")).build();
309 |             
310 |             ${generateJavaCode(method, formattedEndpoint, params)}
311 |             
312 |             System.out.println(response);
313 |         } catch (Exception e) {
314 |             System.err.println("Error calling Nylas API: " + e.getMessage());
315 |         }
316 |     }
317 | }
318 | `,
319 | 
320 |         "Ruby": `
321 | # ${method} ${endpointPath} using Nylas Ruby SDK
322 | require 'nylas'
323 | require 'dotenv/load'
324 | 
325 | # Initialize the Nylas client
326 | nylas = Nylas::Client.new(
327 |   api_key: ENV['NYLAS_API_KEY']
328 | )
329 | 
330 | ${generateRubyCode(method, formattedEndpoint, params)}
331 | 
332 | puts response
333 | `,
334 | 
335 |         "curl": `
336 | # ${method} ${endpointPath} using curl
337 | ${generateCurlCode(method, formattedEndpoint, params)}
338 | `
339 |       };
340 |       
341 |       // Get the template for the requested language, or provide an error message
342 |       const template = templates[normalizedLanguage] || 
343 |         `Code generation is not available for ${language}. Available languages are: Node.js, Python, Java, Ruby, and curl.`;
344 |       
345 |       return {
346 |         content: [
347 |           {
348 |             type: "text",
349 |             text: template
350 |           }
351 |         ]
352 |       };
353 |     }
354 |   );
355 | }
356 | 
357 | /**
358 |  * Register API explorer tools
359 |  */
360 | function registerApiExplorerTools(server: McpServer) {
361 |   // Tool to search the Nylas API documentation
362 |   server.tool(
363 |     "search-api-docs",
364 |     {
365 |       query: z.string(),
366 |       category: z.enum(["email", "calendar", "contacts", "auth", "webhooks"]).optional()
367 |     },
368 |     async ({ query, category }) => {
369 |       // Normalize the query for search
370 |       const normalizedQuery = query.toLowerCase();
371 |       
372 |       // Define search result templates
373 |       const searchResults: Record<string, string[]> = {
374 |         "email": [
375 |           `### Messages API
376 | The Messages API allows you to read, send, and search email messages.
377 | Key endpoints:
378 | - GET /v3/grants/{grant_id}/messages - List messages
379 | - GET /v3/grants/{grant_id}/messages/{message_id} - Get a specific message
380 | - POST /v3/grants/{grant_id}/messages - Send a message`,
381 |           
382 |           `### Threads API
383 | The Threads API allows you to manage email conversations.
384 | Key endpoints:
385 | - GET /v3/grants/{grant_id}/threads - List threads
386 | - GET /v3/grants/{grant_id}/threads/{thread_id} - Get a specific thread`,
387 |           
388 |           `### Drafts API
389 | The Drafts API allows you to create and manage email drafts.
390 | Key endpoints:
391 | - GET /v3/grants/{grant_id}/drafts - List drafts
392 | - POST /v3/grants/{grant_id}/drafts - Create a draft
393 | - POST /v3/grants/{grant_id}/drafts/{draft_id}/send - Send a draft`
394 |         ],
395 |         
396 |         "calendar": [
397 |           `### Calendars API
398 | The Calendars API allows you to manage calendar containers.
399 | Key endpoints:
400 | - GET /v3/grants/{grant_id}/calendars - List calendars
401 | - GET /v3/grants/{grant_id}/calendars/{calendar_id} - Get a specific calendar`,
402 |           
403 |           `### Events API
404 | The Events API allows you to create and manage calendar events.
405 | Key endpoints:
406 | - GET /v3/grants/{grant_id}/events - List events
407 | - POST /v3/grants/{grant_id}/events - Create an event
408 | - PUT /v3/grants/{grant_id}/events/{event_id} - Update an event`,
409 |           
410 |           `### Availability API
411 | The Availability API helps find available time slots.
412 | Key endpoints:
413 | - POST /v3/grants/{grant_id}/calendars/availability - Find available time slots`
414 |         ],
415 |         
416 |         "contacts": [
417 |           `### Contacts API
418 | The Contacts API allows you to manage contact information.
419 | Key endpoints:
420 | - GET /v3/grants/{grant_id}/contacts - List contacts
421 | - GET /v3/grants/{grant_id}/contacts/{contact_id} - Get a specific contact
422 | - POST /v3/grants/{grant_id}/contacts - Create a contact`
423 |         ],
424 |         
425 |         "auth": [
426 |           `### Authentication API
427 | The Authentication API handles OAuth flows.
428 | Key endpoints:
429 | - GET /v3/connect/oauth/authorize - Start OAuth flow
430 | - POST /v3/connect/oauth/token - Exchange code for token or refresh token`,
431 |           
432 |           `### Grants API
433 | The Grants API manages connected accounts.
434 | Key endpoints:
435 | - GET /v3/applications/{application_id}/grants - List connected accounts
436 | - GET /v3/applications/{application_id}/grants/{grant_id} - Get a specific connected account`
437 |         ],
438 |         
439 |         "webhooks": [
440 |           `### Webhooks API
441 | The Webhooks API allows setting up real-time notifications.
442 | Key endpoints:
443 | - GET /v3/applications/{application_id}/webhooks - List webhooks
444 | - POST /v3/applications/{application_id}/webhooks - Create a webhook
445 | - DELETE /v3/applications/{application_id}/webhooks/{webhook_id} - Delete a webhook`
446 |         ]
447 |       };
448 |       
449 |       // If a category is specified, search only in that category
450 |       if (category) {
451 |         const categoryResults = searchResults[category] || [];
452 |         const matches = categoryResults.filter(result => 
453 |           result.toLowerCase().includes(normalizedQuery)
454 |         );
455 |         
456 |         if (matches.length > 0) {
457 |           return {
458 |             content: [
459 |               {
460 |                 type: "text",
461 |                 text: `# Search results for "${query}" in ${category} API\n\n${matches.join('\n\n')}`
462 |               }
463 |             ]
464 |           };
465 |         } else {
466 |           return {
467 |             content: [
468 |               {
469 |                 type: "text",
470 |                 text: `No results found for "${query}" in the ${category} API. Try a different search term or category.`
471 |               }
472 |             ]
473 |           };
474 |         }
475 |       }
476 |       
477 |       // If no category is specified, search in all categories
478 |       const allResults: string[] = [];
479 |       
480 |       Object.entries(searchResults).forEach(([category, results]) => {
481 |         const categoryMatches = results.filter(result => 
482 |           result.toLowerCase().includes(normalizedQuery)
483 |         );
484 |         
485 |         if (categoryMatches.length > 0) {
486 |           allResults.push(`## ${category.charAt(0).toUpperCase() + category.slice(1)} API\n\n${categoryMatches.join('\n\n')}`);
487 |         }
488 |       });
489 |       
490 |       if (allResults.length > 0) {
491 |         return {
492 |           content: [
493 |             {
494 |               type: "text",
495 |               text: `# Search results for "${query}"\n\n${allResults.join('\n\n')}`
496 |             }
497 |           ]
498 |         };
499 |       } else {
500 |         return {
501 |           content: [
502 |             {
503 |               type: "text",
504 |               text: `No results found for "${query}". Try a different search term.`
505 |             }
506 |           ]
507 |         };
508 |       }
509 |     }
510 |   );
511 | }
512 | 
513 | /**
514 |  * Normalize language names for code generation
515 |  */
516 | function normalizeLanguage(language: string): string {
517 |   const langMap: Record<string, string> = {
518 |     'node': 'Node',
519 |     'nodejs': 'Node',
520 |     'javascript': 'Node',
521 |     'js': 'Node',
522 |     'python': 'Python',
523 |     'py': 'Python',
524 |     'java': 'Java',
525 |     'ruby': 'Ruby',
526 |     'rb': 'Ruby',
527 |     'curl': 'curl',
528 |     'api': 'curl',
529 |     'rest': 'curl'
530 |   };
531 |   
532 |   return langMap[language.toLowerCase()] || language;
533 | }
534 | 
535 | /**
536 |  * Generate Node.js code for the API endpoint
537 |  */
538 | function generateNodeCode(method: string, endpoint: string, params: Record<string, any>): string {
539 |   const parts = endpoint.split('/');
540 |   let resourceType = '';
541 |   let functionName = '';
542 |   let grantId = 'process.env.NYLAS_GRANT_ID';
543 |   let resourceId = '';
544 |   
545 |   // Try to determine the resource type and function name
546 |   if (parts.length >= 3) {
547 |     if (parts[1] === 'v3' && parts[2] === 'grants') {
548 |       if (parts.length >= 5) {
549 |         resourceType = parts[4]; // like 'messages', 'events', etc.
550 |         
551 |         if (parts.length >= 6) {
552 |           resourceId = parts[5];
553 |           
554 |           if (parts.length >= 7 && parts[6] === 'send') {
555 |             functionName = 'send';
556 |           }
557 |         }
558 |       }
559 |     }
560 |   }
561 |   
562 |   // Handle different HTTP methods
563 |   switch (method) {
564 |     case 'GET':
565 |       if (resourceId) {
566 |         // Get a specific resource
567 |         return `const response = await nylas.${resourceType}.find({
568 |       identifier: ${grantId},
569 |       ${resourceType.slice(0, -1)}Id: "${resourceId}",
570 |       ${Object.entries(params).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(',\n      ')}
571 |     });`;
572 |       } else {
573 |         // List resources
574 |         return `const response = await nylas.${resourceType}.list({
575 |       identifier: ${grantId},
576 |       ${Object.keys(params).length > 0 ? `queryParams: {
577 |         ${Object.entries(params).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(',\n        ')}
578 |       }` : ''}
579 |     });`;
580 |       }
581 |     
582 |     case 'POST':
583 |       if (functionName === 'send') {
584 |         // Send a draft
585 |         return `const response = await nylas.${resourceType}.send({
586 |       identifier: ${grantId},
587 |       ${resourceType.slice(0, -1)}Id: "${resourceId}"
588 |     });`;
589 |       } else {
590 |         // Create a resource
591 |         return `const response = await nylas.${resourceType}.create({
592 |       identifier: ${grantId},
593 |       ${Object.entries(params).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(',\n      ')}
594 |     });`;
595 |       }
596 |     
597 |     case 'PUT':
598 |       // Update a resource
599 |       return `const response = await nylas.${resourceType}.update({
600 |       identifier: ${grantId},
601 |       ${resourceType.slice(0, -1)}Id: "${resourceId}",
602 |       ${Object.entries(params).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(',\n      ')}
603 |     });`;
604 |     
605 |     case 'DELETE':
606 |       // Delete a resource
607 |       return `const response = await nylas.${resourceType}.destroy({
608 |       identifier: ${grantId},
609 |       ${resourceType.slice(0, -1)}Id: "${resourceId}"
610 |     });`;
611 |     
612 |     default:
613 |       return `// No code generation available for this endpoint
614 | const response = "Please refer to the Nylas API documentation for this endpoint.";`;
615 |   }
616 | }
617 | 
618 | /**
619 |  * Generate Python code for the API endpoint
620 |  */
621 | function generatePythonCode(method: string, endpoint: string, params: Record<string, any>): string {
622 |   const parts = endpoint.split('/');
623 |   let resourceType = '';
624 |   let functionName = '';
625 |   let grantId = 'os.environ.get("NYLAS_GRANT_ID")';
626 |   let resourceId = '';
627 |   
628 |   // Try to determine the resource type and function name
629 |   if (parts.length >= 3) {
630 |     if (parts[1] === 'v3' && parts[2] === 'grants') {
631 |       if (parts.length >= 5) {
632 |         resourceType = parts[4]; // like 'messages', 'events', etc.
633 |         
634 |         if (parts.length >= 6) {
635 |           resourceId = parts[5];
636 |           
637 |           if (parts.length >= 7 && parts[6] === 'send') {
638 |             functionName = 'send';
639 |           }
640 |         }
641 |       }
642 |     }
643 |   }
644 |   
645 |   // Handle different HTTP methods
646 |   switch (method) {
647 |     case 'GET':
648 |       if (resourceId) {
649 |         // Get a specific resource
650 |         return `# Get a specific ${resourceType.slice(0, -1)}
651 | response = nylas.${resourceType}.find(
652 |     ${grantId},
653 |     "${resourceId}"${Object.keys(params).length > 0 ? `,
654 |     query_params={
655 |         ${Object.entries(params).map(([key, value]) => `"${key}": ${JSON.stringify(value)}`).join(',\n        ')}
656 |     }` : ''}
657 | )`;
658 |       } else {
659 |         // List resources
660 |         return `# List ${resourceType}
661 | response = nylas.${resourceType}.list(
662 |     ${grantId}${Object.keys(params).length > 0 ? `,
663 |     query_params={
664 |         ${Object.entries(params).map(([key, value]) => `"${key}": ${JSON.stringify(value)}`).join(',\n        ')}
665 |     }` : ''}
666 | )`;
667 |       }
668 |     
669 |     case 'POST':
670 |       if (functionName === 'send') {
671 |         // Send a draft
672 |         return `# Send a draft
673 | response = nylas.${resourceType}.send(
674 |     ${grantId},
675 |     "${resourceId}"
676 | )`;
677 |       } else {
678 |         // Create a resource
679 |         return `# Create a new ${resourceType.slice(0, -1)}
680 | response = nylas.${resourceType}.create(
681 |     ${grantId},
682 |     {
683 |         ${Object.entries(params).map(([key, value]) => `"${key}": ${JSON.stringify(value)}`).join(',\n        ')}
684 |     }
685 | )`;
686 |       }
687 |     
688 |     case 'PUT':
689 |       // Update a resource
690 |       return `# Update a ${resourceType.slice(0, -1)}
691 | response = nylas.${resourceType}.update(
692 |     ${grantId},
693 |     "${resourceId}",
694 |     {
695 |         ${Object.entries(params).map(([key, value]) => `"${key}": ${JSON.stringify(value)}`).join(',\n        ')}
696 |     }
697 | )`;
698 |     
699 |     case 'DELETE':
700 |       // Delete a resource
701 |       return `# Delete a ${resourceType.slice(0, -1)}
702 | response = nylas.${resourceType}.destroy(
703 |     ${grantId},
704 |     "${resourceId}"
705 | )`;
706 |     
707 |     default:
708 |       return `# No code generation available for this endpoint
709 | response = "Please refer to the Nylas API documentation for this endpoint."`;
710 |   }
711 | }
712 | 
713 | /**
714 |  * Generate Java code for the API endpoint
715 |  */
716 | function generateJavaCode(method: string, endpoint: string, params: Record<string, any>): string {
717 |   const parts = endpoint.split('/');
718 |   let resourceType = '';
719 |   let functionName = '';
720 |   let grantId = 'System.getenv("NYLAS_GRANT_ID")';
721 |   let resourceId = '';
722 |   
723 |   // Try to determine the resource type and function name
724 |   if (parts.length >= 3) {
725 |     if (parts[1] === 'v3' && parts[2] === 'grants') {
726 |       if (parts.length >= 5) {
727 |         resourceType = parts[4]; // like 'messages', 'events', etc.
728 |         resourceType = resourceType.charAt(0).toUpperCase() + resourceType.slice(1);
729 |         
730 |         if (parts.length >= 6) {
731 |           resourceId = parts[5];
732 |           
733 |           if (parts.length >= 7 && parts[6] === 'send') {
734 |             functionName = 'send';
735 |           }
736 |         }
737 |       }
738 |     }
739 |   }
740 |   
741 |   // Handle different HTTP methods
742 |   switch (method) {
743 |     case 'GET':
744 |       if (resourceId) {
745 |         // Get a specific resource
746 |         return `// Get a specific ${resourceType.toLowerCase().slice(0, -1)}
747 | Response<${resourceType.slice(0, -1)}> response = nylas.${resourceType.toLowerCase()}().find(${grantId}, "${resourceId}");`;
748 |       } else {
749 |         // List resources
750 |         if (Object.keys(params).length > 0) {
751 |           return `// List ${resourceType.toLowerCase()} with query parameters
752 | QueryParams queryParams = new QueryParams();
753 | ${Object.entries(params).map(([key, value]) => `queryParams.put("${key}", ${JSON.stringify(value)});`).join('\n')}
754 | 
755 | ListResponse<${resourceType.slice(0, -1)}> response = nylas.${resourceType.toLowerCase()}().list(${grantId}, queryParams);`;
756 |         } else {
757 |           return `// List ${resourceType.toLowerCase()}
758 | ListResponse<${resourceType.slice(0, -1)}> response = nylas.${resourceType.toLowerCase()}().list(${grantId});`;
759 |         }
760 |       }
761 |     
762 |     case 'POST':
763 |       if (functionName === 'send') {
764 |         // Send a draft
765 |         return `// Send a draft
766 | Response<Message> response = nylas.${resourceType.toLowerCase()}().send(${grantId}, "${resourceId}");`;
767 |       } else {
768 |         // Create a resource
769 |         return `// Create a new ${resourceType.toLowerCase().slice(0, -1)}
770 | ${resourceType.slice(0, -1)} new${resourceType.slice(0, -1)} = new ${resourceType.slice(0, -1)}.Builder()
771 |     ${Object.entries(params).map(([key, value]) => {
772 |       // Convert camelCase to method name (e.g., startTime -> startTime())
773 |       const methodName = key.charAt(0).toLowerCase() + key.slice(1);
774 |       return `    .${methodName}(${JSON.stringify(value)})`;
775 |     }).join('\n')}
776 |     .build();
777 | 
778 | Response<${resourceType.slice(0, -1)}> response = nylas.${resourceType.toLowerCase()}().create(${grantId}, new${resourceType.slice(0, -1)});`;
779 |       }
780 |     
781 |     case 'PUT':
782 |       // Update a resource
783 |       return `// Update a ${resourceType.toLowerCase().slice(0, -1)}
784 | ${resourceType.slice(0, -1)} updated${resourceType.slice(0, -1)} = new ${resourceType.slice(0, -1)}.Builder()
785 |     ${Object.entries(params).map(([key, value]) => {
786 |       // Convert camelCase to method name (e.g., startTime -> startTime())
787 |       const methodName = key.charAt(0).toLowerCase() + key.slice(1);
788 |       return `    .${methodName}(${JSON.stringify(value)})`;
789 |     }).join('\n')}
790 |     .build();
791 | 
792 | Response<${resourceType.slice(0, -1)}> response = nylas.${resourceType.toLowerCase()}().update(${grantId}, "${resourceId}", updated${resourceType.slice(0, -1)});`;
793 |     
794 |     case 'DELETE':
795 |       // Delete a resource
796 |       return `// Delete a ${resourceType.toLowerCase().slice(0, -1)}
797 | Response<Void> response = nylas.${resourceType.toLowerCase()}().destroy(${grantId}, "${resourceId}");`;
798 |     
799 |     default:
800 |       return `// No code generation available for this endpoint
801 | String response = "Please refer to the Nylas API documentation for this endpoint.";`;
802 |   }
803 | }
804 | 
805 | /**
806 |  * Generate Ruby code for the API endpoint
807 |  */
808 | function generateRubyCode(method: string, endpoint: string, params: Record<string, any>): string {
809 |   const parts = endpoint.split('/');
810 |   let resourceType = '';
811 |   let functionName = '';
812 |   let grantId = 'ENV["NYLAS_GRANT_ID"]';
813 |   let resourceId = '';
814 |   
815 |   // Try to determine the resource type and function name
816 |   if (parts.length >= 3) {
817 |     if (parts[1] === 'v3' && parts[2] === 'grants') {
818 |       if (parts.length >= 5) {
819 |         resourceType = parts[4]; // like 'messages', 'events', etc.
820 |         
821 |         if (parts.length >= 6) {
822 |           resourceId = parts[5];
823 |           
824 |           if (parts.length >= 7 && parts[6] === 'send') {
825 |             functionName = 'send';
826 |           }
827 |         }
828 |       }
829 |     }
830 |   }
831 |   
832 |   // Handle different HTTP methods
833 |   switch (method) {
834 |     case 'GET':
835 |       if (resourceId) {
836 |         // Get a specific resource
837 |         return `# Get a specific ${resourceType.slice(0, -1)}
838 | response, _ = nylas.${resourceType}.find(
839 |   identifier: ${grantId}, 
840 |   ${resourceType.slice(0, -1)}_id: "${resourceId}"${Object.keys(params).length > 0 ? `,
841 |   query_params: {
842 |     ${Object.entries(params).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(',\n    ')}
843 |   }` : ''}
844 | )`;
845 |       } else {
846 |         // List resources
847 |         return `# List ${resourceType}
848 | response, _ = nylas.${resourceType}.list(
849 |   identifier: ${grantId}${Object.keys(params).length > 0 ? `,
850 |   query_params: {
851 |     ${Object.entries(params).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(',\n    ')}
852 |   }` : ''}
853 | )`;
854 |       }
855 |     
856 |     case 'POST':
857 |       if (functionName === 'send') {
858 |         // Send a draft
859 |         return `# Send a draft
860 | response, _ = nylas.${resourceType}.send(
861 |   identifier: ${grantId}, 
862 |   ${resourceType.slice(0, -1)}_id: "${resourceId}"
863 | )`;
864 |       } else {
865 |         // Create a resource
866 |         return `# Create a new ${resourceType.slice(0, -1)}
867 | response, _ = nylas.${resourceType}.create(
868 |   identifier: ${grantId}, 
869 |   request_body: {
870 |     ${Object.entries(params).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(',\n    ')}
871 |   }
872 | )`;
873 |       }
874 |     
875 |     case 'PUT':
876 |       // Update a resource
877 |       return `# Update a ${resourceType.slice(0, -1)}
878 | response, _ = nylas.${resourceType}.update(
879 |   identifier: ${grantId}, 
880 |   ${resourceType.slice(0, -1)}_id: "${resourceId}", 
881 |   request_body: {
882 |     ${Object.entries(params).map(([key, value]) => `${key}: ${JSON.stringify(value)}`).join(',\n    ')}
883 |   }
884 | )`;
885 |     
886 |     case 'DELETE':
887 |       // Delete a resource
888 |       return `# Delete a ${resourceType.slice(0, -1)}
889 | response, _ = nylas.${resourceType}.destroy(
890 |   identifier: ${grantId}, 
891 |   ${resourceType.slice(0, -1)}_id: "${resourceId}"
892 | )`;
893 |     
894 |     default:
895 |       return `# No code generation available for this endpoint
896 | response = "Please refer to the Nylas API documentation for this endpoint."`;
897 |   }
898 | }
899 | 
900 | /**
901 |  * Generate curl command for the API endpoint
902 |  */
903 | function generateCurlCode(method: string, endpoint: string, params: Record<string, any>): string {
904 |   let baseUrl = "https://api.us.nylas.com";
905 |   const fullUrl = `${baseUrl}${endpoint}`;
906 |   
907 |   // Handle different HTTP methods
908 |   switch (method) {
909 |     case 'GET':
910 |       // Add query parameters if any
911 |       if (Object.keys(params).length > 0) {
912 |         const queryParams = Object.entries(params)
913 |           .map(([key, value]) => `${key}=${encodeURIComponent(JSON.stringify(value))}`)
914 |           .join('&');
915 |         
916 |         return `curl --request GET \\
917 |   --url "${fullUrl}?${queryParams}" \\
918 |   --header "Content-Type: application/json" \\
919 |   --header "Authorization: Bearer $NYLAS_API_KEY"`;
920 |       } else {
921 |         return `curl --request GET \\
922 |   --url "${fullUrl}" \\
923 |   --header "Content-Type: application/json" \\
924 |   --header "Authorization: Bearer $NYLAS_API_KEY"`;
925 |       }
926 |     
927 |     case 'POST':
928 |       // Include request body
929 |       return `curl --request POST \\
930 |   --url "${fullUrl}" \\
931 |   --header "Content-Type: application/json" \\
932 |   --header "Authorization: Bearer $NYLAS_API_KEY" \\
933 |   --data '${JSON.stringify(params, null, 2)}'`;
934 |     
935 |     case 'PUT':
936 |       // Include request body
937 |       return `curl --request PUT \\
938 |   --url "${fullUrl}" \\
939 |   --header "Content-Type: application/json" \\
940 |   --header "Authorization: Bearer $NYLAS_API_KEY" \\
941 |   --data '${JSON.stringify(params, null, 2)}'`;
942 |     
943 |     case 'DELETE':
944 |       return `curl --request DELETE \\
945 |   --url "${fullUrl}" \\
946 |   --header "Content-Type: application/json" \\
947 |   --header "Authorization: Bearer $NYLAS_API_KEY"`;
948 |     
949 |     default:
950 |       return `# No code generation available for this endpoint
951 | # Please refer to the Nylas API documentation`;
952 |   }
953 | }
```
Page 3/3FirstPrevNextLast