├── .gitignore ├── .npmignore ├── Dockerfile ├── LICENSE ├── README.md ├── docker-compose.yml ├── llms-install.md ├── mcp-config.json ├── package-lock.json ├── package.json ├── setup.js ├── smithery.yaml ├── src ├── evals │ └── evals.ts ├── index.ts ├── label-manager.ts └── utl.ts └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | npm-debug.log* 4 | yarn-debug.log* 5 | yarn-error.log* 6 | 7 | # Build 8 | build/ 9 | dist/ 10 | *.tsbuildinfo 11 | 12 | # Environment 13 | .env 14 | .env.local 15 | .env.*.local 16 | 17 | # IDE 18 | .idea/ 19 | .vscode/ 20 | *.swp 21 | *.swo 22 | 23 | # OS 24 | .DS_Store 25 | Thumbs.db 26 | 27 | # Project specific 28 | gcp-oauth.keys.json 29 | .calendar-mcp/ 30 | credentials.json 31 | .calendar-server-credentials.json -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Source 2 | src/ 3 | 4 | # Development 5 | .git/ 6 | .github/ 7 | .gitignore 8 | .npmrc 9 | .env 10 | .env.* 11 | 12 | # IDE 13 | .vscode/ 14 | .idea/ 15 | *.swp 16 | *.swo 17 | 18 | # Logs 19 | logs/ 20 | *.log 21 | npm-debug.log* 22 | 23 | # Dependencies 24 | node_modules/ 25 | 26 | # Build process 27 | tsconfig.json 28 | .eslintrc 29 | .prettierrc 30 | 31 | # Tests 32 | test/ 33 | coverage/ 34 | .nyc_output/ 35 | 36 | # Misc 37 | .DS_Store 38 | Thumbs.db -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:20-slim 2 | 3 | WORKDIR /app 4 | 5 | # Copy package files 6 | COPY package.json package-lock.json* ./ 7 | 8 | # Install dependencies 9 | RUN npm ci 10 | 11 | # Copy source files 12 | COPY tsconfig.json ./ 13 | COPY src ./src 14 | 15 | # Build the application 16 | RUN npm run build 17 | 18 | # Create directory for credentials 19 | RUN mkdir -p /gmail-server 20 | 21 | # Set environment variables 22 | ENV NODE_ENV=production 23 | 24 | # Expose port for OAuth flow 25 | EXPOSE 3000 26 | 27 | # Set entrypoint command 28 | ENTRYPOINT ["node", "dist/index.js"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 GongRzhe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gmail AutoAuth MCP Server 2 | 3 | A Model Context Protocol (MCP) server for Gmail integration in Claude Desktop with auto authentication support. This server enables AI assistants to manage Gmail through natural language interactions. 4 | 5 | ![](https://badge.mcpx.dev?type=server 'MCP Server') 6 | [![smithery badge](https://smithery.ai/badge/@gongrzhe/server-gmail-autoauth-mcp)](https://smithery.ai/server/@gongrzhe/server-gmail-autoauth-mcp) 7 | 8 | 9 | ## Features 10 | 11 | - Send emails with subject, content, attachments, and recipients 12 | - Support for HTML emails and multipart messages with both HTML and plain text versions 13 | - Full support for international characters in subject lines and email content 14 | - Read email messages by ID with advanced MIME structure handling 15 | - View email attachments information (filenames, types, sizes) 16 | - Search emails with various criteria (subject, sender, date range) 17 | - **Comprehensive label management with ability to create, update, delete and list labels** 18 | - List all available Gmail labels (system and user-defined) 19 | - List emails in inbox, sent, or custom labels 20 | - Mark emails as read/unread 21 | - Move emails to different labels/folders 22 | - Delete emails 23 | - **Batch operations for efficiently processing multiple emails at once** 24 | - Full integration with Gmail API 25 | - Simple OAuth2 authentication flow with auto browser launch 26 | - Support for both Desktop and Web application credentials 27 | - Global credential storage for convenience 28 | 29 | ## Installation & Authentication 30 | 31 | ### Installing via Smithery 32 | 33 | To install Gmail AutoAuth for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@gongrzhe/server-gmail-autoauth-mcp): 34 | 35 | ```bash 36 | npx -y @smithery/cli install @gongrzhe/server-gmail-autoauth-mcp --client claude 37 | ``` 38 | 39 | ### Installing Manually 40 | 1. Create a Google Cloud Project and obtain credentials: 41 | 42 | a. Create a Google Cloud Project: 43 | - Go to [Google Cloud Console](https://console.cloud.google.com/) 44 | - Create a new project or select an existing one 45 | - Enable the Gmail API for your project 46 | 47 | b. Create OAuth 2.0 Credentials: 48 | - Go to "APIs & Services" > "Credentials" 49 | - Click "Create Credentials" > "OAuth client ID" 50 | - Choose either "Desktop app" or "Web application" as application type 51 | - Give it a name and click "Create" 52 | - For Web application, add `http://localhost:3000/oauth2callback` to the authorized redirect URIs 53 | - Download the JSON file of your client's OAuth keys 54 | - Rename the key file to `gcp-oauth.keys.json` 55 | 56 | 2. Run Authentication: 57 | 58 | You can authenticate in two ways: 59 | 60 | a. Global Authentication (Recommended): 61 | ```bash 62 | # First time: Place gcp-oauth.keys.json in your home directory's .gmail-mcp folder 63 | mkdir -p ~/.gmail-mcp 64 | mv gcp-oauth.keys.json ~/.gmail-mcp/ 65 | 66 | # Run authentication from anywhere 67 | npx @gongrzhe/server-gmail-autoauth-mcp auth 68 | ``` 69 | 70 | b. Local Authentication: 71 | ```bash 72 | # Place gcp-oauth.keys.json in your current directory 73 | # The file will be automatically copied to global config 74 | npx @gongrzhe/server-gmail-autoauth-mcp auth 75 | ``` 76 | 77 | The authentication process will: 78 | - Look for `gcp-oauth.keys.json` in the current directory or `~/.gmail-mcp/` 79 | - If found in current directory, copy it to `~/.gmail-mcp/` 80 | - Open your default browser for Google authentication 81 | - Save credentials as `~/.gmail-mcp/credentials.json` 82 | 83 | > **Note**: 84 | > - After successful authentication, credentials are stored globally in `~/.gmail-mcp/` and can be used from any directory 85 | > - Both Desktop app and Web application credentials are supported 86 | > - For Web application credentials, make sure to add `http://localhost:3000/oauth2callback` to your authorized redirect URIs 87 | 88 | 3. Configure in Claude Desktop: 89 | 90 | ```json 91 | { 92 | "mcpServers": { 93 | "gmail": { 94 | "command": "npx", 95 | "args": [ 96 | "@gongrzhe/server-gmail-autoauth-mcp" 97 | ] 98 | } 99 | } 100 | } 101 | ``` 102 | 103 | ### Docker Support 104 | 105 | If you prefer using Docker: 106 | 107 | 1. Authentication: 108 | ```bash 109 | docker run -i --rm \ 110 | --mount type=bind,source=/path/to/gcp-oauth.keys.json,target=/gcp-oauth.keys.json \ 111 | -v mcp-gmail:/gmail-server \ 112 | -e GMAIL_OAUTH_PATH=/gcp-oauth.keys.json \ 113 | -e "GMAIL_CREDENTIALS_PATH=/gmail-server/credentials.json" \ 114 | -p 3000:3000 \ 115 | mcp/gmail auth 116 | ``` 117 | 118 | 2. Usage: 119 | ```json 120 | { 121 | "mcpServers": { 122 | "gmail": { 123 | "command": "docker", 124 | "args": [ 125 | "run", 126 | "-i", 127 | "--rm", 128 | "-v", 129 | "mcp-gmail:/gmail-server", 130 | "-e", 131 | "GMAIL_CREDENTIALS_PATH=/gmail-server/credentials.json", 132 | "mcp/gmail" 133 | ] 134 | } 135 | } 136 | } 137 | ``` 138 | 139 | ### Cloud Server Authentication 140 | 141 | For cloud server environments (like n8n), you can specify a custom callback URL during authentication: 142 | 143 | ```bash 144 | npx @gongrzhe/server-gmail-autoauth-mcp auth https://gmail.gongrzhe.com/oauth2callback 145 | ``` 146 | 147 | #### Setup Instructions for Cloud Environment 148 | 149 | 1. **Configure Reverse Proxy:** 150 | - Set up your n8n container to expose a port for authentication 151 | - Configure a reverse proxy to forward traffic from your domain (e.g., `gmail.gongrzhe.com`) to this port 152 | 153 | 2. **DNS Configuration:** 154 | - Add an A record in your DNS settings to resolve your domain to your cloud server's IP address 155 | 156 | 3. **Google Cloud Platform Setup:** 157 | - In your Google Cloud Console, add your custom domain callback URL (e.g., `https://gmail.gongrzhe.com/oauth2callback`) to the authorized redirect URIs list 158 | 159 | 4. **Run Authentication:** 160 | ```bash 161 | npx @gongrzhe/server-gmail-autoauth-mcp auth https://gmail.gongrzhe.com/oauth2callback 162 | ``` 163 | 164 | 5. **Configure in your application:** 165 | ```json 166 | { 167 | "mcpServers": { 168 | "gmail": { 169 | "command": "npx", 170 | "args": [ 171 | "@gongrzhe/server-gmail-autoauth-mcp" 172 | ] 173 | } 174 | } 175 | } 176 | ``` 177 | 178 | This approach allows authentication flows to work properly in environments where localhost isn't accessible, such as containerized applications or cloud servers. 179 | 180 | ## Available Tools 181 | 182 | The server provides the following tools that can be used through Claude Desktop: 183 | 184 | ### 1. Send Email (`send_email`) 185 | 186 | Sends a new email immediately. Supports plain text, HTML, or multipart emails. 187 | 188 | ```json 189 | { 190 | "to": ["recipient@example.com"], 191 | "subject": "Meeting Tomorrow", 192 | "body": "Hi,\n\nJust a reminder about our meeting tomorrow at 10 AM.\n\nBest regards", 193 | "cc": ["cc@example.com"], 194 | "bcc": ["bcc@example.com"], 195 | "mimeType": "text/plain" 196 | } 197 | 198 | ``` 199 | HTML Email Example: 200 | 201 | ```json 202 | { 203 | "to": ["recipient@example.com"], 204 | "subject": "Meeting Tomorrow", 205 | "mimeType": "text/html", 206 | "body": "

Meeting Reminder

Just a reminder about our meeting tomorrow at 10 AM.

Best regards

" 207 | } 208 | ``` 209 | 210 | Multipart Email Example (HTML + Plain Text): 211 | 212 | ```json 213 | { 214 | "to": ["recipient@example.com"], 215 | "subject": "Meeting Tomorrow", 216 | "mimeType": "multipart/alternative", 217 | "body": "Hi,\n\nJust a reminder about our meeting tomorrow at 10 AM.\n\nBest regards", 218 | "htmlBody": "

Meeting Reminder

Just a reminder about our meeting tomorrow at 10 AM.

Best regards

