Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,13 @@ The server automatically filters available tools based on your authorized scopes
| `list_email_labels` | `gmail.readonly`, `gmail.modify`, or `gmail.labels` |
| `send_email`, `draft_email`, `reply_all`, `send_draft` | `gmail.modify`, `gmail.compose`, or `gmail.send` |
| `delete_draft`, `update_draft` | `gmail.modify` or `gmail.compose` |
| `modify_email`, `delete_email`, `batch_modify_emails`, `batch_delete_emails`, `modify_thread`, `report_phishing`, `batch_report_phishing` | `gmail.modify` |
| `modify_email`, `batch_modify_emails`, `modify_thread`, `report_phishing`, `batch_report_phishing` | `gmail.modify` |
| `delete_email`, `batch_delete_emails` | `gmail.full` (`https://mail.google.com/`) |
| `create_label`, `update_label`, `delete_label`, `get_or_create_label` | `gmail.modify` or `gmail.labels` |
| `list_filters`, `get_filter`, `create_filter`, `delete_filter`, `create_filter_from_template` | `gmail.settings.basic` |

`gmail.full` is intentionally separate from the default scopes because it grants permanent-delete capability. Prefer `modify_email` / `batch_modify_emails` for archive, mark-read, label, or inbox cleanup flows; re-authenticate with `--scopes=gmail.full,gmail.settings.basic` only when the assistant should be able to permanently delete mail.

### Re-authenticating

To change your scopes, simply run the auth command again with different scopes. This will replace your existing credentials.
Expand Down Expand Up @@ -459,7 +462,7 @@ Adds or removes labels from emails (move to different folders, archive, etc.).
```

### 7. Delete Email (`delete_email`)
Permanently deletes an email.
Permanently deletes an email. This tool requires `gmail.full` (`https://mail.google.com/`); the default `gmail.modify` scope is not enough for Gmail's permanent-delete endpoint.

```json
{
Expand Down Expand Up @@ -530,7 +533,7 @@ Modifies labels for multiple emails in efficient batches.
```

### 14. Batch Delete Emails (`batch_delete_emails`)
Permanently deletes multiple emails in efficient batches.
Permanently deletes multiple emails in efficient batches. This tool requires `gmail.full` (`https://mail.google.com/`); the default `gmail.modify` scope is not enough for Gmail's permanent-delete endpoint.

```json
{
Expand Down
28 changes: 28 additions & 0 deletions src/delete-scopes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { describe, it, expect } from 'vitest';
import { getAvailableScopeNames, hasScope, scopeNameToUrl } from './scopes.js';
import { getToolByName } from './tools.js';

describe('permanent delete scope requirements', () => {
it('recognizes gmail.full as the permanent-delete Gmail scope', () => {
expect(getAvailableScopeNames()).toContain('gmail.full');
expect(scopeNameToUrl('gmail.full')).toBe('https://mail.google.com/');
});

it('does not expose permanent delete tools with only gmail.modify', () => {
const deleteEmail = getToolByName('delete_email')!;
const batchDeleteEmails = getToolByName('batch_delete_emails')!;

expect(deleteEmail.scopes).toEqual(['gmail.full']);
expect(batchDeleteEmails.scopes).toEqual(['gmail.full']);
expect(hasScope(['gmail.modify'], deleteEmail.scopes)).toBe(false);
expect(hasScope(['gmail.modify'], batchDeleteEmails.scopes)).toBe(false);
});

it('exposes permanent delete tools with gmail.full shorthand or URL scope', () => {
const deleteEmail = getToolByName('delete_email')!;
const batchDeleteEmails = getToolByName('batch_delete_emails')!;

expect(hasScope(['gmail.full'], deleteEmail.scopes)).toBe(true);
expect(hasScope(['https://mail.google.com/'], batchDeleteEmails.scopes)).toBe(true);
});
});
2 changes: 2 additions & 0 deletions src/scopes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// - gmail.send: Send emails only
// - gmail.labels: Manage labels only
// - gmail.settings.basic: Manage filters and settings
// - gmail.full: Full mailbox access, including permanent deletion
//
// Note: gmail.modify includes all capabilities of gmail.readonly,
// so you don't need both scopes together.
Expand All @@ -18,6 +19,7 @@ export const SCOPE_MAP: Record<string, string> = {
"gmail.compose": "https://www.googleapis.com/auth/gmail.compose",
"gmail.send": "https://www.googleapis.com/auth/gmail.send",
"gmail.labels": "https://www.googleapis.com/auth/gmail.labels",
"gmail.full": "https://mail.google.com/",
"gmail.settings.basic": "https://www.googleapis.com/auth/gmail.settings.basic",
"gmail.settings.sharing": "https://www.googleapis.com/auth/gmail.settings.sharing",
};
Expand Down
8 changes: 4 additions & 4 deletions src/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,9 @@ export const toolDefinitions: ToolDefinition[] = [
},
{
name: "delete_email",
description: "Permanently deletes an email",
description: "Permanently deletes an email. Requires gmail.full because Gmail's delete endpoint is not covered by gmail.modify.",
schema: DeleteEmailSchema,
scopes: ["gmail.modify"],
scopes: ["gmail.full"],
annotations: { title: "Delete Email", destructiveHint: true },
},
{
Expand All @@ -348,9 +348,9 @@ export const toolDefinitions: ToolDefinition[] = [
},
{
name: "batch_delete_emails",
description: "Permanently deletes multiple emails in batches",
description: "Permanently deletes multiple emails in batches. Requires gmail.full because Gmail's batchDelete endpoint is not covered by gmail.modify.",
schema: BatchDeleteEmailsSchema,
scopes: ["gmail.modify"],
scopes: ["gmail.full"],
annotations: { title: "Batch Delete Emails", destructiveHint: true },
},

Expand Down