Commit Graph

1432 Commits

Author SHA1 Message Date
Taylor Wilsdon
8d2b23ab0e Merge pull request #502 from stakeswky/fix/non-ascii-attachment-filenames
fix: use RFC 2231 encoding for non-ASCII attachment filenames
2026-02-24 10:31:20 -04:00
Taylor Wilsdon
252487fd88 Apply suggestions from code review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-24 10:30:36 -04:00
Taylor Wilsdon
285406e2ee Merge pull request #495 from mickey-mikey/fix/windows-attachment-corruption
Fix Windows attachment corruption: add O_BINARY flag to os.open
2026-02-24 10:28:53 -04:00
User
2526b87a52 fix: also strip null bytes from attachment filename for consistency 2026-02-23 11:14:21 +08:00
stakeswky
0dc9985d33 fix: use RFC 2231 encoding for non-ASCII attachment filenames
When creating Gmail drafts with attachments whose filenames contain
non-ASCII characters (e.g. umlauts like ü, ö, ä), Gmail displays
"noname" instead of the actual filename.

The root cause is that Content-Disposition was built via string
formatting (f'attachment; filename="{safe_filename}"'), which embeds
raw non-ASCII bytes in the header.  Gmail cannot parse these and falls
back to "noname".

Fix: pass the filename as a keyword argument to add_header(), which
makes Python's email library automatically apply RFC 2231 encoding
(filename*=utf-8''...) for non-ASCII names while keeping ASCII
filenames unchanged.

Fixes #500
2026-02-23 10:40:56 +08:00
mickey-mikey
1e36375493 Merge branch 'taylorwilsdon:main' into fix/windows-attachment-corruption 2026-02-22 19:54:41 +11:00
mickey-mikey
ffeba1f2f3 fix: add O_BINARY flag to os.open for Windows attachment writes
Fixes #494 - Windows attachment corruption for PNG/PDF files.

On Windows, os.open() defaults to text mode, which translates LF (0x0a)
bytes to CRLF (0x0d 0x0a) during os.write(). This corrupts any binary
attachment containing 0x0a bytes (PNG headers, PDFs, etc.).

The fix adds os.O_BINARY to the os.open() flags using the standard
getattr(os, 'O_BINARY', 0) idiom, which returns the flag on Windows
and 0 (no-op) on platforms where it doesn't exist.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 11:45:37 +11:00
Taylor Wilsdon
724234e509 Update README.md 2026-02-21 07:56:01 -05:00
Taylor Wilsdon
519578cdf7 chore: release v1.12.0 2026-02-19 10:05:36 -05:00
Taylor Wilsdon
c3d1e250e6 Merge pull request #428 from francescomucio/feature/create-drive-folder
feat(drive): add create_drive_folder tool and unit test
2026-02-19 10:04:26 -05:00
Taylor Wilsdon
24a4f376d8 refac 2026-02-19 09:58:49 -05:00
Taylor Wilsdon
4f5c65953c Merge branch 'main' of github.com:taylorwilsdon/google_workspace_mcp into feature/create-drive-folder 2026-02-19 09:55:07 -05:00
Taylor Wilsdon
e9d4d291e2 Merge pull request #488 from drewgillson/feat/chat-attachment-download
Add chat attachment support: surface metadata and download files
2026-02-19 09:47:20 -05:00
Taylor Wilsdon
bdc815a723 fix missing readme and tool tier entry for previous addition 2026-02-19 09:46:51 -05:00
Taylor Wilsdon
7d5c0fdbca ruff & mimetype 2026-02-19 09:42:42 -05:00
Taylor Wilsdon
eaa13d3f7e Merge branch 'main' of github.com:taylorwilsdon/google_workspace_mcp into feat/chat-attachment-download 2026-02-19 09:41:06 -05:00
Taylor Wilsdon
6f2a88c105 Merge pull request #489 from MaxGhenis/feat/comment-anchor-text
feat: surface quotedFileContent (anchor text) in comment reading
2026-02-19 09:39:56 -05:00
Taylor Wilsdon
8b8d74cc3f Merge pull request #490 from MaxGhenis/feat/doc-markdown-export
feat(docs): add get_doc_as_markdown tool with comment context
2026-02-19 09:38:26 -05:00
Max Ghenis
7b7fcfdb58 fix: add URL-to-ID extraction, comment_mode validation, and pipe escaping
Address CodeRabbit review feedback:
- Extract doc ID from full Google Docs URLs (e.g. /d/<id>/)
- Validate comment_mode against allowed values
- Escape pipe characters in table cell text

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 19:26:31 -08:00
Max Ghenis
08ad7ad308 feat(docs): add get_doc_as_markdown tool with comment context
Adds a new `get_doc_as_markdown` tool that converts Google Docs to clean
Markdown preserving formatting (headings, bold/italic/strikethrough, links,
code spans, ordered/unordered lists with nesting, and tables).