" 219 | } 220 | ``` 221 | 222 | ### 2. Draft Email (`draft_email`) 223 | Creates a draft email without sending it. 224 | 225 | ```json 226 | { 227 | "to": ["recipient@example.com"], 228 | "subject": "Draft Report", 229 | "body": "Here's the draft report for your review.", 230 | "cc": ["manager@example.com"] 231 | } 232 | ``` 233 | 234 | ### 3. Read Email (`read_email`) 235 | Retrieves the content of a specific email by its ID. 236 | 237 | ```json 238 | { 239 | "messageId": "182ab45cd67ef" 240 | } 241 | ``` 242 | 243 | ### 4. Search Emails (`search_emails`) 244 | Searches for emails using Gmail search syntax. 245 | 246 | ```json 247 | { 248 | "query": "from:sender@example.com after:2024/01/01 has:attachment", 249 | "maxResults": 10 250 | } 251 | ``` 252 | 253 | ### 5. Modify Email (`modify_email`) 254 | Adds or removes labels from emails (move to different folders, archive, etc.). 255 | 256 | ```json 257 | { 258 | "messageId": "182ab45cd67ef", 259 | "addLabelIds": ["IMPORTANT"], 260 | "removeLabelIds": ["INBOX"] 261 | } 262 | ``` 263 | 264 | ### 6. Delete Email (`delete_email`) 265 | Permanently deletes an email. 266 | 267 | ```json 268 | { 269 | "messageId": "182ab45cd67ef" 270 | } 271 | ``` 272 | 273 | ### 7. List Email Labels (`list_email_labels`) 274 | Retrieves all available Gmail labels. 275 | 276 | ```json 277 | {} 278 | ``` 279 | 280 | ### 8. Create Label (`create_label`) 281 | Creates a new Gmail label. 282 | 283 | ```json 284 | { 285 | "name": "Important Projects", 286 | "messageListVisibility": "show", 287 | "labelListVisibility": "labelShow" 288 | } 289 | ``` 290 | 291 | ### 9. Update Label (`update_label`) 292 | Updates an existing Gmail label. 293 | 294 | ```json 295 | { 296 | "id": "Label_1234567890", 297 | "name": "Urgent Projects", 298 | "messageListVisibility": "show", 299 | "labelListVisibility": "labelShow" 300 | } 301 | ``` 302 | 303 | ### 10. Delete Label (`delete_label`) 304 | Deletes a Gmail label. 305 | 306 | ```json 307 | { 308 | "id": "Label_1234567890" 309 | } 310 | ``` 311 | 312 | ### 11. Get or Create Label (`get_or_create_label`) 313 | Gets an existing label by name or creates it if it doesn't exist. 314 | 315 | ```json 316 | { 317 | "name": "Project XYZ", 318 | "messageListVisibility": "show", 319 | "labelListVisibility": "labelShow" 320 | } 321 | ``` 322 | 323 | ### 12. Batch Modify Emails (`batch_modify_emails`) 324 | Modifies labels for multiple emails in efficient batches. 325 | 326 | ```json 327 | { 328 | "messageIds": ["182ab45cd67ef", "182ab45cd67eg", "182ab45cd67eh"], 329 | "addLabelIds": ["IMPORTANT"], 330 | "removeLabelIds": ["INBOX"], 331 | "batchSize": 50 332 | } 333 | ``` 334 | 335 | ### 13. Batch Delete Emails (`batch_delete_emails`) 336 | Permanently deletes multiple emails in efficient batches. 337 | 338 | ```json 339 | { 340 | "messageIds": ["182ab45cd67ef", "182ab45cd67eg", "182ab45cd67eh"], 341 | "batchSize": 50 342 | } 343 | ``` 344 | 345 | ## Advanced Search Syntax 346 | 347 | The `search_emails` tool supports Gmail's powerful search operators: 348 | 349 | | Operator | Example | Description | 350 | |----------|---------|-------------| 351 | | `from:` | `from:john@example.com` | Emails from a specific sender | 352 | | `to:` | `to:mary@example.com` | Emails sent to a specific recipient | 353 | | `subject:` | `subject:"meeting notes"` | Emails with specific text in the subject | 354 | | `has:attachment` | `has:attachment` | Emails with attachments | 355 | | `after:` | `after:2024/01/01` | Emails received after a date | 356 | | `before:` | `before:2024/02/01` | Emails received before a date | 357 | | `is:` | `is:unread` | Emails with a specific state | 358 | | `label:` | `label:work` | Emails with a specific label | 359 | 360 | You can combine multiple operators: `from:john@example.com after:2024/01/01 has:attachment` 361 | 362 | ## Advanced Features 363 | 364 | ### Email Content Extraction 365 | 366 | The server intelligently extracts email content from complex MIME structures: 367 | 368 | - Prioritizes plain text content when available 369 | - Falls back to HTML content if plain text is not available 370 | - Handles multi-part MIME messages with nested parts 371 | - Processes attachments information (filename, type, size) 372 | - Preserves original email headers (From, To, Subject, Date) 373 | 374 | ### International Character Support 375 | 376 | The server fully supports non-ASCII characters in email subjects and content, including: 377 | - Turkish, Chinese, Japanese, Korean, and other non-Latin alphabets 378 | - Special characters and symbols 379 | - Proper encoding ensures correct display in email clients 380 | 381 | ### Comprehensive Label Management 382 | 383 | The server provides a complete set of tools for managing Gmail labels: 384 | 385 | - **Create Labels**: Create new labels with customizable visibility settings 386 | - **Update Labels**: Rename labels or change their visibility settings 387 | - **Delete Labels**: Remove user-created labels (system labels are protected) 388 | - **Find or Create**: Get a label by name or automatically create it if not found 389 | - **List All Labels**: View all system and user labels with detailed information 390 | - **Label Visibility Options**: Control how labels appear in message and label lists 391 | 392 | Label visibility settings include: 393 | - `messageListVisibility`: Controls whether the label appears in the message list (`show` or `hide`) 394 | - `labelListVisibility`: Controls how the label appears in the label list (`labelShow`, `labelShowIfUnread`, or `labelHide`) 395 | 396 | These label management features enable sophisticated organization of emails directly through Claude, without needing to switch to the Gmail interface. 397 | 398 | ### Batch Operations 399 | 400 | The server includes efficient batch processing capabilities: 401 | 402 | - Process up to 50 emails at once (configurable batch size) 403 | - Automatic chunking of large email sets to avoid API limits 404 | - Detailed success/failure reporting for each operation 405 | - Graceful error handling with individual retries 406 | - Perfect for bulk inbox management and organization tasks 407 | 408 | ## Security Notes 409 | 410 | - OAuth credentials are stored securely in your local environment (`~/.gmail-mcp/`) 411 | - The server uses offline access to maintain persistent authentication 412 | - Never share or commit your credentials to version control 413 | - Regularly review and revoke unused access in your Google Account settings 414 | - Credentials are stored globally but are only accessible by the current user 415 | 416 | ## Troubleshooting 417 | 418 | 1. **OAuth Keys Not Found** 419 | - Make sure `gcp-oauth.keys.json` is in either your current directory or `~/.gmail-mcp/` 420 | - Check file permissions 421 | 422 | 2. **Invalid Credentials Format** 423 | - Ensure your OAuth keys file contains either `web` or `installed` credentials 424 | - For web applications, verify the redirect URI is correctly configured 425 | 426 | 3. **Port Already in Use** 427 | - If port 3000 is already in use, please free it up before running authentication 428 | - You can find and stop the process using that port 429 | 430 | 4. **Batch Operation Failures** 431 | - If batch operations fail, they automatically retry individual items 432 | - Check the detailed error messages for specific failures 433 | - Consider reducing the batch size if you encounter rate limiting 434 | 435 | ## Contributing 436 | 437 | Contributions are welcome! Please feel free to submit a Pull Request. 438 | 439 | 440 | ## Running evals 441 | 442 | The evals package loads an mcp client that then runs the index.ts file, so there is no need to rebuild between tests. You can load environment variables by prefixing the npx command. Full documentation can be found [here](https://www.mcpevals.io/docs). 443 | 444 | ```bash 445 | OPENAI_API_KEY=your-key npx mcp-eval src/evals/evals.ts src/index.ts 446 | ``` 447 | 448 | ## License 449 | 450 | MIT 451 | 452 | ## Support 453 | 454 | If you encounter any issues or have questions, please file an issue on the GitHub repository. -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | gmail-mcp: 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | volumes: 9 | - mcp-gmail:/gmail-server 10 | environment: 11 | - GMAIL_CREDENTIALS_PATH=/gmail-server/credentials.json 12 | ports: 13 | - "3000:3000" 14 | restart: unless-stopped 15 | 16 | volumes: 17 | mcp-gmail: -------------------------------------------------------------------------------- /llms-install.md: -------------------------------------------------------------------------------- 1 | # Gmail AutoAuth MCP Installation Guide 2 | 3 | This guide will help you install and configure the Gmail AutoAuth MCP server for managing Gmail operations through Claude Desktop with auto authentication support. 4 | 5 | ## Requirements 6 | 7 | - Node.js and npm installed 8 | - Access to create a Google Cloud Project 9 | - Local directory for configuration storage 10 | - Web browser for OAuth authentication 11 | 12 | ## Installation Steps 13 | 14 | 1. First, create a Google Cloud Project and obtain the necessary credentials: 15 | ``` 16 | 1. Go to Google Cloud Console (https://console.cloud.google.com) 17 | 2. Create a new project or select an existing one 18 | 3. Enable the Gmail API for your project 19 | 4. Create OAuth 2.0 credentials: 20 | - Go to "APIs & Services" > "Credentials" 21 | - Click "Create Credentials" > "OAuth client ID" 22 | - Choose "Desktop app" or "Web application" type 23 | - For Web application, add http://localhost:3000/oauth2callback to redirect URIs 24 | - Download the OAuth keys JSON file 25 | - Rename it to gcp-oauth.keys.json 26 | ``` 27 | 28 | 2. Set up the configuration directory: 29 | ```bash 30 | mkdir -p ~/.gmail-mcp 31 | mv gcp-oauth.keys.json ~/.gmail-mcp/ 32 | ``` 33 | 34 | 3. Run authentication: 35 | ```bash 36 | npx @gongrzhe/server-gmail-autoauth-mcp auth 37 | ``` 38 | This will: 39 | - Look for gcp-oauth.keys.json in current directory or ~/.gmail-mcp/ 40 | - Copy it to ~/.gmail-mcp/ if found in current directory 41 | - Launch browser for Google authentication 42 | - Save credentials as ~/.gmail-mcp/credentials.json 43 | 44 | 4. Configure Claude Desktop by adding the MCP server configuration: 45 | ```json 46 | { 47 | "mcpServers": { 48 | "gmail": { 49 | "command": "npx", 50 | "args": [ 51 | "@gongrzhe/server-gmail-autoauth-mcp" 52 | ] 53 | } 54 | } 55 | } 56 | ``` 57 | 58 | ## Troubleshooting 59 | 60 | If you encounter any issues during installation: 61 | 62 | 1. OAuth Keys Issues: 63 | - Verify gcp-oauth.keys.json exists in correct location 64 | - Check file permissions 65 | - Ensure keys contain valid web or installed credentials 66 | 67 | 2. Authentication Errors: 68 | - Confirm Gmail API is enabled 69 | - For web applications, verify redirect URI configuration 70 | - Check port 3000 is available during authentication 71 | 72 | 3. Configuration Issues: 73 | - Verify ~/.gmail-mcp directory exists and has correct permissions 74 | - Check credentials.json was created after authentication 75 | - Ensure Claude Desktop configuration is properly formatted 76 | 77 | ## Security Notes 78 | 79 | - Store OAuth credentials securely in ~/.gmail-mcp/ 80 | - Never commit credentials to version control 81 | - Use proper file permissions for config directory 82 | - Regularly review access in Google Account settings 83 | - Credentials are only accessible by current user 84 | 85 | ## Usage Examples 86 | 87 | After installation, you can perform various Gmail operations: 88 | 89 | ### Send Email 90 | ```json 91 | { 92 | "to": ["recipient@example.com"], 93 | "subject": "Meeting Tomorrow", 94 | "body": "Hi,\n\nJust a reminder about our meeting tomorrow at 10 AM.\n\nBest regards", 95 | "cc": ["cc@example.com"], 96 | "bcc": ["bcc@example.com"] 97 | } 98 | ``` 99 | 100 | ### Search Emails 101 | ```json 102 | { 103 | "query": "from:sender@example.com after:2024/01/01", 104 | "maxResults": 10 105 | } 106 | ``` 107 | 108 | ### Manage Email 109 | - Read emails by ID 110 | - Move emails between labels 111 | - Mark emails as read/unread 112 | - Delete emails 113 | - List emails in different folders 114 | 115 | For more details or support, please check the GitHub repository or file an issue. -------------------------------------------------------------------------------- /mcp-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mcpServers": { 3 | "gmail": { 4 | "command": "node", 5 | "args": [ 6 | "D:\\BackDataService\\Gmail-MCP-Server\\dist\\index.js" 7 | ] 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@gongrzhe/server-gmail-autoauth-mcp", 3 | "version": "1.1.8", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@gongrzhe/server-gmail-autoauth-mcp", 9 | "version": "1.1.8", 10 | "license": "ISC", 11 | "dependencies": { 12 | "@modelcontextprotocol/sdk": "^0.4.0", 13 | "google-auth-library": "^9.4.1", 14 | "googleapis": "^129.0.0", 15 | "mcp-evals": "^1.0.18", 16 | "open": "^10.0.0", 17 | "zod": "^3.22.4", 18 | "zod-to-json-schema": "^3.22.1" 19 | }, 20 | "bin": { 21 | "gmail-mcp": "dist/index.js" 22 | }, 23 | "devDependencies": { 24 | "@types/node": "^20.10.5", 25 | "typescript": "^5.3.3" 26 | }, 27 | "engines": { 28 | "node": ">=14.0.0" 29 | } 30 | }, 31 | "node_modules/@actions/core": { 32 | "version": "1.11.1", 33 | "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", 34 | "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", 35 | "license": "MIT", 36 | "dependencies": { 37 | "@actions/exec": "^1.1.1", 38 | "@actions/http-client": "^2.0.1" 39 | } 40 | }, 41 | "node_modules/@actions/exec": { 42 | "version": "1.1.1", 43 | "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", 44 | "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", 45 | "license": "MIT", 46 | "dependencies": { 47 | "@actions/io": "^1.0.1" 48 | } 49 | }, 50 | "node_modules/@actions/http-client": { 51 | "version": "2.2.3", 52 | "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", 53 | "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", 54 | "license": "MIT", 55 | "dependencies": { 56 | "tunnel": "^0.0.6", 57 | "undici": "^5.25.4" 58 | } 59 | }, 60 | "node_modules/@actions/io": { 61 | "version": "1.1.3", 62 | "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", 63 | "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", 64 | "license": "MIT" 65 | }, 66 | "node_modules/@ai-sdk/openai": { 67 | "version": "1.3.21", 68 | "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-1.3.21.tgz", 69 | "integrity": "sha512-ipAhkRKUd2YaMmn7DAklX3N7Ywx/rCsJHVyb0V/lKRqPcc612qAFVbjg+Uve8QYJlbPxgfsM4s9JmCFp6PSdYw==", 70 | "license": "Apache-2.0", 71 | "dependencies": { 72 | "@ai-sdk/provider": "1.1.3", 73 | "@ai-sdk/provider-utils": "2.2.7" 74 | }, 75 | "engines": { 76 | "node": ">=18" 77 | }, 78 | "peerDependencies": { 79 | "zod": "^3.0.0" 80 | } 81 | }, 82 | "node_modules/@ai-sdk/provider": { 83 | "version": "1.1.3", 84 | "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-1.1.3.tgz", 85 | "integrity": "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==", 86 | "license": "Apache-2.0", 87 | "dependencies": { 88 | "json-schema": "^0.4.0" 89 | }, 90 | "engines": { 91 | "node": ">=18" 92 | } 93 | }, 94 | "node_modules/@ai-sdk/provider-utils": { 95 | "version": "2.2.7", 96 | "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-2.2.7.tgz", 97 | "integrity": "sha512-kM0xS3GWg3aMChh9zfeM+80vEZfXzR3JEUBdycZLtbRZ2TRT8xOj3WodGHPb06sUK5yD7pAXC/P7ctsi2fvUGQ==", 98 | "license": "Apache-2.0", 99 | "dependencies": { 100 | "@ai-sdk/provider": "1.1.3", 101 | "nanoid": "^3.3.8", 102 | "secure-json-parse": "^2.7.0" 103 | }, 104 | "engines": { 105 | "node": ">=18" 106 | }, 107 | "peerDependencies": { 108 | "zod": "^3.23.8" 109 | } 110 | }, 111 | "node_modules/@ai-sdk/react": { 112 | "version": "1.2.11", 113 | "resolved": "https://registry.npmjs.org/@ai-sdk/react/-/react-1.2.11.tgz", 114 | "integrity": "sha512-+kPqLkJ3TWP6czaJPV+vzAKSUcKQ1598BUrcLHt56sH99+LhmIIW3ylZp0OfC3O6TR3eO1Lt0Yzw4R0mK6g9Gw==", 115 | "license": "Apache-2.0", 116 | "dependencies": { 117 | "@ai-sdk/provider-utils": "2.2.7", 118 | "@ai-sdk/ui-utils": "1.2.10", 119 | "swr": "^2.2.5", 120 | "throttleit": "2.1.0" 121 | }, 122 | "engines": { 123 | "node": ">=18" 124 | }, 125 | "peerDependencies": { 126 | "react": "^18 || ^19 || ^19.0.0-rc", 127 | "zod": "^3.23.8" 128 | }, 129 | "peerDependenciesMeta": { 130 | "zod": { 131 | "optional": true 132 | } 133 | } 134 | }, 135 | "node_modules/@ai-sdk/ui-utils": { 136 | "version": "1.2.10", 137 | "resolved": "https://registry.npmjs.org/@ai-sdk/ui-utils/-/ui-utils-1.2.10.tgz", 138 | "integrity": "sha512-GUj+LBoAlRQF1dL/M49jtufGqtLOMApxTpCmVjoRpIPt/dFALVL9RfqfvxwztyIwbK+IxGzcYjSGRsrWrj+86g==", 139 | "license": "Apache-2.0", 140 | "dependencies": { 141 | "@ai-sdk/provider": "1.1.3", 142 | "@ai-sdk/provider-utils": "2.2.7", 143 | "zod-to-json-schema": "^3.24.1" 144 | }, 145 | "engines": { 146 | "node": ">=18" 147 | }, 148 | "peerDependencies": { 149 | "zod": "^3.23.8" 150 | } 151 | }, 152 | "node_modules/@anthropic-ai/sdk": { 153 | "version": "0.8.1", 154 | "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.8.1.tgz", 155 | "integrity": "sha512-59etePenCizVx1O8Qhi1T1ruE04ISfNzCnyhZNcsss1QljsLmYS83jttarMNEvGYcsUF7rwxw2lzcC3Zbxao7g==", 156 | "license": "MIT", 157 | "dependencies": { 158 | "@types/node": "^18.11.18", 159 | "@types/node-fetch": "^2.6.4", 160 | "abort-controller": "^3.0.0", 161 | "agentkeepalive": "^4.2.1", 162 | "digest-fetch": "^1.3.0", 163 | "form-data-encoder": "1.7.2", 164 | "formdata-node": "^4.3.2", 165 | "node-fetch": "^2.6.7", 166 | "web-streams-polyfill": "^3.2.1" 167 | } 168 | }, 169 | "node_modules/@anthropic-ai/sdk/node_modules/@types/node": { 170 | "version": "18.19.87", 171 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.87.tgz", 172 | "integrity": "sha512-OIAAu6ypnVZHmsHCeJ+7CCSub38QNBS9uceMQeg7K5Ur0Jr+wG9wEOEvvMbhp09pxD5czIUy/jND7s7Tb6Nw7A==", 173 | "license": "MIT", 174 | "dependencies": { 175 | "undici-types": "~5.26.4" 176 | } 177 | }, 178 | "node_modules/@anthropic-ai/sdk/node_modules/undici-types": { 179 | "version": "5.26.5", 180 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 181 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 182 | "license": "MIT" 183 | }, 184 | "node_modules/@esbuild/aix-ppc64": { 185 | "version": "0.25.3", 186 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", 187 | "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", 188 | "cpu": [ 189 | "ppc64" 190 | ], 191 | "license": "MIT", 192 | "optional": true, 193 | "os": [ 194 | "aix" 195 | ], 196 | "engines": { 197 | "node": ">=18" 198 | } 199 | }, 200 | "node_modules/@esbuild/android-arm": { 201 | "version": "0.25.3", 202 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", 203 | "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", 204 | "cpu": [ 205 | "arm" 206 | ], 207 | "license": "MIT", 208 | "optional": true, 209 | "os": [ 210 | "android" 211 | ], 212 | "engines": { 213 | "node": ">=18" 214 | } 215 | }, 216 | "node_modules/@esbuild/android-arm64": { 217 | "version": "0.25.3", 218 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", 219 | "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", 220 | "cpu": [ 221 | "arm64" 222 | ], 223 | "license": "MIT", 224 | "optional": true, 225 | "os": [ 226 | "android" 227 | ], 228 | "engines": { 229 | "node": ">=18" 230 | } 231 | }, 232 | "node_modules/@esbuild/android-x64": { 233 | "version": "0.25.3", 234 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", 235 | "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", 236 | "cpu": [ 237 | "x64" 238 | ], 239 | "license": "MIT", 240 | "optional": true, 241 | "os": [ 242 | "android" 243 | ], 244 | "engines": { 245 | "node": ">=18" 246 | } 247 | }, 248 | "node_modules/@esbuild/darwin-arm64": { 249 | "version": "0.25.3", 250 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", 251 | "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", 252 | "cpu": [ 253 | "arm64" 254 | ], 255 | "license": "MIT", 256 | "optional": true, 257 | "os": [ 258 | "darwin" 259 | ], 260 | "engines": { 261 | "node": ">=18" 262 | } 263 | }, 264 | "node_modules/@esbuild/darwin-x64": { 265 | "version": "0.25.3", 266 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", 267 | "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", 268 | "cpu": [ 269 | "x64" 270 | ], 271 | "license": "MIT", 272 | "optional": true, 273 | "os": [ 274 | "darwin" 275 | ], 276 | "engines": { 277 | "node": ">=18" 278 | } 279 | }, 280 | "node_modules/@esbuild/freebsd-arm64": { 281 | "version": "0.25.3", 282 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", 283 | "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", 284 | "cpu": [ 285 | "arm64" 286 | ], 287 | "license": "MIT", 288 | "optional": true, 289 | "os": [ 290 | "freebsd" 291 | ], 292 | "engines": { 293 | "node": ">=18" 294 | } 295 | }, 296 | "node_modules/@esbuild/freebsd-x64": { 297 | "version": "0.25.3", 298 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", 299 | "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", 300 | "cpu": [ 301 | "x64" 302 | ], 303 | "license": "MIT", 304 | "optional": true, 305 | "os": [ 306 | "freebsd" 307 | ], 308 | "engines": { 309 | "node": ">=18" 310 | } 311 | }, 312 | "node_modules/@esbuild/linux-arm": { 313 | "version": "0.25.3", 314 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", 315 | "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", 316 | "cpu": [ 317 | "arm" 318 | ], 319 | "license": "MIT", 320 | "optional": true, 321 | "os": [ 322 | "linux" 323 | ], 324 | "engines": { 325 | "node": ">=18" 326 | } 327 | }, 328 | "node_modules/@esbuild/linux-arm64": { 329 | "version": "0.25.3", 330 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", 331 | "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", 332 | "cpu": [ 333 | "arm64" 334 | ], 335 | "license": "MIT", 336 | "optional": true, 337 | "os": [ 338 | "linux" 339 | ], 340 | "engines": { 341 | "node": ">=18" 342 | } 343 | }, 344 | "node_modules/@esbuild/linux-ia32": { 345 | "version": "0.25.3", 346 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", 347 | "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", 348 | "cpu": [ 349 | "ia32" 350 | ], 351 | "license": "MIT", 352 | "optional": true, 353 | "os": [ 354 | "linux" 355 | ], 356 | "engines": { 357 | "node": ">=18" 358 | } 359 | }, 360 | "node_modules/@esbuild/linux-loong64": { 361 | "version": "0.25.3", 362 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", 363 | "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", 364 | "cpu": [ 365 | "loong64" 366 | ], 367 | "license": "MIT", 368 | "optional": true, 369 | "os": [ 370 | "linux" 371 | ], 372 | "engines": { 373 | "node": ">=18" 374 | } 375 | }, 376 | "node_modules/@esbuild/linux-mips64el": { 377 | "version": "0.25.3", 378 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", 379 | "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", 380 | "cpu": [ 381 | "mips64el" 382 | ], 383 | "license": "MIT", 384 | "optional": true, 385 | "os": [ 386 | "linux" 387 | ], 388 | "engines": { 389 | "node": ">=18" 390 | } 391 | }, 392 | "node_modules/@esbuild/linux-ppc64": { 393 | "version": "0.25.3", 394 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", 395 | "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", 396 | "cpu": [ 397 | "ppc64" 398 | ], 399 | "license": "MIT", 400 | "optional": true, 401 | "os": [ 402 | "linux" 403 | ], 404 | "engines": { 405 | "node": ">=18" 406 | } 407 | }, 408 | "node_modules/@esbuild/linux-riscv64": { 409 | "version": "0.25.3", 410 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", 411 | "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", 412 | "cpu": [ 413 | "riscv64" 414 | ], 415 | "license": "MIT", 416 | "optional": true, 417 | "os": [ 418 | "linux" 419 | ], 420 | "engines": { 421 | "node": ">=18" 422 | } 423 | }, 424 | "node_modules/@esbuild/linux-s390x": { 425 | "version": "0.25.3", 426 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", 427 | "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", 428 | "cpu": [ 429 | "s390x" 430 | ], 431 | "license": "MIT", 432 | "optional": true, 433 | "os": [ 434 | "linux" 435 | ], 436 | "engines": { 437 | "node": ">=18" 438 | } 439 | }, 440 | "node_modules/@esbuild/linux-x64": { 441 | "version": "0.25.3", 442 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", 443 | "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", 444 | "cpu": [ 445 | "x64" 446 | ], 447 | "license": "MIT", 448 | "optional": true, 449 | "os": [ 450 | "linux" 451 | ], 452 | "engines": { 453 | "node": ">=18" 454 | } 455 | }, 456 | "node_modules/@esbuild/netbsd-arm64": { 457 | "version": "0.25.3", 458 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", 459 | "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", 460 | "cpu": [ 461 | "arm64" 462 | ], 463 | "license": "MIT", 464 | "optional": true, 465 | "os": [ 466 | "netbsd" 467 | ], 468 | "engines": { 469 | "node": ">=18" 470 | } 471 | }, 472 | "node_modules/@esbuild/netbsd-x64": { 473 | "version": "0.25.3", 474 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", 475 | "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", 476 | "cpu": [ 477 | "x64" 478 | ], 479 | "license": "MIT", 480 | "optional": true, 481 | "os": [ 482 | "netbsd" 483 | ], 484 | "engines": { 485 | "node": ">=18" 486 | } 487 | }, 488 | "node_modules/@esbuild/openbsd-arm64": { 489 | "version": "0.25.3", 490 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", 491 | "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", 492 | "cpu": [ 493 | "arm64" 494 | ], 495 | "license": "MIT", 496 | "optional": true, 497 | "os": [ 498 | "openbsd" 499 | ], 500 | "engines": { 501 | "node": ">=18" 502 | } 503 | }, 504 | "node_modules/@esbuild/openbsd-x64": { 505 | "version": "0.25.3", 506 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", 507 | "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", 508 | "cpu": [ 509 | "x64" 510 | ], 511 | "license": "MIT", 512 | "optional": true, 513 | "os": [ 514 | "openbsd" 515 | ], 516 | "engines": { 517 | "node": ">=18" 518 | } 519 | }, 520 | "node_modules/@esbuild/sunos-x64": { 521 | "version": "0.25.3", 522 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", 523 | "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", 524 | "cpu": [ 525 | "x64" 526 | ], 527 | "license": "MIT", 528 | "optional": true, 529 | "os": [ 530 | "sunos" 531 | ], 532 | "engines": { 533 | "node": ">=18" 534 | } 535 | }, 536 | "node_modules/@esbuild/win32-arm64": { 537 | "version": "0.25.3", 538 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", 539 | "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", 540 | "cpu": [ 541 | "arm64" 542 | ], 543 | "license": "MIT", 544 | "optional": true, 545 | "os": [ 546 | "win32" 547 | ], 548 | "engines": { 549 | "node": ">=18" 550 | } 551 | }, 552 | "node_modules/@esbuild/win32-ia32": { 553 | "version": "0.25.3", 554 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", 555 | "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", 556 | "cpu": [ 557 | "ia32" 558 | ], 559 | "license": "MIT", 560 | "optional": true, 561 | "os": [ 562 | "win32" 563 | ], 564 | "engines": { 565 | "node": ">=18" 566 | } 567 | }, 568 | "node_modules/@esbuild/win32-x64": { 569 | "version": "0.25.3", 570 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", 571 | "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", 572 | "cpu": [ 573 | "x64" 574 | ], 575 | "license": "MIT", 576 | "optional": true, 577 | "os": [ 578 | "win32" 579 | ], 580 | "engines": { 581 | "node": ">=18" 582 | } 583 | }, 584 | "node_modules/@fastify/busboy": { 585 | "version": "2.1.1", 586 | "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", 587 | "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", 588 | "license": "MIT", 589 | "engines": { 590 | "node": ">=14" 591 | } 592 | }, 593 | "node_modules/@modelcontextprotocol/sdk": { 594 | "version": "0.4.0", 595 | "license": "MIT", 596 | "dependencies": { 597 | "content-type": "^1.0.5", 598 | "raw-body": "^3.0.0", 599 | "zod": "^3.23.8" 600 | } 601 | }, 602 | "node_modules/@opentelemetry/api": { 603 | "version": "1.9.0", 604 | "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", 605 | "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", 606 | "license": "Apache-2.0", 607 | "engines": { 608 | "node": ">=8.0.0" 609 | } 610 | }, 611 | "node_modules/@types/diff-match-patch": { 612 | "version": "1.0.36", 613 | "resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz", 614 | "integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==", 615 | "license": "MIT" 616 | }, 617 | "node_modules/@types/node": { 618 | "version": "20.17.10", 619 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz", 620 | "integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==", 621 | "license": "MIT", 622 | "dependencies": { 623 | "undici-types": "~6.19.2" 624 | } 625 | }, 626 | "node_modules/@types/node-fetch": { 627 | "version": "2.6.12", 628 | "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.12.tgz", 629 | "integrity": "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==", 630 | "license": "MIT", 631 | "dependencies": { 632 | "@types/node": "*", 633 | "form-data": "^4.0.0" 634 | } 635 | }, 636 | "node_modules/abort-controller": { 637 | "version": "3.0.0", 638 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 639 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 640 | "license": "MIT", 641 | "dependencies": { 642 | "event-target-shim": "^5.0.0" 643 | }, 644 | "engines": { 645 | "node": ">=6.5" 646 | } 647 | }, 648 | "node_modules/accepts": { 649 | "version": "2.0.0", 650 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", 651 | "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", 652 | "license": "MIT", 653 | "dependencies": { 654 | "mime-types": "^3.0.0", 655 | "negotiator": "^1.0.0" 656 | }, 657 | "engines": { 658 | "node": ">= 0.6" 659 | } 660 | }, 661 | "node_modules/accepts/node_modules/mime-db": { 662 | "version": "1.54.0", 663 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 664 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 665 | "license": "MIT", 666 | "engines": { 667 | "node": ">= 0.6" 668 | } 669 | }, 670 | "node_modules/accepts/node_modules/mime-types": { 671 | "version": "3.0.1", 672 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 673 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 674 | "license": "MIT", 675 | "dependencies": { 676 | "mime-db": "^1.54.0" 677 | }, 678 | "engines": { 679 | "node": ">= 0.6" 680 | } 681 | }, 682 | "node_modules/agent-base": { 683 | "version": "7.1.3", 684 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", 685 | "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", 686 | "license": "MIT", 687 | "engines": { 688 | "node": ">= 14" 689 | } 690 | }, 691 | "node_modules/agentkeepalive": { 692 | "version": "4.6.0", 693 | "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", 694 | "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", 695 | "license": "MIT", 696 | "dependencies": { 697 | "humanize-ms": "^1.2.1" 698 | }, 699 | "engines": { 700 | "node": ">= 8.0.0" 701 | } 702 | }, 703 | "node_modules/ai": { 704 | "version": "4.3.13", 705 | "resolved": "https://registry.npmjs.org/ai/-/ai-4.3.13.tgz", 706 | "integrity": "sha512-cC5HXItuOwGykSMacCPzNp6+NMTxeuTjOenztVgSJhdC9Z4OrzBxwkyeDAf4h1QP938ZFi7IBdq3u4lxVoVmvw==", 707 | "license": "Apache-2.0", 708 | "dependencies": { 709 | "@ai-sdk/provider": "1.1.3", 710 | "@ai-sdk/provider-utils": "2.2.7", 711 | "@ai-sdk/react": "1.2.11", 712 | "@ai-sdk/ui-utils": "1.2.10", 713 | "@opentelemetry/api": "1.9.0", 714 | "jsondiffpatch": "0.6.0" 715 | }, 716 | "engines": { 717 | "node": ">=18" 718 | }, 719 | "peerDependencies": { 720 | "react": "^18 || ^19 || ^19.0.0-rc", 721 | "zod": "^3.23.8" 722 | }, 723 | "peerDependenciesMeta": { 724 | "react": { 725 | "optional": true 726 | } 727 | } 728 | }, 729 | "node_modules/ansi-styles": { 730 | "version": "4.3.0", 731 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 732 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 733 | "license": "MIT", 734 | "dependencies": { 735 | "color-convert": "^2.0.1" 736 | }, 737 | "engines": { 738 | "node": ">=8" 739 | }, 740 | "funding": { 741 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 742 | } 743 | }, 744 | "node_modules/asynckit": { 745 | "version": "0.4.0", 746 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 747 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", 748 | "license": "MIT" 749 | }, 750 | "node_modules/base-64": { 751 | "version": "0.1.0", 752 | "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", 753 | "integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==" 754 | }, 755 | "node_modules/base64-js": { 756 | "version": "1.5.1", 757 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 758 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 759 | "funding": [ 760 | { 761 | "type": "github", 762 | "url": "https://github.com/sponsors/feross" 763 | }, 764 | { 765 | "type": "patreon", 766 | "url": "https://www.patreon.com/feross" 767 | }, 768 | { 769 | "type": "consulting", 770 | "url": "https://feross.org/support" 771 | } 772 | ], 773 | "license": "MIT" 774 | }, 775 | "node_modules/bignumber.js": { 776 | "version": "9.1.2", 777 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", 778 | "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", 779 | "license": "MIT", 780 | "engines": { 781 | "node": "*" 782 | } 783 | }, 784 | "node_modules/body-parser": { 785 | "version": "2.2.0", 786 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", 787 | "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", 788 | "license": "MIT", 789 | "dependencies": { 790 | "bytes": "^3.1.2", 791 | "content-type": "^1.0.5", 792 | "debug": "^4.4.0", 793 | "http-errors": "^2.0.0", 794 | "iconv-lite": "^0.6.3", 795 | "on-finished": "^2.4.1", 796 | "qs": "^6.14.0", 797 | "raw-body": "^3.0.0", 798 | "type-is": "^2.0.0" 799 | }, 800 | "engines": { 801 | "node": ">=18" 802 | } 803 | }, 804 | "node_modules/buffer-equal-constant-time": { 805 | "version": "1.0.1", 806 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 807 | "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", 808 | "license": "BSD-3-Clause" 809 | }, 810 | "node_modules/bundle-name": { 811 | "version": "4.1.0", 812 | "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", 813 | "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", 814 | "license": "MIT", 815 | "dependencies": { 816 | "run-applescript": "^7.0.0" 817 | }, 818 | "engines": { 819 | "node": ">=18" 820 | }, 821 | "funding": { 822 | "url": "https://github.com/sponsors/sindresorhus" 823 | } 824 | }, 825 | "node_modules/bytes": { 826 | "version": "3.1.2", 827 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 828 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 829 | "license": "MIT", 830 | "engines": { 831 | "node": ">= 0.8" 832 | } 833 | }, 834 | "node_modules/call-bind-apply-helpers": { 835 | "version": "1.0.1", 836 | "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", 837 | "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", 838 | "license": "MIT", 839 | "dependencies": { 840 | "es-errors": "^1.3.0", 841 | "function-bind": "^1.1.2" 842 | }, 843 | "engines": { 844 | "node": ">= 0.4" 845 | } 846 | }, 847 | "node_modules/call-bound": { 848 | "version": "1.0.3", 849 | "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", 850 | "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", 851 | "license": "MIT", 852 | "dependencies": { 853 | "call-bind-apply-helpers": "^1.0.1", 854 | "get-intrinsic": "^1.2.6" 855 | }, 856 | "engines": { 857 | "node": ">= 0.4" 858 | }, 859 | "funding": { 860 | "url": "https://github.com/sponsors/ljharb" 861 | } 862 | }, 863 | "node_modules/chalk": { 864 | "version": "4.1.2", 865 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 866 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 867 | "license": "MIT", 868 | "dependencies": { 869 | "ansi-styles": "^4.1.0", 870 | "supports-color": "^7.1.0" 871 | }, 872 | "engines": { 873 | "node": ">=10" 874 | }, 875 | "funding": { 876 | "url": "https://github.com/chalk/chalk?sponsor=1" 877 | } 878 | }, 879 | "node_modules/charenc": { 880 | "version": "0.0.2", 881 | "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", 882 | "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", 883 | "license": "BSD-3-Clause", 884 | "engines": { 885 | "node": "*" 886 | } 887 | }, 888 | "node_modules/color-convert": { 889 | "version": "2.0.1", 890 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 891 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 892 | "license": "MIT", 893 | "dependencies": { 894 | "color-name": "~1.1.4" 895 | }, 896 | "engines": { 897 | "node": ">=7.0.0" 898 | } 899 | }, 900 | "node_modules/color-name": { 901 | "version": "1.1.4", 902 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 903 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 904 | "license": "MIT" 905 | }, 906 | "node_modules/combined-stream": { 907 | "version": "1.0.8", 908 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 909 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 910 | "license": "MIT", 911 | "dependencies": { 912 | "delayed-stream": "~1.0.0" 913 | }, 914 | "engines": { 915 | "node": ">= 0.8" 916 | } 917 | }, 918 | "node_modules/content-disposition": { 919 | "version": "1.0.0", 920 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", 921 | "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", 922 | "license": "MIT", 923 | "dependencies": { 924 | "safe-buffer": "5.2.1" 925 | }, 926 | "engines": { 927 | "node": ">= 0.6" 928 | } 929 | }, 930 | "node_modules/content-type": { 931 | "version": "1.0.5", 932 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 933 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", 934 | "license": "MIT", 935 | "engines": { 936 | "node": ">= 0.6" 937 | } 938 | }, 939 | "node_modules/cookie": { 940 | "version": "0.7.2", 941 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", 942 | "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", 943 | "license": "MIT", 944 | "engines": { 945 | "node": ">= 0.6" 946 | } 947 | }, 948 | "node_modules/cookie-signature": { 949 | "version": "1.2.2", 950 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", 951 | "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", 952 | "license": "MIT", 953 | "engines": { 954 | "node": ">=6.6.0" 955 | } 956 | }, 957 | "node_modules/cors": { 958 | "version": "2.8.5", 959 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 960 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 961 | "license": "MIT", 962 | "dependencies": { 963 | "object-assign": "^4", 964 | "vary": "^1" 965 | }, 966 | "engines": { 967 | "node": ">= 0.10" 968 | } 969 | }, 970 | "node_modules/cross-spawn": { 971 | "version": "7.0.6", 972 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 973 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 974 | "license": "MIT", 975 | "dependencies": { 976 | "path-key": "^3.1.0", 977 | "shebang-command": "^2.0.0", 978 | "which": "^2.0.1" 979 | }, 980 | "engines": { 981 | "node": ">= 8" 982 | } 983 | }, 984 | "node_modules/crypt": { 985 | "version": "0.0.2", 986 | "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", 987 | "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", 988 | "license": "BSD-3-Clause", 989 | "engines": { 990 | "node": "*" 991 | } 992 | }, 993 | "node_modules/debug": { 994 | "version": "4.4.0", 995 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 996 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 997 | "license": "MIT", 998 | "dependencies": { 999 | "ms": "^2.1.3" 1000 | }, 1001 | "engines": { 1002 | "node": ">=6.0" 1003 | }, 1004 | "peerDependenciesMeta": { 1005 | "supports-color": { 1006 | "optional": true 1007 | } 1008 | } 1009 | }, 1010 | "node_modules/default-browser": { 1011 | "version": "5.2.1", 1012 | "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", 1013 | "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", 1014 | "license": "MIT", 1015 | "dependencies": { 1016 | "bundle-name": "^4.1.0", 1017 | "default-browser-id": "^5.0.0" 1018 | }, 1019 | "engines": { 1020 | "node": ">=18" 1021 | }, 1022 | "funding": { 1023 | "url": "https://github.com/sponsors/sindresorhus" 1024 | } 1025 | }, 1026 | "node_modules/default-browser-id": { 1027 | "version": "5.0.0", 1028 | "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", 1029 | "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", 1030 | "license": "MIT", 1031 | "engines": { 1032 | "node": ">=18" 1033 | }, 1034 | "funding": { 1035 | "url": "https://github.com/sponsors/sindresorhus" 1036 | } 1037 | }, 1038 | "node_modules/define-lazy-prop": { 1039 | "version": "3.0.0", 1040 | "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", 1041 | "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", 1042 | "license": "MIT", 1043 | "engines": { 1044 | "node": ">=12" 1045 | }, 1046 | "funding": { 1047 | "url": "https://github.com/sponsors/sindresorhus" 1048 | } 1049 | }, 1050 | "node_modules/delayed-stream": { 1051 | "version": "1.0.0", 1052 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 1053 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 1054 | "license": "MIT", 1055 | "engines": { 1056 | "node": ">=0.4.0" 1057 | } 1058 | }, 1059 | "node_modules/depd": { 1060 | "version": "2.0.0", 1061 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 1062 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", 1063 | "license": "MIT", 1064 | "engines": { 1065 | "node": ">= 0.8" 1066 | } 1067 | }, 1068 | "node_modules/dequal": { 1069 | "version": "2.0.3", 1070 | "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", 1071 | "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", 1072 | "license": "MIT", 1073 | "engines": { 1074 | "node": ">=6" 1075 | } 1076 | }, 1077 | "node_modules/diff-match-patch": { 1078 | "version": "1.0.5", 1079 | "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", 1080 | "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==", 1081 | "license": "Apache-2.0" 1082 | }, 1083 | "node_modules/digest-fetch": { 1084 | "version": "1.3.0", 1085 | "resolved": "https://registry.npmjs.org/digest-fetch/-/digest-fetch-1.3.0.tgz", 1086 | "integrity": "sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==", 1087 | "license": "ISC", 1088 | "dependencies": { 1089 | "base-64": "^0.1.0", 1090 | "md5": "^2.3.0" 1091 | } 1092 | }, 1093 | "node_modules/dotenv": { 1094 | "version": "16.5.0", 1095 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", 1096 | "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", 1097 | "license": "BSD-2-Clause", 1098 | "engines": { 1099 | "node": ">=12" 1100 | }, 1101 | "funding": { 1102 | "url": "https://dotenvx.com" 1103 | } 1104 | }, 1105 | "node_modules/dunder-proto": { 1106 | "version": "1.0.1", 1107 | "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", 1108 | "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", 1109 | "license": "MIT", 1110 | "dependencies": { 1111 | "call-bind-apply-helpers": "^1.0.1", 1112 | "es-errors": "^1.3.0", 1113 | "gopd": "^1.2.0" 1114 | }, 1115 | "engines": { 1116 | "node": ">= 0.4" 1117 | } 1118 | }, 1119 | "node_modules/ecdsa-sig-formatter": { 1120 | "version": "1.0.11", 1121 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 1122 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 1123 | "license": "Apache-2.0", 1124 | "dependencies": { 1125 | "safe-buffer": "^5.0.1" 1126 | } 1127 | }, 1128 | "node_modules/ee-first": { 1129 | "version": "1.1.1", 1130 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1131 | "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", 1132 | "license": "MIT" 1133 | }, 1134 | "node_modules/encodeurl": { 1135 | "version": "2.0.0", 1136 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", 1137 | "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", 1138 | "license": "MIT", 1139 | "engines": { 1140 | "node": ">= 0.8" 1141 | } 1142 | }, 1143 | "node_modules/es-define-property": { 1144 | "version": "1.0.1", 1145 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", 1146 | "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", 1147 | "license": "MIT", 1148 | "engines": { 1149 | "node": ">= 0.4" 1150 | } 1151 | }, 1152 | "node_modules/es-errors": { 1153 | "version": "1.3.0", 1154 | "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", 1155 | "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", 1156 | "license": "MIT", 1157 | "engines": { 1158 | "node": ">= 0.4" 1159 | } 1160 | }, 1161 | "node_modules/es-object-atoms": { 1162 | "version": "1.0.0", 1163 | "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", 1164 | "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", 1165 | "license": "MIT", 1166 | "dependencies": { 1167 | "es-errors": "^1.3.0" 1168 | }, 1169 | "engines": { 1170 | "node": ">= 0.4" 1171 | } 1172 | }, 1173 | "node_modules/es-set-tostringtag": { 1174 | "version": "2.1.0", 1175 | "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", 1176 | "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", 1177 | "license": "MIT", 1178 | "dependencies": { 1179 | "es-errors": "^1.3.0", 1180 | "get-intrinsic": "^1.2.6", 1181 | "has-tostringtag": "^1.0.2", 1182 | "hasown": "^2.0.2" 1183 | }, 1184 | "engines": { 1185 | "node": ">= 0.4" 1186 | } 1187 | }, 1188 | "node_modules/esbuild": { 1189 | "version": "0.25.3", 1190 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", 1191 | "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", 1192 | "hasInstallScript": true, 1193 | "license": "MIT", 1194 | "bin": { 1195 | "esbuild": "bin/esbuild" 1196 | }, 1197 | "engines": { 1198 | "node": ">=18" 1199 | }, 1200 | "optionalDependencies": { 1201 | "@esbuild/aix-ppc64": "0.25.3", 1202 | "@esbuild/android-arm": "0.25.3", 1203 | "@esbuild/android-arm64": "0.25.3", 1204 | "@esbuild/android-x64": "0.25.3", 1205 | "@esbuild/darwin-arm64": "0.25.3", 1206 | "@esbuild/darwin-x64": "0.25.3", 1207 | "@esbuild/freebsd-arm64": "0.25.3", 1208 | "@esbuild/freebsd-x64": "0.25.3", 1209 | "@esbuild/linux-arm": "0.25.3", 1210 | "@esbuild/linux-arm64": "0.25.3", 1211 | "@esbuild/linux-ia32": "0.25.3", 1212 | "@esbuild/linux-loong64": "0.25.3", 1213 | "@esbuild/linux-mips64el": "0.25.3", 1214 | "@esbuild/linux-ppc64": "0.25.3", 1215 | "@esbuild/linux-riscv64": "0.25.3", 1216 | "@esbuild/linux-s390x": "0.25.3", 1217 | "@esbuild/linux-x64": "0.25.3", 1218 | "@esbuild/netbsd-arm64": "0.25.3", 1219 | "@esbuild/netbsd-x64": "0.25.3", 1220 | "@esbuild/openbsd-arm64": "0.25.3", 1221 | "@esbuild/openbsd-x64": "0.25.3", 1222 | "@esbuild/sunos-x64": "0.25.3", 1223 | "@esbuild/win32-arm64": "0.25.3", 1224 | "@esbuild/win32-ia32": "0.25.3", 1225 | "@esbuild/win32-x64": "0.25.3" 1226 | } 1227 | }, 1228 | "node_modules/escape-html": { 1229 | "version": "1.0.3", 1230 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1231 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", 1232 | "license": "MIT" 1233 | }, 1234 | "node_modules/etag": { 1235 | "version": "1.8.1", 1236 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1237 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", 1238 | "license": "MIT", 1239 | "engines": { 1240 | "node": ">= 0.6" 1241 | } 1242 | }, 1243 | "node_modules/event-target-shim": { 1244 | "version": "5.0.1", 1245 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 1246 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", 1247 | "license": "MIT", 1248 | "engines": { 1249 | "node": ">=6" 1250 | } 1251 | }, 1252 | "node_modules/eventsource": { 1253 | "version": "3.0.6", 1254 | "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.6.tgz", 1255 | "integrity": "sha512-l19WpE2m9hSuyP06+FbuUUf1G+R0SFLrtQfbRb9PRr+oimOfxQhgGCbVaXg5IvZyyTThJsxh6L/srkMiCeBPDA==", 1256 | "license": "MIT", 1257 | "dependencies": { 1258 | "eventsource-parser": "^3.0.1" 1259 | }, 1260 | "engines": { 1261 | "node": ">=18.0.0" 1262 | } 1263 | }, 1264 | "node_modules/eventsource-parser": { 1265 | "version": "3.0.1", 1266 | "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.1.tgz", 1267 | "integrity": "sha512-VARTJ9CYeuQYb0pZEPbzi740OWFgpHe7AYJ2WFZVnUDUQp5Dk2yJUgF36YsZ81cOyxT0QxmXD2EQpapAouzWVA==", 1268 | "license": "MIT", 1269 | "engines": { 1270 | "node": ">=18.0.0" 1271 | } 1272 | }, 1273 | "node_modules/express": { 1274 | "version": "5.1.0", 1275 | "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", 1276 | "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", 1277 | "license": "MIT", 1278 | "dependencies": { 1279 | "accepts": "^2.0.0", 1280 | "body-parser": "^2.2.0", 1281 | "content-disposition": "^1.0.0", 1282 | "content-type": "^1.0.5", 1283 | "cookie": "^0.7.1", 1284 | "cookie-signature": "^1.2.1", 1285 | "debug": "^4.4.0", 1286 | "encodeurl": "^2.0.0", 1287 | "escape-html": "^1.0.3", 1288 | "etag": "^1.8.1", 1289 | "finalhandler": "^2.1.0", 1290 | "fresh": "^2.0.0", 1291 | "http-errors": "^2.0.0", 1292 | "merge-descriptors": "^2.0.0", 1293 | "mime-types": "^3.0.0", 1294 | "on-finished": "^2.4.1", 1295 | "once": "^1.4.0", 1296 | "parseurl": "^1.3.3", 1297 | "proxy-addr": "^2.0.7", 1298 | "qs": "^6.14.0", 1299 | "range-parser": "^1.2.1", 1300 | "router": "^2.2.0", 1301 | "send": "^1.1.0", 1302 | "serve-static": "^2.2.0", 1303 | "statuses": "^2.0.1", 1304 | "type-is": "^2.0.1", 1305 | "vary": "^1.1.2" 1306 | }, 1307 | "engines": { 1308 | "node": ">= 18" 1309 | }, 1310 | "funding": { 1311 | "type": "opencollective", 1312 | "url": "https://opencollective.com/express" 1313 | } 1314 | }, 1315 | "node_modules/express-rate-limit": { 1316 | "version": "7.5.0", 1317 | "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", 1318 | "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", 1319 | "license": "MIT", 1320 | "engines": { 1321 | "node": ">= 16" 1322 | }, 1323 | "funding": { 1324 | "url": "https://github.com/sponsors/express-rate-limit" 1325 | }, 1326 | "peerDependencies": { 1327 | "express": "^4.11 || 5 || ^5.0.0-beta.1" 1328 | } 1329 | }, 1330 | "node_modules/express/node_modules/mime-db": { 1331 | "version": "1.54.0", 1332 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 1333 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 1334 | "license": "MIT", 1335 | "engines": { 1336 | "node": ">= 0.6" 1337 | } 1338 | }, 1339 | "node_modules/express/node_modules/mime-types": { 1340 | "version": "3.0.1", 1341 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 1342 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 1343 | "license": "MIT", 1344 | "dependencies": { 1345 | "mime-db": "^1.54.0" 1346 | }, 1347 | "engines": { 1348 | "node": ">= 0.6" 1349 | } 1350 | }, 1351 | "node_modules/extend": { 1352 | "version": "3.0.2", 1353 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 1354 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", 1355 | "license": "MIT" 1356 | }, 1357 | "node_modules/finalhandler": { 1358 | "version": "2.1.0", 1359 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", 1360 | "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", 1361 | "license": "MIT", 1362 | "dependencies": { 1363 | "debug": "^4.4.0", 1364 | "encodeurl": "^2.0.0", 1365 | "escape-html": "^1.0.3", 1366 | "on-finished": "^2.4.1", 1367 | "parseurl": "^1.3.3", 1368 | "statuses": "^2.0.1" 1369 | }, 1370 | "engines": { 1371 | "node": ">= 0.8" 1372 | } 1373 | }, 1374 | "node_modules/form-data": { 1375 | "version": "4.0.2", 1376 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", 1377 | "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", 1378 | "license": "MIT", 1379 | "dependencies": { 1380 | "asynckit": "^0.4.0", 1381 | "combined-stream": "^1.0.8", 1382 | "es-set-tostringtag": "^2.1.0", 1383 | "mime-types": "^2.1.12" 1384 | }, 1385 | "engines": { 1386 | "node": ">= 6" 1387 | } 1388 | }, 1389 | "node_modules/form-data-encoder": { 1390 | "version": "1.7.2", 1391 | "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", 1392 | "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", 1393 | "license": "MIT" 1394 | }, 1395 | "node_modules/formdata-node": { 1396 | "version": "4.4.1", 1397 | "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", 1398 | "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", 1399 | "license": "MIT", 1400 | "dependencies": { 1401 | "node-domexception": "1.0.0", 1402 | "web-streams-polyfill": "4.0.0-beta.3" 1403 | }, 1404 | "engines": { 1405 | "node": ">= 12.20" 1406 | } 1407 | }, 1408 | "node_modules/formdata-node/node_modules/web-streams-polyfill": { 1409 | "version": "4.0.0-beta.3", 1410 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", 1411 | "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", 1412 | "license": "MIT", 1413 | "engines": { 1414 | "node": ">= 14" 1415 | } 1416 | }, 1417 | "node_modules/forwarded": { 1418 | "version": "0.2.0", 1419 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1420 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 1421 | "license": "MIT", 1422 | "engines": { 1423 | "node": ">= 0.6" 1424 | } 1425 | }, 1426 | "node_modules/fresh": { 1427 | "version": "2.0.0", 1428 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", 1429 | "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", 1430 | "license": "MIT", 1431 | "engines": { 1432 | "node": ">= 0.8" 1433 | } 1434 | }, 1435 | "node_modules/fsevents": { 1436 | "version": "2.3.3", 1437 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1438 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1439 | "hasInstallScript": true, 1440 | "license": "MIT", 1441 | "optional": true, 1442 | "os": [ 1443 | "darwin" 1444 | ], 1445 | "engines": { 1446 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1447 | } 1448 | }, 1449 | "node_modules/function-bind": { 1450 | "version": "1.1.2", 1451 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", 1452 | "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", 1453 | "license": "MIT", 1454 | "funding": { 1455 | "url": "https://github.com/sponsors/ljharb" 1456 | } 1457 | }, 1458 | "node_modules/gaxios": { 1459 | "version": "6.7.1", 1460 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz", 1461 | "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==", 1462 | "license": "Apache-2.0", 1463 | "dependencies": { 1464 | "extend": "^3.0.2", 1465 | "https-proxy-agent": "^7.0.1", 1466 | "is-stream": "^2.0.0", 1467 | "node-fetch": "^2.6.9", 1468 | "uuid": "^9.0.1" 1469 | }, 1470 | "engines": { 1471 | "node": ">=14" 1472 | } 1473 | }, 1474 | "node_modules/gcp-metadata": { 1475 | "version": "6.1.0", 1476 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz", 1477 | "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==", 1478 | "license": "Apache-2.0", 1479 | "dependencies": { 1480 | "gaxios": "^6.0.0", 1481 | "json-bigint": "^1.0.0" 1482 | }, 1483 | "engines": { 1484 | "node": ">=14" 1485 | } 1486 | }, 1487 | "node_modules/get-intrinsic": { 1488 | "version": "1.2.6", 1489 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", 1490 | "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", 1491 | "license": "MIT", 1492 | "dependencies": { 1493 | "call-bind-apply-helpers": "^1.0.1", 1494 | "dunder-proto": "^1.0.0", 1495 | "es-define-property": "^1.0.1", 1496 | "es-errors": "^1.3.0", 1497 | "es-object-atoms": "^1.0.0", 1498 | "function-bind": "^1.1.2", 1499 | "gopd": "^1.2.0", 1500 | "has-symbols": "^1.1.0", 1501 | "hasown": "^2.0.2", 1502 | "math-intrinsics": "^1.0.0" 1503 | }, 1504 | "engines": { 1505 | "node": ">= 0.4" 1506 | }, 1507 | "funding": { 1508 | "url": "https://github.com/sponsors/ljharb" 1509 | } 1510 | }, 1511 | "node_modules/get-tsconfig": { 1512 | "version": "4.10.0", 1513 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", 1514 | "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", 1515 | "license": "MIT", 1516 | "dependencies": { 1517 | "resolve-pkg-maps": "^1.0.0" 1518 | }, 1519 | "funding": { 1520 | "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 1521 | } 1522 | }, 1523 | "node_modules/google-auth-library": { 1524 | "version": "9.15.0", 1525 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.0.tgz", 1526 | "integrity": "sha512-7ccSEJFDFO7exFbO6NRyC+xH8/mZ1GZGG2xxx9iHxZWcjUjJpjWxIMw3cofAKcueZ6DATiukmmprD7yavQHOyQ==", 1527 | "license": "Apache-2.0", 1528 | "dependencies": { 1529 | "base64-js": "^1.3.0", 1530 | "ecdsa-sig-formatter": "^1.0.11", 1531 | "gaxios": "^6.1.1", 1532 | "gcp-metadata": "^6.1.0", 1533 | "gtoken": "^7.0.0", 1534 | "jws": "^4.0.0" 1535 | }, 1536 | "engines": { 1537 | "node": ">=14" 1538 | } 1539 | }, 1540 | "node_modules/googleapis": { 1541 | "version": "129.0.0", 1542 | "resolved": "https://registry.npmjs.org/googleapis/-/googleapis-129.0.0.tgz", 1543 | "integrity": "sha512-gFatrzby+oh/GxEeMhJOKzgs9eG7yksRcTon9b+kPie4ZnDSgGQ85JgtUaBtLSBkcKpUKukdSP6Km1aCjs4y4Q==", 1544 | "license": "Apache-2.0", 1545 | "dependencies": { 1546 | "google-auth-library": "^9.0.0", 1547 | "googleapis-common": "^7.0.0" 1548 | }, 1549 | "engines": { 1550 | "node": ">=14.0.0" 1551 | } 1552 | }, 1553 | "node_modules/googleapis-common": { 1554 | "version": "7.2.0", 1555 | "resolved": "https://registry.npmjs.org/googleapis-common/-/googleapis-common-7.2.0.tgz", 1556 | "integrity": "sha512-/fhDZEJZvOV3X5jmD+fKxMqma5q2Q9nZNSF3kn1F18tpxmA86BcTxAGBQdM0N89Z3bEaIs+HVznSmFJEAmMTjA==", 1557 | "license": "Apache-2.0", 1558 | "dependencies": { 1559 | "extend": "^3.0.2", 1560 | "gaxios": "^6.0.3", 1561 | "google-auth-library": "^9.7.0", 1562 | "qs": "^6.7.0", 1563 | "url-template": "^2.0.8", 1564 | "uuid": "^9.0.0" 1565 | }, 1566 | "engines": { 1567 | "node": ">=14.0.0" 1568 | } 1569 | }, 1570 | "node_modules/gopd": { 1571 | "version": "1.2.0", 1572 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", 1573 | "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", 1574 | "license": "MIT", 1575 | "engines": { 1576 | "node": ">= 0.4" 1577 | }, 1578 | "funding": { 1579 | "url": "https://github.com/sponsors/ljharb" 1580 | } 1581 | }, 1582 | "node_modules/gtoken": { 1583 | "version": "7.1.0", 1584 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz", 1585 | "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==", 1586 | "license": "MIT", 1587 | "dependencies": { 1588 | "gaxios": "^6.0.0", 1589 | "jws": "^4.0.0" 1590 | }, 1591 | "engines": { 1592 | "node": ">=14.0.0" 1593 | } 1594 | }, 1595 | "node_modules/has-flag": { 1596 | "version": "4.0.0", 1597 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1598 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1599 | "license": "MIT", 1600 | "engines": { 1601 | "node": ">=8" 1602 | } 1603 | }, 1604 | "node_modules/has-symbols": { 1605 | "version": "1.1.0", 1606 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", 1607 | "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", 1608 | "license": "MIT", 1609 | "engines": { 1610 | "node": ">= 0.4" 1611 | }, 1612 | "funding": { 1613 | "url": "https://github.com/sponsors/ljharb" 1614 | } 1615 | }, 1616 | "node_modules/has-tostringtag": { 1617 | "version": "1.0.2", 1618 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", 1619 | "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", 1620 | "license": "MIT", 1621 | "dependencies": { 1622 | "has-symbols": "^1.0.3" 1623 | }, 1624 | "engines": { 1625 | "node": ">= 0.4" 1626 | }, 1627 | "funding": { 1628 | "url": "https://github.com/sponsors/ljharb" 1629 | } 1630 | }, 1631 | "node_modules/hasown": { 1632 | "version": "2.0.2", 1633 | "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", 1634 | "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", 1635 | "license": "MIT", 1636 | "dependencies": { 1637 | "function-bind": "^1.1.2" 1638 | }, 1639 | "engines": { 1640 | "node": ">= 0.4" 1641 | } 1642 | }, 1643 | "node_modules/http-errors": { 1644 | "version": "2.0.0", 1645 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 1646 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 1647 | "license": "MIT", 1648 | "dependencies": { 1649 | "depd": "2.0.0", 1650 | "inherits": "2.0.4", 1651 | "setprototypeof": "1.2.0", 1652 | "statuses": "2.0.1", 1653 | "toidentifier": "1.0.1" 1654 | }, 1655 | "engines": { 1656 | "node": ">= 0.8" 1657 | } 1658 | }, 1659 | "node_modules/https-proxy-agent": { 1660 | "version": "7.0.6", 1661 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", 1662 | "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", 1663 | "license": "MIT", 1664 | "dependencies": { 1665 | "agent-base": "^7.1.2", 1666 | "debug": "4" 1667 | }, 1668 | "engines": { 1669 | "node": ">= 14" 1670 | } 1671 | }, 1672 | "node_modules/humanize-ms": { 1673 | "version": "1.2.1", 1674 | "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", 1675 | "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", 1676 | "license": "MIT", 1677 | "dependencies": { 1678 | "ms": "^2.0.0" 1679 | } 1680 | }, 1681 | "node_modules/iconv-lite": { 1682 | "version": "0.6.3", 1683 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 1684 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 1685 | "license": "MIT", 1686 | "dependencies": { 1687 | "safer-buffer": ">= 2.1.2 < 3.0.0" 1688 | }, 1689 | "engines": { 1690 | "node": ">=0.10.0" 1691 | } 1692 | }, 1693 | "node_modules/inherits": { 1694 | "version": "2.0.4", 1695 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1696 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1697 | "license": "ISC" 1698 | }, 1699 | "node_modules/ipaddr.js": { 1700 | "version": "1.9.1", 1701 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1702 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 1703 | "license": "MIT", 1704 | "engines": { 1705 | "node": ">= 0.10" 1706 | } 1707 | }, 1708 | "node_modules/is-buffer": { 1709 | "version": "1.1.6", 1710 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 1711 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", 1712 | "license": "MIT" 1713 | }, 1714 | "node_modules/is-docker": { 1715 | "version": "3.0.0", 1716 | "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", 1717 | "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", 1718 | "license": "MIT", 1719 | "bin": { 1720 | "is-docker": "cli.js" 1721 | }, 1722 | "engines": { 1723 | "node": "^12.20.0 || ^14.13.1 || >=16.0.0" 1724 | }, 1725 | "funding": { 1726 | "url": "https://github.com/sponsors/sindresorhus" 1727 | } 1728 | }, 1729 | "node_modules/is-inside-container": { 1730 | "version": "1.0.0", 1731 | "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", 1732 | "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", 1733 | "license": "MIT", 1734 | "dependencies": { 1735 | "is-docker": "^3.0.0" 1736 | }, 1737 | "bin": { 1738 | "is-inside-container": "cli.js" 1739 | }, 1740 | "engines": { 1741 | "node": ">=14.16" 1742 | }, 1743 | "funding": { 1744 | "url": "https://github.com/sponsors/sindresorhus" 1745 | } 1746 | }, 1747 | "node_modules/is-promise": { 1748 | "version": "4.0.0", 1749 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 1750 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", 1751 | "license": "MIT" 1752 | }, 1753 | "node_modules/is-stream": { 1754 | "version": "2.0.1", 1755 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", 1756 | "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", 1757 | "license": "MIT", 1758 | "engines": { 1759 | "node": ">=8" 1760 | }, 1761 | "funding": { 1762 | "url": "https://github.com/sponsors/sindresorhus" 1763 | } 1764 | }, 1765 | "node_modules/is-wsl": { 1766 | "version": "3.1.0", 1767 | "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", 1768 | "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", 1769 | "license": "MIT", 1770 | "dependencies": { 1771 | "is-inside-container": "^1.0.0" 1772 | }, 1773 | "engines": { 1774 | "node": ">=16" 1775 | }, 1776 | "funding": { 1777 | "url": "https://github.com/sponsors/sindresorhus" 1778 | } 1779 | }, 1780 | "node_modules/isexe": { 1781 | "version": "2.0.0", 1782 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1783 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1784 | "license": "ISC" 1785 | }, 1786 | "node_modules/json-bigint": { 1787 | "version": "1.0.0", 1788 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", 1789 | "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", 1790 | "license": "MIT", 1791 | "dependencies": { 1792 | "bignumber.js": "^9.0.0" 1793 | } 1794 | }, 1795 | "node_modules/json-schema": { 1796 | "version": "0.4.0", 1797 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", 1798 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", 1799 | "license": "(AFL-2.1 OR BSD-3-Clause)" 1800 | }, 1801 | "node_modules/jsondiffpatch": { 1802 | "version": "0.6.0", 1803 | "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.6.0.tgz", 1804 | "integrity": "sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ==", 1805 | "license": "MIT", 1806 | "dependencies": { 1807 | "@types/diff-match-patch": "^1.0.36", 1808 | "chalk": "^5.3.0", 1809 | "diff-match-patch": "^1.0.5" 1810 | }, 1811 | "bin": { 1812 | "jsondiffpatch": "bin/jsondiffpatch.js" 1813 | }, 1814 | "engines": { 1815 | "node": "^18.0.0 || >=20.0.0" 1816 | } 1817 | }, 1818 | "node_modules/jsondiffpatch/node_modules/chalk": { 1819 | "version": "5.4.1", 1820 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", 1821 | "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", 1822 | "license": "MIT", 1823 | "engines": { 1824 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 1825 | }, 1826 | "funding": { 1827 | "url": "https://github.com/chalk/chalk?sponsor=1" 1828 | } 1829 | }, 1830 | "node_modules/jwa": { 1831 | "version": "2.0.0", 1832 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", 1833 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", 1834 | "license": "MIT", 1835 | "dependencies": { 1836 | "buffer-equal-constant-time": "1.0.1", 1837 | "ecdsa-sig-formatter": "1.0.11", 1838 | "safe-buffer": "^5.0.1" 1839 | } 1840 | }, 1841 | "node_modules/jws": { 1842 | "version": "4.0.0", 1843 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", 1844 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", 1845 | "license": "MIT", 1846 | "dependencies": { 1847 | "jwa": "^2.0.0", 1848 | "safe-buffer": "^5.0.1" 1849 | } 1850 | }, 1851 | "node_modules/math-intrinsics": { 1852 | "version": "1.1.0", 1853 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", 1854 | "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", 1855 | "license": "MIT", 1856 | "engines": { 1857 | "node": ">= 0.4" 1858 | } 1859 | }, 1860 | "node_modules/mcp-evals": { 1861 | "version": "1.0.18", 1862 | "resolved": "https://registry.npmjs.org/mcp-evals/-/mcp-evals-1.0.18.tgz", 1863 | "integrity": "sha512-khDcEG0XWshdCRirqLXogNoDLmzFA86QyuKoi5ioXsbeRZ3XQra8Zsg7vD+C0K5vwkFIoB1vTuPjHEHMhdLFtQ==", 1864 | "license": "MIT", 1865 | "dependencies": { 1866 | "@actions/core": "^1.10.0", 1867 | "@ai-sdk/openai": "^1.3.17", 1868 | "@anthropic-ai/sdk": "^0.8.0", 1869 | "@modelcontextprotocol/sdk": "^1.10.2", 1870 | "ai": "^4.3.9", 1871 | "chalk": "^4.1.2", 1872 | "dotenv": "^16.3.1", 1873 | "openai": "^4.24.1", 1874 | "tsx": "^4.19.3" 1875 | }, 1876 | "bin": { 1877 | "mcp-eval": "dist/cli.js" 1878 | }, 1879 | "peerDependencies": { 1880 | "react": "^19.1.0" 1881 | } 1882 | }, 1883 | "node_modules/mcp-evals/node_modules/@modelcontextprotocol/sdk": { 1884 | "version": "1.11.0", 1885 | "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.0.tgz", 1886 | "integrity": "sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==", 1887 | "license": "MIT", 1888 | "dependencies": { 1889 | "content-type": "^1.0.5", 1890 | "cors": "^2.8.5", 1891 | "cross-spawn": "^7.0.3", 1892 | "eventsource": "^3.0.2", 1893 | "express": "^5.0.1", 1894 | "express-rate-limit": "^7.5.0", 1895 | "pkce-challenge": "^5.0.0", 1896 | "raw-body": "^3.0.0", 1897 | "zod": "^3.23.8", 1898 | "zod-to-json-schema": "^3.24.1" 1899 | }, 1900 | "engines": { 1901 | "node": ">=18" 1902 | } 1903 | }, 1904 | "node_modules/md5": { 1905 | "version": "2.3.0", 1906 | "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", 1907 | "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", 1908 | "license": "BSD-3-Clause", 1909 | "dependencies": { 1910 | "charenc": "0.0.2", 1911 | "crypt": "0.0.2", 1912 | "is-buffer": "~1.1.6" 1913 | } 1914 | }, 1915 | "node_modules/media-typer": { 1916 | "version": "1.1.0", 1917 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", 1918 | "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", 1919 | "license": "MIT", 1920 | "engines": { 1921 | "node": ">= 0.8" 1922 | } 1923 | }, 1924 | "node_modules/merge-descriptors": { 1925 | "version": "2.0.0", 1926 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", 1927 | "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", 1928 | "license": "MIT", 1929 | "engines": { 1930 | "node": ">=18" 1931 | }, 1932 | "funding": { 1933 | "url": "https://github.com/sponsors/sindresorhus" 1934 | } 1935 | }, 1936 | "node_modules/mime-db": { 1937 | "version": "1.52.0", 1938 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1939 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1940 | "license": "MIT", 1941 | "engines": { 1942 | "node": ">= 0.6" 1943 | } 1944 | }, 1945 | "node_modules/mime-types": { 1946 | "version": "2.1.35", 1947 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1948 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1949 | "license": "MIT", 1950 | "dependencies": { 1951 | "mime-db": "1.52.0" 1952 | }, 1953 | "engines": { 1954 | "node": ">= 0.6" 1955 | } 1956 | }, 1957 | "node_modules/ms": { 1958 | "version": "2.1.3", 1959 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1960 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1961 | "license": "MIT" 1962 | }, 1963 | "node_modules/nanoid": { 1964 | "version": "3.3.11", 1965 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", 1966 | "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", 1967 | "funding": [ 1968 | { 1969 | "type": "github", 1970 | "url": "https://github.com/sponsors/ai" 1971 | } 1972 | ], 1973 | "license": "MIT", 1974 | "bin": { 1975 | "nanoid": "bin/nanoid.cjs" 1976 | }, 1977 | "engines": { 1978 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1979 | } 1980 | }, 1981 | "node_modules/negotiator": { 1982 | "version": "1.0.0", 1983 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", 1984 | "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", 1985 | "license": "MIT", 1986 | "engines": { 1987 | "node": ">= 0.6" 1988 | } 1989 | }, 1990 | "node_modules/node-domexception": { 1991 | "version": "1.0.0", 1992 | "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", 1993 | "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 1994 | "deprecated": "Use your platform's native DOMException instead", 1995 | "funding": [ 1996 | { 1997 | "type": "github", 1998 | "url": "https://github.com/sponsors/jimmywarting" 1999 | }, 2000 | { 2001 | "type": "github", 2002 | "url": "https://paypal.me/jimmywarting" 2003 | } 2004 | ], 2005 | "license": "MIT", 2006 | "engines": { 2007 | "node": ">=10.5.0" 2008 | } 2009 | }, 2010 | "node_modules/node-fetch": { 2011 | "version": "2.7.0", 2012 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", 2013 | "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", 2014 | "license": "MIT", 2015 | "dependencies": { 2016 | "whatwg-url": "^5.0.0" 2017 | }, 2018 | "engines": { 2019 | "node": "4.x || >=6.0.0" 2020 | }, 2021 | "peerDependencies": { 2022 | "encoding": "^0.1.0" 2023 | }, 2024 | "peerDependenciesMeta": { 2025 | "encoding": { 2026 | "optional": true 2027 | } 2028 | } 2029 | }, 2030 | "node_modules/object-assign": { 2031 | "version": "4.1.1", 2032 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 2033 | "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", 2034 | "license": "MIT", 2035 | "engines": { 2036 | "node": ">=0.10.0" 2037 | } 2038 | }, 2039 | "node_modules/object-inspect": { 2040 | "version": "1.13.3", 2041 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", 2042 | "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", 2043 | "license": "MIT", 2044 | "engines": { 2045 | "node": ">= 0.4" 2046 | }, 2047 | "funding": { 2048 | "url": "https://github.com/sponsors/ljharb" 2049 | } 2050 | }, 2051 | "node_modules/on-finished": { 2052 | "version": "2.4.1", 2053 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 2054 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 2055 | "license": "MIT", 2056 | "dependencies": { 2057 | "ee-first": "1.1.1" 2058 | }, 2059 | "engines": { 2060 | "node": ">= 0.8" 2061 | } 2062 | }, 2063 | "node_modules/once": { 2064 | "version": "1.4.0", 2065 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2066 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 2067 | "license": "ISC", 2068 | "dependencies": { 2069 | "wrappy": "1" 2070 | } 2071 | }, 2072 | "node_modules/open": { 2073 | "version": "10.1.0", 2074 | "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", 2075 | "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", 2076 | "license": "MIT", 2077 | "dependencies": { 2078 | "default-browser": "^5.2.1", 2079 | "define-lazy-prop": "^3.0.0", 2080 | "is-inside-container": "^1.0.0", 2081 | "is-wsl": "^3.1.0" 2082 | }, 2083 | "engines": { 2084 | "node": ">=18" 2085 | }, 2086 | "funding": { 2087 | "url": "https://github.com/sponsors/sindresorhus" 2088 | } 2089 | }, 2090 | "node_modules/openai": { 2091 | "version": "4.96.2", 2092 | "resolved": "https://registry.npmjs.org/openai/-/openai-4.96.2.tgz", 2093 | "integrity": "sha512-R2XnxvMsizkROr7BV3uNp1q/3skwPZ7fmPjO1bXLnfB4Tu5xKxrT1EVwzjhxn0MZKBKAvOaGWS63jTMN6KrIXA==", 2094 | "license": "Apache-2.0", 2095 | "dependencies": { 2096 | "@types/node": "^18.11.18", 2097 | "@types/node-fetch": "^2.6.4", 2098 | "abort-controller": "^3.0.0", 2099 | "agentkeepalive": "^4.2.1", 2100 | "form-data-encoder": "1.7.2", 2101 | "formdata-node": "^4.3.2", 2102 | "node-fetch": "^2.6.7" 2103 | }, 2104 | "bin": { 2105 | "openai": "bin/cli" 2106 | }, 2107 | "peerDependencies": { 2108 | "ws": "^8.18.0", 2109 | "zod": "^3.23.8" 2110 | }, 2111 | "peerDependenciesMeta": { 2112 | "ws": { 2113 | "optional": true 2114 | }, 2115 | "zod": { 2116 | "optional": true 2117 | } 2118 | } 2119 | }, 2120 | "node_modules/openai/node_modules/@types/node": { 2121 | "version": "18.19.87", 2122 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.87.tgz", 2123 | "integrity": "sha512-OIAAu6ypnVZHmsHCeJ+7CCSub38QNBS9uceMQeg7K5Ur0Jr+wG9wEOEvvMbhp09pxD5czIUy/jND7s7Tb6Nw7A==", 2124 | "license": "MIT", 2125 | "dependencies": { 2126 | "undici-types": "~5.26.4" 2127 | } 2128 | }, 2129 | "node_modules/openai/node_modules/undici-types": { 2130 | "version": "5.26.5", 2131 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 2132 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 2133 | "license": "MIT" 2134 | }, 2135 | "node_modules/parseurl": { 2136 | "version": "1.3.3", 2137 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 2138 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 2139 | "license": "MIT", 2140 | "engines": { 2141 | "node": ">= 0.8" 2142 | } 2143 | }, 2144 | "node_modules/path-key": { 2145 | "version": "3.1.1", 2146 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2147 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2148 | "license": "MIT", 2149 | "engines": { 2150 | "node": ">=8" 2151 | } 2152 | }, 2153 | "node_modules/path-to-regexp": { 2154 | "version": "8.2.0", 2155 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", 2156 | "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", 2157 | "license": "MIT", 2158 | "engines": { 2159 | "node": ">=16" 2160 | } 2161 | }, 2162 | "node_modules/pkce-challenge": { 2163 | "version": "5.0.0", 2164 | "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", 2165 | "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", 2166 | "license": "MIT", 2167 | "engines": { 2168 | "node": ">=16.20.0" 2169 | } 2170 | }, 2171 | "node_modules/proxy-addr": { 2172 | "version": "2.0.7", 2173 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 2174 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 2175 | "license": "MIT", 2176 | "dependencies": { 2177 | "forwarded": "0.2.0", 2178 | "ipaddr.js": "1.9.1" 2179 | }, 2180 | "engines": { 2181 | "node": ">= 0.10" 2182 | } 2183 | }, 2184 | "node_modules/qs": { 2185 | "version": "6.14.0", 2186 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", 2187 | "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", 2188 | "license": "BSD-3-Clause", 2189 | "dependencies": { 2190 | "side-channel": "^1.1.0" 2191 | }, 2192 | "engines": { 2193 | "node": ">=0.6" 2194 | }, 2195 | "funding": { 2196 | "url": "https://github.com/sponsors/ljharb" 2197 | } 2198 | }, 2199 | "node_modules/range-parser": { 2200 | "version": "1.2.1", 2201 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 2202 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 2203 | "license": "MIT", 2204 | "engines": { 2205 | "node": ">= 0.6" 2206 | } 2207 | }, 2208 | "node_modules/raw-body": { 2209 | "version": "3.0.0", 2210 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", 2211 | "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", 2212 | "license": "MIT", 2213 | "dependencies": { 2214 | "bytes": "3.1.2", 2215 | "http-errors": "2.0.0", 2216 | "iconv-lite": "0.6.3", 2217 | "unpipe": "1.0.0" 2218 | }, 2219 | "engines": { 2220 | "node": ">= 0.8" 2221 | } 2222 | }, 2223 | "node_modules/react": { 2224 | "version": "19.1.0", 2225 | "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", 2226 | "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", 2227 | "license": "MIT", 2228 | "peer": true, 2229 | "engines": { 2230 | "node": ">=0.10.0" 2231 | } 2232 | }, 2233 | "node_modules/resolve-pkg-maps": { 2234 | "version": "1.0.0", 2235 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", 2236 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", 2237 | "license": "MIT", 2238 | "funding": { 2239 | "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" 2240 | } 2241 | }, 2242 | "node_modules/router": { 2243 | "version": "2.2.0", 2244 | "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", 2245 | "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", 2246 | "license": "MIT", 2247 | "dependencies": { 2248 | "debug": "^4.4.0", 2249 | "depd": "^2.0.0", 2250 | "is-promise": "^4.0.0", 2251 | "parseurl": "^1.3.3", 2252 | "path-to-regexp": "^8.0.0" 2253 | }, 2254 | "engines": { 2255 | "node": ">= 18" 2256 | } 2257 | }, 2258 | "node_modules/run-applescript": { 2259 | "version": "7.0.0", 2260 | "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", 2261 | "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", 2262 | "license": "MIT", 2263 | "engines": { 2264 | "node": ">=18" 2265 | }, 2266 | "funding": { 2267 | "url": "https://github.com/sponsors/sindresorhus" 2268 | } 2269 | }, 2270 | "node_modules/safe-buffer": { 2271 | "version": "5.2.1", 2272 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2273 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2274 | "funding": [ 2275 | { 2276 | "type": "github", 2277 | "url": "https://github.com/sponsors/feross" 2278 | }, 2279 | { 2280 | "type": "patreon", 2281 | "url": "https://www.patreon.com/feross" 2282 | }, 2283 | { 2284 | "type": "consulting", 2285 | "url": "https://feross.org/support" 2286 | } 2287 | ], 2288 | "license": "MIT" 2289 | }, 2290 | "node_modules/safer-buffer": { 2291 | "version": "2.1.2", 2292 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2293 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 2294 | "license": "MIT" 2295 | }, 2296 | "node_modules/secure-json-parse": { 2297 | "version": "2.7.0", 2298 | "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", 2299 | "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", 2300 | "license": "BSD-3-Clause" 2301 | }, 2302 | "node_modules/send": { 2303 | "version": "1.2.0", 2304 | "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", 2305 | "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", 2306 | "license": "MIT", 2307 | "dependencies": { 2308 | "debug": "^4.3.5", 2309 | "encodeurl": "^2.0.0", 2310 | "escape-html": "^1.0.3", 2311 | "etag": "^1.8.1", 2312 | "fresh": "^2.0.0", 2313 | "http-errors": "^2.0.0", 2314 | "mime-types": "^3.0.1", 2315 | "ms": "^2.1.3", 2316 | "on-finished": "^2.4.1", 2317 | "range-parser": "^1.2.1", 2318 | "statuses": "^2.0.1" 2319 | }, 2320 | "engines": { 2321 | "node": ">= 18" 2322 | } 2323 | }, 2324 | "node_modules/send/node_modules/mime-db": { 2325 | "version": "1.54.0", 2326 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 2327 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 2328 | "license": "MIT", 2329 | "engines": { 2330 | "node": ">= 0.6" 2331 | } 2332 | }, 2333 | "node_modules/send/node_modules/mime-types": { 2334 | "version": "3.0.1", 2335 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 2336 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 2337 | "license": "MIT", 2338 | "dependencies": { 2339 | "mime-db": "^1.54.0" 2340 | }, 2341 | "engines": { 2342 | "node": ">= 0.6" 2343 | } 2344 | }, 2345 | "node_modules/serve-static": { 2346 | "version": "2.2.0", 2347 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", 2348 | "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", 2349 | "license": "MIT", 2350 | "dependencies": { 2351 | "encodeurl": "^2.0.0", 2352 | "escape-html": "^1.0.3", 2353 | "parseurl": "^1.3.3", 2354 | "send": "^1.2.0" 2355 | }, 2356 | "engines": { 2357 | "node": ">= 18" 2358 | } 2359 | }, 2360 | "node_modules/setprototypeof": { 2361 | "version": "1.2.0", 2362 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 2363 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", 2364 | "license": "ISC" 2365 | }, 2366 | "node_modules/shebang-command": { 2367 | "version": "2.0.0", 2368 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2369 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2370 | "license": "MIT", 2371 | "dependencies": { 2372 | "shebang-regex": "^3.0.0" 2373 | }, 2374 | "engines": { 2375 | "node": ">=8" 2376 | } 2377 | }, 2378 | "node_modules/shebang-regex": { 2379 | "version": "3.0.0", 2380 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2381 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2382 | "license": "MIT", 2383 | "engines": { 2384 | "node": ">=8" 2385 | } 2386 | }, 2387 | "node_modules/side-channel": { 2388 | "version": "1.1.0", 2389 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", 2390 | "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", 2391 | "license": "MIT", 2392 | "dependencies": { 2393 | "es-errors": "^1.3.0", 2394 | "object-inspect": "^1.13.3", 2395 | "side-channel-list": "^1.0.0", 2396 | "side-channel-map": "^1.0.1", 2397 | "side-channel-weakmap": "^1.0.2" 2398 | }, 2399 | "engines": { 2400 | "node": ">= 0.4" 2401 | }, 2402 | "funding": { 2403 | "url": "https://github.com/sponsors/ljharb" 2404 | } 2405 | }, 2406 | "node_modules/side-channel-list": { 2407 | "version": "1.0.0", 2408 | "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", 2409 | "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", 2410 | "license": "MIT", 2411 | "dependencies": { 2412 | "es-errors": "^1.3.0", 2413 | "object-inspect": "^1.13.3" 2414 | }, 2415 | "engines": { 2416 | "node": ">= 0.4" 2417 | }, 2418 | "funding": { 2419 | "url": "https://github.com/sponsors/ljharb" 2420 | } 2421 | }, 2422 | "node_modules/side-channel-map": { 2423 | "version": "1.0.1", 2424 | "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", 2425 | "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", 2426 | "license": "MIT", 2427 | "dependencies": { 2428 | "call-bound": "^1.0.2", 2429 | "es-errors": "^1.3.0", 2430 | "get-intrinsic": "^1.2.5", 2431 | "object-inspect": "^1.13.3" 2432 | }, 2433 | "engines": { 2434 | "node": ">= 0.4" 2435 | }, 2436 | "funding": { 2437 | "url": "https://github.com/sponsors/ljharb" 2438 | } 2439 | }, 2440 | "node_modules/side-channel-weakmap": { 2441 | "version": "1.0.2", 2442 | "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", 2443 | "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", 2444 | "license": "MIT", 2445 | "dependencies": { 2446 | "call-bound": "^1.0.2", 2447 | "es-errors": "^1.3.0", 2448 | "get-intrinsic": "^1.2.5", 2449 | "object-inspect": "^1.13.3", 2450 | "side-channel-map": "^1.0.1" 2451 | }, 2452 | "engines": { 2453 | "node": ">= 0.4" 2454 | }, 2455 | "funding": { 2456 | "url": "https://github.com/sponsors/ljharb" 2457 | } 2458 | }, 2459 | "node_modules/statuses": { 2460 | "version": "2.0.1", 2461 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 2462 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", 2463 | "license": "MIT", 2464 | "engines": { 2465 | "node": ">= 0.8" 2466 | } 2467 | }, 2468 | "node_modules/supports-color": { 2469 | "version": "7.2.0", 2470 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2471 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2472 | "license": "MIT", 2473 | "dependencies": { 2474 | "has-flag": "^4.0.0" 2475 | }, 2476 | "engines": { 2477 | "node": ">=8" 2478 | } 2479 | }, 2480 | "node_modules/swr": { 2481 | "version": "2.3.3", 2482 | "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.3.tgz", 2483 | "integrity": "sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==", 2484 | "license": "MIT", 2485 | "dependencies": { 2486 | "dequal": "^2.0.3", 2487 | "use-sync-external-store": "^1.4.0" 2488 | }, 2489 | "peerDependencies": { 2490 | "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2491 | } 2492 | }, 2493 | "node_modules/throttleit": { 2494 | "version": "2.1.0", 2495 | "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-2.1.0.tgz", 2496 | "integrity": "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw==", 2497 | "license": "MIT", 2498 | "engines": { 2499 | "node": ">=18" 2500 | }, 2501 | "funding": { 2502 | "url": "https://github.com/sponsors/sindresorhus" 2503 | } 2504 | }, 2505 | "node_modules/toidentifier": { 2506 | "version": "1.0.1", 2507 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 2508 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 2509 | "license": "MIT", 2510 | "engines": { 2511 | "node": ">=0.6" 2512 | } 2513 | }, 2514 | "node_modules/tr46": { 2515 | "version": "0.0.3", 2516 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 2517 | "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", 2518 | "license": "MIT" 2519 | }, 2520 | "node_modules/tsx": { 2521 | "version": "4.19.4", 2522 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.4.tgz", 2523 | "integrity": "sha512-gK5GVzDkJK1SI1zwHf32Mqxf2tSJkNx+eYcNly5+nHvWqXUJYUkWBQtKauoESz3ymezAI++ZwT855x5p5eop+Q==", 2524 | "license": "MIT", 2525 | "dependencies": { 2526 | "esbuild": "~0.25.0", 2527 | "get-tsconfig": "^4.7.5" 2528 | }, 2529 | "bin": { 2530 | "tsx": "dist/cli.mjs" 2531 | }, 2532 | "engines": { 2533 | "node": ">=18.0.0" 2534 | }, 2535 | "optionalDependencies": { 2536 | "fsevents": "~2.3.3" 2537 | } 2538 | }, 2539 | "node_modules/tunnel": { 2540 | "version": "0.0.6", 2541 | "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", 2542 | "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", 2543 | "license": "MIT", 2544 | "engines": { 2545 | "node": ">=0.6.11 <=0.7.0 || >=0.7.3" 2546 | } 2547 | }, 2548 | "node_modules/type-is": { 2549 | "version": "2.0.1", 2550 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", 2551 | "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", 2552 | "license": "MIT", 2553 | "dependencies": { 2554 | "content-type": "^1.0.5", 2555 | "media-typer": "^1.1.0", 2556 | "mime-types": "^3.0.0" 2557 | }, 2558 | "engines": { 2559 | "node": ">= 0.6" 2560 | } 2561 | }, 2562 | "node_modules/type-is/node_modules/mime-db": { 2563 | "version": "1.54.0", 2564 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", 2565 | "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", 2566 | "license": "MIT", 2567 | "engines": { 2568 | "node": ">= 0.6" 2569 | } 2570 | }, 2571 | "node_modules/type-is/node_modules/mime-types": { 2572 | "version": "3.0.1", 2573 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", 2574 | "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", 2575 | "license": "MIT", 2576 | "dependencies": { 2577 | "mime-db": "^1.54.0" 2578 | }, 2579 | "engines": { 2580 | "node": ">= 0.6" 2581 | } 2582 | }, 2583 | "node_modules/typescript": { 2584 | "version": "5.7.2", 2585 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", 2586 | "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", 2587 | "dev": true, 2588 | "license": "Apache-2.0", 2589 | "bin": { 2590 | "tsc": "bin/tsc", 2591 | "tsserver": "bin/tsserver" 2592 | }, 2593 | "engines": { 2594 | "node": ">=14.17" 2595 | } 2596 | }, 2597 | "node_modules/undici": { 2598 | "version": "5.29.0", 2599 | "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", 2600 | "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", 2601 | "license": "MIT", 2602 | "dependencies": { 2603 | "@fastify/busboy": "^2.0.0" 2604 | }, 2605 | "engines": { 2606 | "node": ">=14.0" 2607 | } 2608 | }, 2609 | "node_modules/undici-types": { 2610 | "version": "6.19.8", 2611 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", 2612 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", 2613 | "license": "MIT" 2614 | }, 2615 | "node_modules/unpipe": { 2616 | "version": "1.0.0", 2617 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2618 | "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", 2619 | "license": "MIT", 2620 | "engines": { 2621 | "node": ">= 0.8" 2622 | } 2623 | }, 2624 | "node_modules/url-template": { 2625 | "version": "2.0.8", 2626 | "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", 2627 | "integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==", 2628 | "license": "BSD" 2629 | }, 2630 | "node_modules/use-sync-external-store": { 2631 | "version": "1.5.0", 2632 | "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", 2633 | "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", 2634 | "license": "MIT", 2635 | "peerDependencies": { 2636 | "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" 2637 | } 2638 | }, 2639 | "node_modules/uuid": { 2640 | "version": "9.0.1", 2641 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", 2642 | "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", 2643 | "funding": [ 2644 | "https://github.com/sponsors/broofa", 2645 | "https://github.com/sponsors/ctavan" 2646 | ], 2647 | "license": "MIT", 2648 | "bin": { 2649 | "uuid": "dist/bin/uuid" 2650 | } 2651 | }, 2652 | "node_modules/vary": { 2653 | "version": "1.1.2", 2654 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 2655 | "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", 2656 | "license": "MIT", 2657 | "engines": { 2658 | "node": ">= 0.8" 2659 | } 2660 | }, 2661 | "node_modules/web-streams-polyfill": { 2662 | "version": "3.3.3", 2663 | "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", 2664 | "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", 2665 | "license": "MIT", 2666 | "engines": { 2667 | "node": ">= 8" 2668 | } 2669 | }, 2670 | "node_modules/webidl-conversions": { 2671 | "version": "3.0.1", 2672 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 2673 | "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", 2674 | "license": "BSD-2-Clause" 2675 | }, 2676 | "node_modules/whatwg-url": { 2677 | "version": "5.0.0", 2678 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 2679 | "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", 2680 | "license": "MIT", 2681 | "dependencies": { 2682 | "tr46": "~0.0.3", 2683 | "webidl-conversions": "^3.0.0" 2684 | } 2685 | }, 2686 | "node_modules/which": { 2687 | "version": "2.0.2", 2688 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2689 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2690 | "license": "ISC", 2691 | "dependencies": { 2692 | "isexe": "^2.0.0" 2693 | }, 2694 | "bin": { 2695 | "node-which": "bin/node-which" 2696 | }, 2697 | "engines": { 2698 | "node": ">= 8" 2699 | } 2700 | }, 2701 | "node_modules/wrappy": { 2702 | "version": "1.0.2", 2703 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2704 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 2705 | "license": "ISC" 2706 | }, 2707 | "node_modules/zod": { 2708 | "version": "3.24.1", 2709 | "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", 2710 | "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", 2711 | "license": "MIT", 2712 | "funding": { 2713 | "url": "https://github.com/sponsors/colinhacks" 2714 | } 2715 | }, 2716 | "node_modules/zod-to-json-schema": { 2717 | "version": "3.24.1", 2718 | "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.1.tgz", 2719 | "integrity": "sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==", 2720 | "license": "ISC", 2721 | "peerDependencies": { 2722 | "zod": "^3.24.1" 2723 | } 2724 | } 2725 | } 2726 | } 2727 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@gongrzhe/server-gmail-autoauth-mcp", 3 | "version": "1.1.9", 4 | "description": "Gmail MCP server with auto authentication support", 5 | "type": "module", 6 | "main": "dist/index.js", 7 | "bin": { 8 | "gmail-mcp": "./dist/index.js" 9 | }, 10 | "scripts": { 11 | "build": "tsc", 12 | "start": "node dist/index.js", 13 | "auth": "node dist/index.js auth", 14 | "prepare": "npm run build", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "files": [ 18 | "dist", 19 | "README.md" 20 | ], 21 | "keywords": [ 22 | "gmail", 23 | "mcp", 24 | "cursor", 25 | "ai", 26 | "oauth", 27 | "model-context-protocol", 28 | "google-gmail", 29 | "claude", 30 | "auto-auth" 31 | ], 32 | "author": "gongrzhe", 33 | "license": "ISC", 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/gongrzhe/server-gmail-autoauth-mcp.git" 37 | }, 38 | "bugs": { 39 | "url": "https://github.com/gongrzhe/server-gmail-autoauth-mcp/issues" 40 | }, 41 | "homepage": "https://github.com/gongrzhe/server-gmail-autoauth-mcp#readme", 42 | "publishConfig": { 43 | "access": "public" 44 | }, 45 | "engines": { 46 | "node": ">=14.0.0" 47 | }, 48 | "dependencies": { 49 | "@modelcontextprotocol/sdk": "^0.4.0", 50 | "google-auth-library": "^9.4.1", 51 | "googleapis": "^129.0.0", 52 | "mcp-evals": "^1.0.18", 53 | "open": "^10.0.0", 54 | "zod": "^3.22.4", 55 | "zod-to-json-schema": "^3.22.1" 56 | }, 57 | "devDependencies": { 58 | "@types/node": "^20.10.5", 59 | "typescript": "^5.3.3" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /setup.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Basic debugging script 4 | console.log('====== Starting Setup Script ======'); 5 | 6 | try { 7 | // ES module imports 8 | console.log('Importing modules...'); 9 | import('fs').then(fs => { 10 | console.log('Successfully imported fs module'); 11 | 12 | import('path').then(path => { 13 | console.log('Successfully imported path module'); 14 | 15 | import('os').then(os => { 16 | console.log('Successfully imported os module'); 17 | 18 | import('child_process').then(({ execSync }) => { 19 | console.log('Successfully imported child_process module'); 20 | 21 | import('url').then(({ fileURLToPath }) => { 22 | console.log('Successfully imported url module'); 23 | 24 | // Get directory path 25 | const __filename = fileURLToPath(import.meta.url); 26 | const __dirname = path.dirname(__filename); 27 | console.log(`Current directory: ${__dirname}`); 28 | 29 | // Check Node.js version 30 | const nodeVersion = process.versions.node.split('.'); 31 | console.log(`Node.js version: ${process.versions.node}`); 32 | 33 | // Project path 34 | const basePath = path.resolve(__dirname); 35 | console.log(`Project path: ${basePath}`); 36 | 37 | // Create configuration 38 | console.log('Starting to create MCP configuration...'); 39 | const serverScriptPath = path.join(basePath, 'dist', 'index.js'); 40 | console.log(`Server script path: ${serverScriptPath}`); 41 | 42 | // Create configuration directory 43 | const configDir = path.join(os.homedir(), '.gmail-mcp'); 44 | console.log(`Configuration directory: ${configDir}`); 45 | 46 | if (!fs.existsSync(configDir)) { 47 | console.log('Creating configuration directory...'); 48 | fs.mkdirSync(configDir, { recursive: true }); 49 | console.log('Configuration directory created successfully'); 50 | } else { 51 | console.log('Configuration directory already exists'); 52 | } 53 | 54 | // Create MCP configuration 55 | const config = { 56 | "mcpServers": { 57 | "gmail": { 58 | "command": "node", 59 | "args": [serverScriptPath] 60 | } 61 | } 62 | }; 63 | 64 | // Save configuration 65 | const configPath = path.join(basePath, 'mcp-config.json'); 66 | console.log(`Saving configuration to: ${configPath}`); 67 | fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); 68 | console.log('Configuration saved'); 69 | 70 | // Get Claude Desktop configuration path 71 | let claudeConfigPath; 72 | if (process.platform === 'win32') { 73 | claudeConfigPath = path.join(process.env.APPDATA, 'Claude', 'claude_desktop_config.json'); 74 | } else if (process.platform === 'darwin') { 75 | claudeConfigPath = path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'); 76 | } else { 77 | claudeConfigPath = path.join(os.homedir(), '.config', 'Claude', 'claude_desktop_config.json'); 78 | } 79 | 80 | console.log(`Claude Desktop configuration path: ${claudeConfigPath}`); 81 | 82 | // Output instructions 83 | console.log('\n===== Setup Complete ====='); 84 | console.log(`MCP configuration written to: ${configPath}`); 85 | console.log('\nMCP configuration content:'); 86 | console.log(JSON.stringify(config, null, 2)); 87 | console.log(`\nPlease merge this configuration into the Claude Desktop configuration file: ${claudeConfigPath}`); 88 | console.log('\nBefore using the Gmail MCP server, you need to authenticate:'); 89 | console.log(`node ${serverScriptPath} auth`); 90 | 91 | console.log('\nSetup complete! You can now use the Gmail MCP server with compatible clients.'); 92 | }).catch(err => { 93 | console.error('Error importing url module:', err); 94 | }); 95 | }).catch(err => { 96 | console.error('Error importing child_process module:', err); 97 | }); 98 | }).catch(err => { 99 | console.error('Error importing os module:', err); 100 | }); 101 | }).catch(err => { 102 | console.error('Error importing path module:', err); 103 | }); 104 | }).catch(err => { 105 | console.error('Error importing fs module:', err); 106 | }); 107 | } catch (error) { 108 | console.error('Error executing script:', error); 109 | } 110 | -------------------------------------------------------------------------------- /smithery.yaml: -------------------------------------------------------------------------------- 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml 2 | 3 | startCommand: 4 | type: stdio 5 | configSchema: 6 | # JSON Schema defining the configuration options for the MCP. 7 | type: object 8 | required: 9 | - gcpOauthKeysPath 10 | - credentialsPath 11 | properties: 12 | gcpOauthKeysPath: 13 | type: string 14 | description: Path to the GCP OAuth keys JSON file 15 | credentialsPath: 16 | type: string 17 | description: Path to the stored credentials JSON file 18 | commandFunction: 19 | # A function that produces the CLI command to start the MCP on stdio. 20 | |- 21 | (config) => ({command:'node',args:['dist/index.js'],env:{GMAIL_OAUTH_PATH:config.gcpOauthKeysPath, GMAIL_CREDENTIALS_PATH:config.credentialsPath}}) -------------------------------------------------------------------------------- /src/evals/evals.ts: -------------------------------------------------------------------------------- 1 | //evals.ts 2 | 3 | import { EvalConfig } from 'mcp-evals'; 4 | import { openai } from "@ai-sdk/openai"; 5 | import { grade, EvalFunction } from "mcp-evals"; 6 | 7 | const send_emailEval: EvalFunction = { 8 | name: "send_emailEval", 9 | description: "Evaluates sending a new email", 10 | run: async () => { 11 | const result = await grade(openai("gpt-4"), "Please send an email to example@domain.com with the subject 'Meeting Reminder' and a short message confirming our meeting tomorrow, politely requesting confirmation of attendance."); 12 | return JSON.parse(result); 13 | } 14 | }; 15 | 16 | const draft_email: EvalFunction = { 17 | name: 'draft_email', 18 | description: 'Evaluates the tool’s ability to draft an email', 19 | run: async () => { 20 | const result = await grade(openai("gpt-4"), "Draft a new email to my manager requesting a meeting to discuss project updates and timelines."); 21 | return JSON.parse(result); 22 | } 23 | }; 24 | 25 | const read_emailEval: EvalFunction = { 26 | name: 'read_email Tool Evaluation', 27 | description: 'Evaluates retrieving the content of a specific email', 28 | run: async () => { 29 | const result = await grade(openai("gpt-4"), "Please retrieve the content of the email with the subject 'Upcoming Meeting' from my inbox."); 30 | return JSON.parse(result); 31 | } 32 | }; 33 | 34 | const search_emailsEval: EvalFunction = { 35 | name: "search_emails Tool Evaluation", 36 | description: "Evaluates the tool's ability to search emails using Gmail syntax", 37 | run: async () => { 38 | const result = await grade(openai("gpt-4"), "Search my mailbox for unread emails from boss@company.com that have attachments. Provide the Gmail search syntax."); 39 | return JSON.parse(result); 40 | } 41 | }; 42 | 43 | const modify_emailEval: EvalFunction = { 44 | name: 'modify_email Tool Evaluation', 45 | description: 'Evaluates the modify_email tool functionality', 46 | run: async () => { 47 | const result = await grade(openai("gpt-4"), "Please move the email labeled 'Work' to the 'Important' folder and remove the 'unread' label."); 48 | return JSON.parse(result); 49 | } 50 | }; 51 | 52 | const config: EvalConfig = { 53 | model: openai("gpt-4"), 54 | evals: [send_emailEval, draft_email, read_emailEval, search_emailsEval, modify_emailEval] 55 | }; 56 | 57 | export default config; 58 | 59 | export const evals = [send_emailEval, draft_email, read_emailEval, search_emailsEval, modify_emailEval]; -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { Server } from "@modelcontextprotocol/sdk/server/index.js"; 4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; 5 | import { 6 | CallToolRequestSchema, 7 | ListToolsRequestSchema, 8 | } from "@modelcontextprotocol/sdk/types.js"; 9 | import { google } from 'googleapis'; 10 | import { z } from "zod"; 11 | import { zodToJsonSchema } from "zod-to-json-schema"; 12 | import { OAuth2Client } from 'google-auth-library'; 13 | import fs from 'fs'; 14 | import path from 'path'; 15 | import { fileURLToPath } from 'url'; 16 | import http from 'http'; 17 | import open from 'open'; 18 | import os from 'os'; 19 | import {createEmailMessage} from "./utl.js"; 20 | import { createLabel, updateLabel, deleteLabel, listLabels, findLabelByName, getOrCreateLabel, GmailLabel } from "./label-manager.js"; 21 | 22 | const __dirname = path.dirname(fileURLToPath(import.meta.url)); 23 | 24 | // Configuration paths 25 | const CONFIG_DIR = path.join(os.homedir(), '.gmail-mcp'); 26 | const OAUTH_PATH = process.env.GMAIL_OAUTH_PATH || path.join(CONFIG_DIR, 'gcp-oauth.keys.json'); 27 | const CREDENTIALS_PATH = process.env.GMAIL_CREDENTIALS_PATH || path.join(CONFIG_DIR, 'credentials.json'); 28 | 29 | // Type definitions for Gmail API responses 30 | interface GmailMessagePart { 31 | partId?: string; 32 | mimeType?: string; 33 | filename?: string; 34 | headers?: Array<{ 35 | name: string; 36 | value: string; 37 | }>; 38 | body?: { 39 | attachmentId?: string; 40 | size?: number; 41 | data?: string; 42 | }; 43 | parts?: GmailMessagePart[]; 44 | } 45 | 46 | interface EmailAttachment { 47 | id: string; 48 | filename: string; 49 | mimeType: string; 50 | size: number; 51 | } 52 | 53 | interface EmailContent { 54 | text: string; 55 | html: string; 56 | } 57 | 58 | // OAuth2 configuration 59 | let oauth2Client: OAuth2Client; 60 | 61 | /** 62 | * Recursively extract email body content from MIME message parts 63 | * Handles complex email structures with nested parts 64 | */ 65 | function extractEmailContent(messagePart: GmailMessagePart): EmailContent { 66 | // Initialize containers for different content types 67 | let textContent = ''; 68 | let htmlContent = ''; 69 | 70 | // If the part has a body with data, process it based on MIME type 71 | if (messagePart.body && messagePart.body.data) { 72 | const content = Buffer.from(messagePart.body.data, 'base64').toString('utf8'); 73 | 74 | // Store content based on its MIME type 75 | if (messagePart.mimeType === 'text/plain') { 76 | textContent = content; 77 | } else if (messagePart.mimeType === 'text/html') { 78 | htmlContent = content; 79 | } 80 | } 81 | 82 | // If the part has nested parts, recursively process them 83 | if (messagePart.parts && messagePart.parts.length > 0) { 84 | for (const part of messagePart.parts) { 85 | const { text, html } = extractEmailContent(part); 86 | if (text) textContent += text; 87 | if (html) htmlContent += html; 88 | } 89 | } 90 | 91 | // Return both plain text and HTML content 92 | return { text: textContent, html: htmlContent }; 93 | } 94 | 95 | async function loadCredentials() { 96 | try { 97 | // Create config directory if it doesn't exist 98 | if (!process.env.GMAIL_OAUTH_PATH && !CREDENTIALS_PATH &&!fs.existsSync(CONFIG_DIR)) { 99 | fs.mkdirSync(CONFIG_DIR, { recursive: true }); 100 | } 101 | 102 | // Check for OAuth keys in current directory first, then in config directory 103 | const localOAuthPath = path.join(process.cwd(), 'gcp-oauth.keys.json'); 104 | let oauthPath = OAUTH_PATH; 105 | 106 | if (fs.existsSync(localOAuthPath)) { 107 | // If found in current directory, copy to config directory 108 | fs.copyFileSync(localOAuthPath, OAUTH_PATH); 109 | console.log('OAuth keys found in current directory, copied to global config.'); 110 | } 111 | 112 | if (!fs.existsSync(OAUTH_PATH)) { 113 | console.error('Error: OAuth keys file not found. Please place gcp-oauth.keys.json in current directory or', CONFIG_DIR); 114 | process.exit(1); 115 | } 116 | 117 | const keysContent = JSON.parse(fs.readFileSync(OAUTH_PATH, 'utf8')); 118 | const keys = keysContent.installed || keysContent.web; 119 | 120 | if (!keys) { 121 | console.error('Error: Invalid OAuth keys file format. File should contain either "installed" or "web" credentials.'); 122 | process.exit(1); 123 | } 124 | 125 | const callback = process.argv[2] === 'auth' && process.argv[3] 126 | ? process.argv[3] 127 | : "http://localhost:3000/oauth2callback"; 128 | 129 | oauth2Client = new OAuth2Client( 130 | keys.client_id, 131 | keys.client_secret, 132 | callback 133 | ); 134 | 135 | if (fs.existsSync(CREDENTIALS_PATH)) { 136 | const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8')); 137 | oauth2Client.setCredentials(credentials); 138 | } 139 | } catch (error) { 140 | console.error('Error loading credentials:', error); 141 | process.exit(1); 142 | } 143 | } 144 | 145 | async function authenticate() { 146 | const server = http.createServer(); 147 | server.listen(3000); 148 | 149 | return new Promise((resolve, reject) => { 150 | const authUrl = oauth2Client.generateAuthUrl({ 151 | access_type: 'offline', 152 | scope: ['https://www.googleapis.com/auth/gmail.modify'], 153 | }); 154 | 155 | console.log('Please visit this URL to authenticate:', authUrl); 156 | open(authUrl); 157 | 158 | server.on('request', async (req, res) => { 159 | if (!req.url?.startsWith('/oauth2callback')) return; 160 | 161 | const url = new URL(req.url, 'http://localhost:3000'); 162 | const code = url.searchParams.get('code'); 163 | 164 | if (!code) { 165 | res.writeHead(400); 166 | res.end('No code provided'); 167 | reject(new Error('No code provided')); 168 | return; 169 | } 170 | 171 | try { 172 | const { tokens } = await oauth2Client.getToken(code); 173 | oauth2Client.setCredentials(tokens); 174 | fs.writeFileSync(CREDENTIALS_PATH, JSON.stringify(tokens)); 175 | 176 | res.writeHead(200); 177 | res.end('Authentication successful! You can close this window.'); 178 | server.close(); 179 | resolve(); 180 | } catch (error) { 181 | res.writeHead(500); 182 | res.end('Authentication failed'); 183 | reject(error); 184 | } 185 | }); 186 | }); 187 | } 188 | 189 | // Schema definitions 190 | const SendEmailSchema = z.object({ 191 | to: z.array(z.string()).describe("List of recipient email addresses"), 192 | subject: z.string().describe("Email subject"), 193 | body: z.string().describe("Email body content (used for text/plain or when htmlBody not provided)"), 194 | htmlBody: z.string().optional().describe("HTML version of the email body"), 195 | mimeType: z.enum(['text/plain', 'text/html', 'multipart/alternative']).optional().default('text/plain').describe("Email content type"), 196 | cc: z.array(z.string()).optional().describe("List of CC recipients"), 197 | bcc: z.array(z.string()).optional().describe("List of BCC recipients"), 198 | threadId: z.string().optional().describe("Thread ID to reply to"), 199 | inReplyTo: z.string().optional().describe("Message ID being replied to"), 200 | }); 201 | 202 | const ReadEmailSchema = z.object({ 203 | messageId: z.string().describe("ID of the email message to retrieve"), 204 | }); 205 | 206 | const SearchEmailsSchema = z.object({ 207 | query: z.string().describe("Gmail search query (e.g., 'from:example@gmail.com')"), 208 | maxResults: z.number().optional().describe("Maximum number of results to return"), 209 | }); 210 | 211 | // Updated schema to include removeLabelIds 212 | const ModifyEmailSchema = z.object({ 213 | messageId: z.string().describe("ID of the email message to modify"), 214 | labelIds: z.array(z.string()).optional().describe("List of label IDs to apply"), 215 | addLabelIds: z.array(z.string()).optional().describe("List of label IDs to add to the message"), 216 | removeLabelIds: z.array(z.string()).optional().describe("List of label IDs to remove from the message"), 217 | }); 218 | 219 | const DeleteEmailSchema = z.object({ 220 | messageId: z.string().describe("ID of the email message to delete"), 221 | }); 222 | 223 | // New schema for listing email labels 224 | const ListEmailLabelsSchema = z.object({}).describe("Retrieves all available Gmail labels"); 225 | 226 | // Label management schemas 227 | const CreateLabelSchema = z.object({ 228 | name: z.string().describe("Name for the new label"), 229 | messageListVisibility: z.enum(['show', 'hide']).optional().describe("Whether to show or hide the label in the message list"), 230 | labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"), 231 | }).describe("Creates a new Gmail label"); 232 | 233 | const UpdateLabelSchema = z.object({ 234 | id: z.string().describe("ID of the label to update"), 235 | name: z.string().optional().describe("New name for the label"), 236 | messageListVisibility: z.enum(['show', 'hide']).optional().describe("Whether to show or hide the label in the message list"), 237 | labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"), 238 | }).describe("Updates an existing Gmail label"); 239 | 240 | const DeleteLabelSchema = z.object({ 241 | id: z.string().describe("ID of the label to delete"), 242 | }).describe("Deletes a Gmail label"); 243 | 244 | const GetOrCreateLabelSchema = z.object({ 245 | name: z.string().describe("Name of the label to get or create"), 246 | messageListVisibility: z.enum(['show', 'hide']).optional().describe("Whether to show or hide the label in the message list"), 247 | labelListVisibility: z.enum(['labelShow', 'labelShowIfUnread', 'labelHide']).optional().describe("Visibility of the label in the label list"), 248 | }).describe("Gets an existing label by name or creates it if it doesn't exist"); 249 | 250 | // Schemas for batch operations 251 | const BatchModifyEmailsSchema = z.object({ 252 | messageIds: z.array(z.string()).describe("List of message IDs to modify"), 253 | addLabelIds: z.array(z.string()).optional().describe("List of label IDs to add to all messages"), 254 | removeLabelIds: z.array(z.string()).optional().describe("List of label IDs to remove from all messages"), 255 | batchSize: z.number().optional().default(50).describe("Number of messages to process in each batch (default: 50)"), 256 | }); 257 | 258 | const BatchDeleteEmailsSchema = z.object({ 259 | messageIds: z.array(z.string()).describe("List of message IDs to delete"), 260 | batchSize: z.number().optional().default(50).describe("Number of messages to process in each batch (default: 50)"), 261 | }); 262 | 263 | // Main function 264 | async function main() { 265 | await loadCredentials(); 266 | 267 | if (process.argv[2] === 'auth') { 268 | await authenticate(); 269 | console.log('Authentication completed successfully'); 270 | process.exit(0); 271 | } 272 | 273 | // Initialize Gmail API 274 | const gmail = google.gmail({ version: 'v1', auth: oauth2Client }); 275 | 276 | // Server implementation 277 | const server = new Server({ 278 | name: "gmail", 279 | version: "1.0.0", 280 | capabilities: { 281 | tools: {}, 282 | }, 283 | }); 284 | 285 | // Tool handlers 286 | server.setRequestHandler(ListToolsRequestSchema, async () => ({ 287 | tools: [ 288 | { 289 | name: "send_email", 290 | description: "Sends a new email", 291 | inputSchema: zodToJsonSchema(SendEmailSchema), 292 | }, 293 | { 294 | name: "draft_email", 295 | description: "Draft a new email", 296 | inputSchema: zodToJsonSchema(SendEmailSchema), 297 | }, 298 | { 299 | name: "read_email", 300 | description: "Retrieves the content of a specific email", 301 | inputSchema: zodToJsonSchema(ReadEmailSchema), 302 | }, 303 | { 304 | name: "search_emails", 305 | description: "Searches for emails using Gmail search syntax", 306 | inputSchema: zodToJsonSchema(SearchEmailsSchema), 307 | }, 308 | { 309 | name: "modify_email", 310 | description: "Modifies email labels (move to different folders)", 311 | inputSchema: zodToJsonSchema(ModifyEmailSchema), 312 | }, 313 | { 314 | name: "delete_email", 315 | description: "Permanently deletes an email", 316 | inputSchema: zodToJsonSchema(DeleteEmailSchema), 317 | }, 318 | { 319 | name: "list_email_labels", 320 | description: "Retrieves all available Gmail labels", 321 | inputSchema: zodToJsonSchema(ListEmailLabelsSchema), 322 | }, 323 | { 324 | name: "batch_modify_emails", 325 | description: "Modifies labels for multiple emails in batches", 326 | inputSchema: zodToJsonSchema(BatchModifyEmailsSchema), 327 | }, 328 | { 329 | name: "batch_delete_emails", 330 | description: "Permanently deletes multiple emails in batches", 331 | inputSchema: zodToJsonSchema(BatchDeleteEmailsSchema), 332 | }, 333 | { 334 | name: "create_label", 335 | description: "Creates a new Gmail label", 336 | inputSchema: zodToJsonSchema(CreateLabelSchema), 337 | }, 338 | { 339 | name: "update_label", 340 | description: "Updates an existing Gmail label", 341 | inputSchema: zodToJsonSchema(UpdateLabelSchema), 342 | }, 343 | { 344 | name: "delete_label", 345 | description: "Deletes a Gmail label", 346 | inputSchema: zodToJsonSchema(DeleteLabelSchema), 347 | }, 348 | { 349 | name: "get_or_create_label", 350 | description: "Gets an existing label by name or creates it if it doesn't exist", 351 | inputSchema: zodToJsonSchema(GetOrCreateLabelSchema), 352 | }, 353 | ], 354 | })) 355 | 356 | server.setRequestHandler(CallToolRequestSchema, async (request) => { 357 | const { name, arguments: args } = request.params; 358 | 359 | async function handleEmailAction(action: "send" | "draft", validatedArgs: any) { 360 | const message = createEmailMessage(validatedArgs); 361 | 362 | const encodedMessage = Buffer.from(message).toString('base64') 363 | .replace(/\+/g, '-') 364 | .replace(/\//g, '_') 365 | .replace(/=+$/, ''); 366 | 367 | // Define the type for messageRequest 368 | interface GmailMessageRequest { 369 | raw: string; 370 | threadId?: string; 371 | } 372 | 373 | const messageRequest: GmailMessageRequest = { 374 | raw: encodedMessage, 375 | }; 376 | 377 | // Add threadId if specified 378 | if (validatedArgs.threadId) { 379 | messageRequest.threadId = validatedArgs.threadId; 380 | } 381 | 382 | if (action === "send") { 383 | const response = await gmail.users.messages.send({ 384 | userId: 'me', 385 | requestBody: messageRequest, 386 | }); 387 | return { 388 | content: [ 389 | { 390 | type: "text", 391 | text: `Email sent successfully with ID: ${response.data.id}`, 392 | }, 393 | ], 394 | }; 395 | } else { 396 | const response = await gmail.users.drafts.create({ 397 | userId: 'me', 398 | requestBody: { 399 | message: messageRequest, 400 | }, 401 | }); 402 | return { 403 | content: [ 404 | { 405 | type: "text", 406 | text: `Email draft created successfully with ID: ${response.data.id}`, 407 | }, 408 | ], 409 | }; 410 | } 411 | } 412 | 413 | // Helper function to process operations in batches 414 | async function processBatches( 415 | items: T[], 416 | batchSize: number, 417 | processFn: (batch: T[]) => Promise 418 | ): Promise<{ successes: U[], failures: { item: T, error: Error }[] }> { 419 | const successes: U[] = []; 420 | const failures: { item: T, error: Error }[] = []; 421 | 422 | // Process in batches 423 | for (let i = 0; i < items.length; i += batchSize) { 424 | const batch = items.slice(i, i + batchSize); 425 | try { 426 | const results = await processFn(batch); 427 | successes.push(...results); 428 | } catch (error) { 429 | // If batch fails, try individual items 430 | for (const item of batch) { 431 | try { 432 | const result = await processFn([item]); 433 | successes.push(...result); 434 | } catch (itemError) { 435 | failures.push({ item, error: itemError as Error }); 436 | } 437 | } 438 | } 439 | } 440 | 441 | return { successes, failures }; 442 | } 443 | 444 | try { 445 | switch (name) { 446 | case "send_email": 447 | case "draft_email": { 448 | const validatedArgs = SendEmailSchema.parse(args); 449 | const action = name === "send_email" ? "send" : "draft"; 450 | return await handleEmailAction(action, validatedArgs); 451 | } 452 | 453 | case "read_email": { 454 | const validatedArgs = ReadEmailSchema.parse(args); 455 | const response = await gmail.users.messages.get({ 456 | userId: 'me', 457 | id: validatedArgs.messageId, 458 | format: 'full', 459 | }); 460 | 461 | const headers = response.data.payload?.headers || []; 462 | const subject = headers.find(h => h.name?.toLowerCase() === 'subject')?.value || ''; 463 | const from = headers.find(h => h.name?.toLowerCase() === 'from')?.value || ''; 464 | const to = headers.find(h => h.name?.toLowerCase() === 'to')?.value || ''; 465 | const date = headers.find(h => h.name?.toLowerCase() === 'date')?.value || ''; 466 | const threadId = response.data.threadId || ''; 467 | 468 | // Extract email content using the recursive function 469 | const { text, html } = extractEmailContent(response.data.payload as GmailMessagePart || {}); 470 | 471 | // Use plain text content if available, otherwise use HTML content 472 | // (optionally, you could implement HTML-to-text conversion here) 473 | let body = text || html || ''; 474 | 475 | // If we only have HTML content, add a note for the user 476 | const contentTypeNote = !text && html ? 477 | '[Note: This email is HTML-formatted. Plain text version not available.]\n\n' : ''; 478 | 479 | // Get attachment information 480 | const attachments: EmailAttachment[] = []; 481 | const processAttachmentParts = (part: GmailMessagePart, path: string = '') => { 482 | if (part.body && part.body.attachmentId) { 483 | const filename = part.filename || `attachment-${part.body.attachmentId}`; 484 | attachments.push({ 485 | id: part.body.attachmentId, 486 | filename: filename, 487 | mimeType: part.mimeType || 'application/octet-stream', 488 | size: part.body.size || 0 489 | }); 490 | } 491 | 492 | if (part.parts) { 493 | part.parts.forEach((subpart: GmailMessagePart) => 494 | processAttachmentParts(subpart, `${path}/parts`) 495 | ); 496 | } 497 | }; 498 | 499 | if (response.data.payload) { 500 | processAttachmentParts(response.data.payload as GmailMessagePart); 501 | } 502 | 503 | // Add attachment info to output if any are present 504 | const attachmentInfo = attachments.length > 0 ? 505 | `\n\nAttachments (${attachments.length}):\n` + 506 | attachments.map(a => `- ${a.filename} (${a.mimeType}, ${Math.round(a.size/1024)} KB)`).join('\n') : ''; 507 | 508 | return { 509 | content: [ 510 | { 511 | type: "text", 512 | text: `Thread ID: ${threadId}\nSubject: ${subject}\nFrom: ${from}\nTo: ${to}\nDate: ${date}\n\n${contentTypeNote}${body}${attachmentInfo}`, 513 | }, 514 | ], 515 | }; 516 | } 517 | 518 | case "search_emails": { 519 | const validatedArgs = SearchEmailsSchema.parse(args); 520 | const response = await gmail.users.messages.list({ 521 | userId: 'me', 522 | q: validatedArgs.query, 523 | maxResults: validatedArgs.maxResults || 10, 524 | }); 525 | 526 | const messages = response.data.messages || []; 527 | const results = await Promise.all( 528 | messages.map(async (msg) => { 529 | const detail = await gmail.users.messages.get({ 530 | userId: 'me', 531 | id: msg.id!, 532 | format: 'metadata', 533 | metadataHeaders: ['Subject', 'From', 'Date'], 534 | }); 535 | const headers = detail.data.payload?.headers || []; 536 | return { 537 | id: msg.id, 538 | subject: headers.find(h => h.name === 'Subject')?.value || '', 539 | from: headers.find(h => h.name === 'From')?.value || '', 540 | date: headers.find(h => h.name === 'Date')?.value || '', 541 | }; 542 | }) 543 | ); 544 | 545 | return { 546 | content: [ 547 | { 548 | type: "text", 549 | text: results.map(r => 550 | `ID: ${r.id}\nSubject: ${r.subject}\nFrom: ${r.from}\nDate: ${r.date}\n` 551 | ).join('\n'), 552 | }, 553 | ], 554 | }; 555 | } 556 | 557 | // Updated implementation for the modify_email handler 558 | case "modify_email": { 559 | const validatedArgs = ModifyEmailSchema.parse(args); 560 | 561 | // Prepare request body 562 | const requestBody: any = {}; 563 | 564 | if (validatedArgs.labelIds) { 565 | requestBody.addLabelIds = validatedArgs.labelIds; 566 | } 567 | 568 | if (validatedArgs.addLabelIds) { 569 | requestBody.addLabelIds = validatedArgs.addLabelIds; 570 | } 571 | 572 | if (validatedArgs.removeLabelIds) { 573 | requestBody.removeLabelIds = validatedArgs.removeLabelIds; 574 | } 575 | 576 | await gmail.users.messages.modify({ 577 | userId: 'me', 578 | id: validatedArgs.messageId, 579 | requestBody: requestBody, 580 | }); 581 | 582 | return { 583 | content: [ 584 | { 585 | type: "text", 586 | text: `Email ${validatedArgs.messageId} labels updated successfully`, 587 | }, 588 | ], 589 | }; 590 | } 591 | 592 | case "delete_email": { 593 | const validatedArgs = DeleteEmailSchema.parse(args); 594 | await gmail.users.messages.delete({ 595 | userId: 'me', 596 | id: validatedArgs.messageId, 597 | }); 598 | 599 | return { 600 | content: [ 601 | { 602 | type: "text", 603 | text: `Email ${validatedArgs.messageId} deleted successfully`, 604 | }, 605 | ], 606 | }; 607 | } 608 | 609 | case "list_email_labels": { 610 | const labelResults = await listLabels(gmail); 611 | const systemLabels = labelResults.system; 612 | const userLabels = labelResults.user; 613 | 614 | return { 615 | content: [ 616 | { 617 | type: "text", 618 | text: `Found ${labelResults.count.total} labels (${labelResults.count.system} system, ${labelResults.count.user} user):\n\n` + 619 | "System Labels:\n" + 620 | systemLabels.map((l: GmailLabel) => `ID: ${l.id}\nName: ${l.name}\n`).join('\n') + 621 | "\nUser Labels:\n" + 622 | userLabels.map((l: GmailLabel) => `ID: ${l.id}\nName: ${l.name}\n`).join('\n') 623 | }, 624 | ], 625 | }; 626 | } 627 | 628 | case "batch_modify_emails": { 629 | const validatedArgs = BatchModifyEmailsSchema.parse(args); 630 | const messageIds = validatedArgs.messageIds; 631 | const batchSize = validatedArgs.batchSize || 50; 632 | 633 | // Prepare request body 634 | const requestBody: any = {}; 635 | 636 | if (validatedArgs.addLabelIds) { 637 | requestBody.addLabelIds = validatedArgs.addLabelIds; 638 | } 639 | 640 | if (validatedArgs.removeLabelIds) { 641 | requestBody.removeLabelIds = validatedArgs.removeLabelIds; 642 | } 643 | 644 | // Process messages in batches 645 | const { successes, failures } = await processBatches( 646 | messageIds, 647 | batchSize, 648 | async (batch) => { 649 | const results = await Promise.all( 650 | batch.map(async (messageId) => { 651 | const result = await gmail.users.messages.modify({ 652 | userId: 'me', 653 | id: messageId, 654 | requestBody: requestBody, 655 | }); 656 | return { messageId, success: true }; 657 | }) 658 | ); 659 | return results; 660 | } 661 | ); 662 | 663 | // Generate summary of the operation 664 | const successCount = successes.length; 665 | const failureCount = failures.length; 666 | 667 | let resultText = `Batch label modification complete.\n`; 668 | resultText += `Successfully processed: ${successCount} messages\n`; 669 | 670 | if (failureCount > 0) { 671 | resultText += `Failed to process: ${failureCount} messages\n\n`; 672 | resultText += `Failed message IDs:\n`; 673 | resultText += failures.map(f => `- ${(f.item as string).substring(0, 16)}... (${f.error.message})`).join('\n'); 674 | } 675 | 676 | return { 677 | content: [ 678 | { 679 | type: "text", 680 | text: resultText, 681 | }, 682 | ], 683 | }; 684 | } 685 | 686 | case "batch_delete_emails": { 687 | const validatedArgs = BatchDeleteEmailsSchema.parse(args); 688 | const messageIds = validatedArgs.messageIds; 689 | const batchSize = validatedArgs.batchSize || 50; 690 | 691 | // Process messages in batches 692 | const { successes, failures } = await processBatches( 693 | messageIds, 694 | batchSize, 695 | async (batch) => { 696 | const results = await Promise.all( 697 | batch.map(async (messageId) => { 698 | await gmail.users.messages.delete({ 699 | userId: 'me', 700 | id: messageId, 701 | }); 702 | return { messageId, success: true }; 703 | }) 704 | ); 705 | return results; 706 | } 707 | ); 708 | 709 | // Generate summary of the operation 710 | const successCount = successes.length; 711 | const failureCount = failures.length; 712 | 713 | let resultText = `Batch delete operation complete.\n`; 714 | resultText += `Successfully deleted: ${successCount} messages\n`; 715 | 716 | if (failureCount > 0) { 717 | resultText += `Failed to delete: ${failureCount} messages\n\n`; 718 | resultText += `Failed message IDs:\n`; 719 | resultText += failures.map(f => `- ${(f.item as string).substring(0, 16)}... (${f.error.message})`).join('\n'); 720 | } 721 | 722 | return { 723 | content: [ 724 | { 725 | type: "text", 726 | text: resultText, 727 | }, 728 | ], 729 | }; 730 | } 731 | 732 | // New label management handlers 733 | case "create_label": { 734 | const validatedArgs = CreateLabelSchema.parse(args); 735 | const result = await createLabel(gmail, validatedArgs.name, { 736 | messageListVisibility: validatedArgs.messageListVisibility, 737 | labelListVisibility: validatedArgs.labelListVisibility, 738 | }); 739 | 740 | return { 741 | content: [ 742 | { 743 | type: "text", 744 | text: `Label created successfully:\nID: ${result.id}\nName: ${result.name}\nType: ${result.type}`, 745 | }, 746 | ], 747 | }; 748 | } 749 | 750 | case "update_label": { 751 | const validatedArgs = UpdateLabelSchema.parse(args); 752 | 753 | // Prepare request body with only the fields that were provided 754 | const updates: any = {}; 755 | if (validatedArgs.name) updates.name = validatedArgs.name; 756 | if (validatedArgs.messageListVisibility) updates.messageListVisibility = validatedArgs.messageListVisibility; 757 | if (validatedArgs.labelListVisibility) updates.labelListVisibility = validatedArgs.labelListVisibility; 758 | 759 | const result = await updateLabel(gmail, validatedArgs.id, updates); 760 | 761 | return { 762 | content: [ 763 | { 764 | type: "text", 765 | text: `Label updated successfully:\nID: ${result.id}\nName: ${result.name}\nType: ${result.type}`, 766 | }, 767 | ], 768 | }; 769 | } 770 | 771 | case "delete_label": { 772 | const validatedArgs = DeleteLabelSchema.parse(args); 773 | const result = await deleteLabel(gmail, validatedArgs.id); 774 | 775 | return { 776 | content: [ 777 | { 778 | type: "text", 779 | text: result.message, 780 | }, 781 | ], 782 | }; 783 | } 784 | 785 | case "get_or_create_label": { 786 | const validatedArgs = GetOrCreateLabelSchema.parse(args); 787 | const result = await getOrCreateLabel(gmail, validatedArgs.name, { 788 | messageListVisibility: validatedArgs.messageListVisibility, 789 | labelListVisibility: validatedArgs.labelListVisibility, 790 | }); 791 | 792 | const action = result.type === 'user' && result.name === validatedArgs.name ? 'found existing' : 'created new'; 793 | 794 | return { 795 | content: [ 796 | { 797 | type: "text", 798 | text: `Successfully ${action} label:\nID: ${result.id}\nName: ${result.name}\nType: ${result.type}`, 799 | }, 800 | ], 801 | }; 802 | } 803 | 804 | default: 805 | throw new Error(`Unknown tool: ${name}`); 806 | } 807 | } catch (error: any) { 808 | return { 809 | content: [ 810 | { 811 | type: "text", 812 | text: `Error: ${error.message}`, 813 | }, 814 | ], 815 | }; 816 | } 817 | }); 818 | 819 | const transport = new StdioServerTransport(); 820 | server.connect(transport); 821 | } 822 | 823 | main().catch((error) => { 824 | console.error('Server error:', error); 825 | process.exit(1); 826 | }); 827 | -------------------------------------------------------------------------------- /src/label-manager.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Label Manager for Gmail MCP Server 3 | * Provides comprehensive label management functionality 4 | */ 5 | 6 | // Type definitions for Gmail API labels 7 | export interface GmailLabel { 8 | id: string; 9 | name: string; 10 | type?: string; 11 | messageListVisibility?: string; 12 | labelListVisibility?: string; 13 | messagesTotal?: number; 14 | messagesUnread?: number; 15 | color?: { 16 | textColor?: string; 17 | backgroundColor?: string; 18 | }; 19 | } 20 | 21 | /** 22 | * Creates a new Gmail label 23 | * @param gmail - Gmail API instance 24 | * @param labelName - Name of the label to create 25 | * @param options - Optional settings for the label 26 | * @returns The newly created label 27 | */ 28 | export async function createLabel(gmail: any, labelName: string, options: { 29 | messageListVisibility?: string; 30 | labelListVisibility?: string; 31 | } = {}) { 32 | try { 33 | // Default visibility settings if not provided 34 | const messageListVisibility = options.messageListVisibility || 'show'; 35 | const labelListVisibility = options.labelListVisibility || 'labelShow'; 36 | 37 | const response = await gmail.users.labels.create({ 38 | userId: 'me', 39 | requestBody: { 40 | name: labelName, 41 | messageListVisibility, 42 | labelListVisibility, 43 | }, 44 | }); 45 | 46 | return response.data; 47 | } catch (error: any) { 48 | // Handle duplicate labels more gracefully 49 | if (error.message && error.message.includes('already exists')) { 50 | throw new Error(`Label "${labelName}" already exists. Please use a different name.`); 51 | } 52 | 53 | throw new Error(`Failed to create label: ${error.message}`); 54 | } 55 | } 56 | 57 | /** 58 | * Updates an existing Gmail label 59 | * @param gmail - Gmail API instance 60 | * @param labelId - ID of the label to update 61 | * @param updates - Properties to update 62 | * @returns The updated label 63 | */ 64 | export async function updateLabel(gmail: any, labelId: string, updates: { 65 | name?: string; 66 | messageListVisibility?: string; 67 | labelListVisibility?: string; 68 | }) { 69 | try { 70 | // Verify the label exists before updating 71 | await gmail.users.labels.get({ 72 | userId: 'me', 73 | id: labelId, 74 | }); 75 | 76 | const response = await gmail.users.labels.update({ 77 | userId: 'me', 78 | id: labelId, 79 | requestBody: updates, 80 | }); 81 | 82 | return response.data; 83 | } catch (error: any) { 84 | if (error.code === 404) { 85 | throw new Error(`Label with ID "${labelId}" not found.`); 86 | } 87 | 88 | throw new Error(`Failed to update label: ${error.message}`); 89 | } 90 | } 91 | 92 | /** 93 | * Deletes a Gmail label 94 | * @param gmail - Gmail API instance 95 | * @param labelId - ID of the label to delete 96 | * @returns Success message 97 | */ 98 | export async function deleteLabel(gmail: any, labelId: string) { 99 | try { 100 | // Ensure we're not trying to delete system labels 101 | const label = await gmail.users.labels.get({ 102 | userId: 'me', 103 | id: labelId, 104 | }); 105 | 106 | if (label.data.type === 'system') { 107 | throw new Error(`Cannot delete system label with ID "${labelId}".`); 108 | } 109 | 110 | await gmail.users.labels.delete({ 111 | userId: 'me', 112 | id: labelId, 113 | }); 114 | 115 | return { success: true, message: `Label "${label.data.name}" deleted successfully.` }; 116 | } catch (error: any) { 117 | if (error.code === 404) { 118 | throw new Error(`Label with ID "${labelId}" not found.`); 119 | } 120 | 121 | throw new Error(`Failed to delete label: ${error.message}`); 122 | } 123 | } 124 | 125 | /** 126 | * Gets a detailed list of all Gmail labels 127 | * @param gmail - Gmail API instance 128 | * @returns Object containing system and user labels 129 | */ 130 | export async function listLabels(gmail: any) { 131 | try { 132 | const response = await gmail.users.labels.list({ 133 | userId: 'me', 134 | }); 135 | 136 | const labels = response.data.labels || []; 137 | 138 | // Group labels by type for better organization 139 | const systemLabels = labels.filter((label:GmailLabel) => label.type === 'system'); 140 | const userLabels = labels.filter((label:GmailLabel) => label.type === 'user'); 141 | 142 | return { 143 | all: labels, 144 | system: systemLabels, 145 | user: userLabels, 146 | count: { 147 | total: labels.length, 148 | system: systemLabels.length, 149 | user: userLabels.length 150 | } 151 | }; 152 | } catch (error: any) { 153 | throw new Error(`Failed to list labels: ${error.message}`); 154 | } 155 | } 156 | 157 | /** 158 | * Finds a label by name 159 | * @param gmail - Gmail API instance 160 | * @param labelName - Name of the label to find 161 | * @returns The found label or null if not found 162 | */ 163 | export async function findLabelByName(gmail: any, labelName: string) { 164 | try { 165 | const labelsResponse = await listLabels(gmail); 166 | const allLabels = labelsResponse.all; 167 | 168 | // Case-insensitive match 169 | const foundLabel = allLabels.find( 170 | (label: GmailLabel) => label.name.toLowerCase() === labelName.toLowerCase() 171 | ); 172 | 173 | return foundLabel || null; 174 | } catch (error: any) { 175 | throw new Error(`Failed to find label: ${error.message}`); 176 | } 177 | } 178 | 179 | /** 180 | * Creates label if it doesn't exist or returns existing label 181 | * @param gmail - Gmail API instance 182 | * @param labelName - Name of the label to create 183 | * @param options - Optional settings for the label 184 | * @returns The new or existing label 185 | */ 186 | export async function getOrCreateLabel(gmail: any, labelName: string, options: { 187 | messageListVisibility?: string; 188 | labelListVisibility?: string; 189 | } = {}) { 190 | try { 191 | // First try to find an existing label 192 | const existingLabel = await findLabelByName(gmail, labelName); 193 | 194 | if (existingLabel) { 195 | return existingLabel; 196 | } 197 | 198 | // If not found, create a new one 199 | return await createLabel(gmail, labelName, options); 200 | } catch (error: any) { 201 | throw new Error(`Failed to get or create label: ${error.message}`); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /src/utl.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper function to encode email headers containing non-ASCII characters 3 | * according to RFC 2047 MIME specification 4 | */ 5 | function encodeEmailHeader(text: string): string { 6 | // Only encode if the text contains non-ASCII characters 7 | if (/[^\x00-\x7F]/.test(text)) { 8 | // Use MIME Words encoding (RFC 2047) 9 | return '=?UTF-8?B?' + Buffer.from(text).toString('base64') + '?='; 10 | } 11 | return text; 12 | } 13 | 14 | export const validateEmail = (email: string): boolean => { 15 | const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 16 | return emailRegex.test(email); 17 | }; 18 | 19 | export function createEmailMessage(validatedArgs: any): string { 20 | const encodedSubject = encodeEmailHeader(validatedArgs.subject); 21 | // Determine content type based on available content and explicit mimeType 22 | let mimeType = validatedArgs.mimeType || 'text/plain'; 23 | 24 | // If htmlBody is provided and mimeType isn't explicitly set to text/plain, 25 | // use multipart/alternative to include both versions 26 | if (validatedArgs.htmlBody && mimeType !== 'text/plain') { 27 | mimeType = 'multipart/alternative'; 28 | } 29 | 30 | // Generate a random boundary string for multipart messages 31 | const boundary = `----=_NextPart_${Math.random().toString(36).substring(2)}`; 32 | 33 | // Validate email addresses 34 | (validatedArgs.to as string[]).forEach(email => { 35 | if (!validateEmail(email)) { 36 | throw new Error(`Recipient email address is invalid: ${email}`); 37 | } 38 | }); 39 | 40 | // Common email headers 41 | const emailParts = [ 42 | 'From: me', 43 | `To: ${validatedArgs.to.join(', ')}`, 44 | validatedArgs.cc ? `Cc: ${validatedArgs.cc.join(', ')}` : '', 45 | validatedArgs.bcc ? `Bcc: ${validatedArgs.bcc.join(', ')}` : '', 46 | `Subject: ${encodedSubject}`, 47 | // Add thread-related headers if specified 48 | validatedArgs.inReplyTo ? `In-Reply-To: ${validatedArgs.inReplyTo}` : '', 49 | validatedArgs.inReplyTo ? `References: ${validatedArgs.inReplyTo}` : '', 50 | 'MIME-Version: 1.0', 51 | ].filter(Boolean); 52 | 53 | // Construct the email based on the content type 54 | if (mimeType === 'multipart/alternative') { 55 | // Multipart email with both plain text and HTML 56 | emailParts.push(`Content-Type: multipart/alternative; boundary="${boundary}"`); 57 | emailParts.push(''); 58 | 59 | // Plain text part 60 | emailParts.push(`--${boundary}`); 61 | emailParts.push('Content-Type: text/plain; charset=UTF-8'); 62 | emailParts.push('Content-Transfer-Encoding: 7bit'); 63 | emailParts.push(''); 64 | emailParts.push(validatedArgs.body); 65 | emailParts.push(''); 66 | 67 | // HTML part 68 | emailParts.push(`--${boundary}`); 69 | emailParts.push('Content-Type: text/html; charset=UTF-8'); 70 | emailParts.push('Content-Transfer-Encoding: 7bit'); 71 | emailParts.push(''); 72 | emailParts.push(validatedArgs.htmlBody || validatedArgs.body); // Use body as fallback 73 | emailParts.push(''); 74 | 75 | // Close the boundary 76 | emailParts.push(`--${boundary}--`); 77 | } else if (mimeType === 'text/html') { 78 | // HTML-only email 79 | emailParts.push('Content-Type: text/html; charset=UTF-8'); 80 | emailParts.push('Content-Transfer-Encoding: 7bit'); 81 | emailParts.push(''); 82 | emailParts.push(validatedArgs.htmlBody || validatedArgs.body); 83 | } else { 84 | // Plain text email (default) 85 | emailParts.push('Content-Type: text/plain; charset=UTF-8'); 86 | emailParts.push('Content-Transfer-Encoding: 7bit'); 87 | emailParts.push(''); 88 | emailParts.push(validatedArgs.body); 89 | } 90 | 91 | return emailParts.join('\r\n'); 92 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "ES2020", 5 | "moduleResolution": "node", 6 | "outDir": "./dist", 7 | "rootDir": "./src", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "skipLibCheck": true, 11 | "forceConsistentCasingInFileNames": true 12 | }, 13 | "include": ["src/**/*"], 14 | "exclude": ["node_modules", "dist"] 15 | } 16 | --------------------------------------------------------------------------------