Optionally overlays comments with their anchor text (quotedFileContent) —
the specific text each comment is attached to — in two modes:
- inline: footnote-style references placed at the anchor text location
- appendix: all comments grouped at the bottom with blockquoted anchors

This gives AI agents full document context in a single tool call, unlike
get_doc_content which strips all formatting to plain text.

New files:
- gdocs/docs_markdown.py: Converter + comment formatting logic
- tests/gdocs/test_docs_markdown.py: 18 tests

Tool tier: extended (alongside search_docs, export_doc_to_pdf, etc.)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 19:15:56 -08:00
Max Ghenis
d4070a209b feat: surface quotedFileContent (anchor text) in comment reading
When reading comments via read_document_comments / read_spreadsheet_comments /
read_presentation_comments, the Drive API's quotedFileContent.value field is
now requested and displayed as "Quoted text:" in the output. This shows which
specific text in the document each comment is anchored to.

Comments without anchor text (document-level comments) omit the line.

Relates to #210

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 19:12:21 -08:00
Drew Gillson
4f3eec459d Add chat attachment support: surface metadata and download images/files
Previously, get_messages and search_messages completely ignored the
attachment field on Chat API messages. This adds:

- Attachment metadata (filename, type) displayed inline in get_messages
  and search_messages output
- New download_chat_attachment tool that downloads attachments via the
  Chat API media endpoint and saves to local disk

The download uses httpx with a Bearer token against the
chat.googleapis.com/v1/media endpoint (with alt=media), which works
correctly in both OAuth 2.0 and OAuth 2.1 modes. The attachment's
downloadUri field is intentionally ignored as it points to
chat.google.com which requires browser session cookies.

Key details:
- Uses attachmentDataRef.resourceName for the media endpoint URL
- No new OAuth scopes required (existing chat_read is sufficient)
- Tool registered in the extended tier
- 10 unit tests covering metadata display, download, and edge cases
2026-02-18 17:02:18 -07:00
Taylor Wilsdon
860bc4c16f Merge pull request #484 from sethladd/add-chat-spaces-readonly-scope
Add chat.spaces.readonly scope for listing spaces
2026-02-18 13:21:24 -05:00
Taylor Wilsdon
a6988cf643 fix ruff workflow 2026-02-18 13:19:49 -05:00
Taylor Wilsdon
9b8dc6568c chat spaces readonly scope 2026-02-18 12:46:08 -05:00
Taylor Wilsdon
28f03c2e92 ruff 2026-02-18 12:36:25 -05:00
Taylor Wilsdon
96725470ec Merge branch 'main' of github.com:taylorwilsdon/google_workspace_mcp into add-chat-spaces-readonly-scope 2026-02-18 12:36:18 -05:00
Taylor Wilsdon
6b21632e58 Merge pull request #486 from taylorwilsdon/issues/483
enh: Refresh flow when scopes change since last authorization
2026-02-18 12:34:11 -05:00
Taylor Wilsdon
f62e0bbd26 pr feedback 2026-02-18 12:28:17 -05:00
Taylor Wilsdon
3cc40c1357 Merge branch 'issues/483' of github.com:taylorwilsdon/google_workspace_mcp into issues/483 2026-02-18 12:22:32 -05:00
Taylor Wilsdon
90a2a9c00b set for scopes 2026-02-18 12:22:13 -05:00
github-actions[bot]
950206c707 style: auto-fix ruff lint and format 2026-02-18 16:49:48 +00:00
Taylor Wilsdon
a28fa0a249 address issues/483 2026-02-18 11:48:53 -05:00
Seth Ladd
d964324e5d Add chat.spaces.readonly scope for listing spaces
The list_spaces tool was using chat.messages.readonly which is overly
broad for simply enumerating available spaces. This adds the
chat.spaces.readonly scope and uses it for list_spaces, following the
principle of least privilege.

Closes #479

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 20:58:08 -08:00
Taylor Wilsdon
a047572c98 Merge pull request #482 from drewgillson/feat/chat-enhancements
feat(chat): People API sender resolution, rich links, threads, and reactions
2026-02-17 21:11:16 -05:00
Taylor Wilsdon
d542d4aadb cache that shit 2026-02-17 21:10:52 -05:00
Taylor Wilsdon
3d9d0fb473 refactor github actions for ruff 2026-02-17 21:06:03 -05:00
Taylor Wilsdon
e90e22d719 refac 2026-02-17 21:02:48 -05:00
Taylor Wilsdon
2b551e5f57 Merge branch 'main' of https://github.com/taylorwilsdon/google_workspace_mcp into feat/chat-enhancements 2026-02-17 21:01:46 -05:00
Taylor Wilsdon
6eca4ddcc4 ruff 2026-02-17 21:01:44 -05:00
Taylor Wilsdon
ace2bebd5c Create FUNDING.yml 2026-02-17 20:56:51 -05:00
Drew Gillson
be2f68ff68 feat(chat): add People API sender resolution, rich links, threads, and reactions
Resolves several gaps in the Google Chat tools:

**Sender resolution via People API:**
- Chat API doesn't return displayName for service account access
- New `_resolve_sender()` uses People API to look up user IDs
- In-memory cache avoids repeated lookups
- get_messages and search_messages now use `require_multiple_services`
  to inject both chat and people services

**Rich link (smart chip) extraction:**
- When users paste Workspace URLs that render as smart chips, the URL
  is stripped from the `text` field and only available in annotations
- New `_extract_rich_links()` extracts RICH_LINK annotation URIs
- Surfaced as `[linked: <url>]` in get_messages and search_messages

**Thread support:**
- get_messages shows `[thread: ...]` for threaded replies
- send_message gains `thread_name` param for replying in existing threads
  using `messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`
- Fixes existing `thread_key` param which was missing messageReplyOption

**Emoji reactions:**
- get_messages shows `[reactions: 👍x3, 🎉x1]` from emojiReactionSummaries
- New `create_reaction` tool to add emoji reactions to messages
2026-02-17 17:28:29 -07:00
Taylor Wilsdon
6322bf8f67 chore: release v1.11.5 2026-02-17 16:54:01 -05:00
Taylor Wilsdon
1d4efd4376 bump 2026-02-17 16:53:53 -05:00
Taylor Wilsdon
f8b7ef16ce chore: release v1.11.4 2026-02-17 16:52:08 -05:00
Taylor Wilsdon
d3bbd4eec5 bump 2026-02-17 16:51:56 -05:00
Taylor Wilsdon
c0cdaa6e39 chore: release v1.11.3 2026-02-17 16:50:47 -05:00
Taylor Wilsdon
b86dba469b clean up dxt, update license in pyproject 2026-02-17 16:50:38 -05:00
Taylor Wilsdon
9df78a2e16 Merge pull request #436 from the-gigi-pplx/feature/doc-links
Add hyperlink support to modify_doc_text
2026-02-17 15:10:44 -05:00
Taylor Wilsdon
1eae403b64 add link url 2026-02-17 14:54:34 -05:00