mcp-gee-sweet 0.8.2.dev45__tar.gz → 0.8.2.dev51__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/commands/merge-pr.md +4 -2
  2. mcp_gee_sweet-0.8.2.dev51/.claude/commands/retro.md +23 -0
  3. mcp_gee_sweet-0.8.2.dev51/.claude/settings.json +5 -0
  4. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/team-roles/amy.md +8 -0
  5. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/team-roles/aziz.md +9 -0
  6. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/team-roles/dev.md +9 -0
  7. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/team-roles/kai.md +8 -0
  8. mcp_gee_sweet-0.8.2.dev51/.claude/team-roles/qa.md +23 -0
  9. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/CLAUDE.md +1 -1
  10. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/PKG-INFO +3 -3
  11. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/README.md +2 -2
  12. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/configuration.md +1 -1
  13. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/run.md +1 -0
  14. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/tests/sheets_mgmt.md +261 -0
  15. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/roadmap.md +2 -2
  16. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/tools.md +4 -1
  17. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/sheets/structure.py +283 -0
  18. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/sheets/test_structure.py +291 -0
  19. mcp_gee_sweet-0.8.2.dev45/.claude/team-roles/qa.md +0 -13
  20. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/commands/cleanup-worktrees.md +0 -0
  21. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/commands/orchestrator.md +0 -0
  22. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/commands/prep-for-pr.md +0 -0
  23. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/commands/release.md +0 -0
  24. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/commands/start-worktree.md +0 -0
  25. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/commands/team-member.md +0 -0
  26. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.claude/commands/verify-pr.md +0 -0
  27. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.dockerignore +0 -0
  28. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  29. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  30. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  31. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.github/dependabot.yml +0 -0
  32. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.github/workflows/ci.yml +0 -0
  33. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.github/workflows/docs.yml +0 -0
  34. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.github/workflows/publish-dev.yml +0 -0
  35. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.github/workflows/release.yml +0 -0
  36. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.gitignore +0 -0
  37. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.pre-commit-config.yaml +0 -0
  38. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/.python-version +0 -0
  39. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/CHANGELOG.md +0 -0
  40. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/CODE_OF_CONDUCT.md +0 -0
  41. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/CONTRIBUTING.md +0 -0
  42. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/Dockerfile +0 -0
  43. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/LICENSE +0 -0
  44. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/Makefile +0 -0
  45. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/SECURITY.md +0 -0
  46. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docker-compose.yml +0 -0
  47. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/auth.md +0 -0
  48. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/client-setup.md +0 -0
  49. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-async-tool-execution.md +0 -0
  50. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-cache-invalidation.md +0 -0
  51. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-chart-theming.md +0 -0
  52. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-composite-tools.md +0 -0
  53. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-dev-team.md +0 -0
  54. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-docs-formatting.md +0 -0
  55. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-fork.md +0 -0
  56. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-grid-data-size-cap.md +0 -0
  57. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-publishing.md +0 -0
  58. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-release-docs-roles.md +0 -0
  59. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-repositioning.md +0 -0
  60. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-response-size-cap-generalization.md +0 -0
  61. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/decision-testing.md +0 -0
  62. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/decisions/index.md +0 -0
  63. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/design/docs-ast-pipeline.md +0 -0
  64. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/design/effectiveformat-spike.md +0 -0
  65. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/design/index.md +0 -0
  66. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/design/markdown-support.md +0 -0
  67. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/design/phase3-theme-system.md +0 -0
  68. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/design.md +0 -0
  69. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/index.md +0 -0
  70. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/known-limitations.md +0 -0
  71. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/notes-read.md +0 -0
  72. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/README.md +0 -0
  73. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/fixtures/tc-d195-create-doc.md +0 -0
  74. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/fixtures/tc-d196-create-doc.html +0 -0
  75. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/fixtures/tc-d213-dollar-escape.md +0 -0
  76. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/fixtures/tc-d226-heading-table.md +0 -0
  77. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/fixtures.template.md +0 -0
  78. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/operations.yaml +0 -0
  79. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/playwright_oauth.md +0 -0
  80. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/.gitkeep +0 -0
  81. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-06-02.md +0 -0
  82. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-06-14.md +0 -0
  83. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-06-17.md +0 -0
  84. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-06-18.md +0 -0
  85. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-06-21-drive-discovery.md +0 -0
  86. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-06-21-sheets-delete-clear.md +0 -0
  87. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-06-28.md +0 -0
  88. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-07-04-docs.md +0 -0
  89. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-07-04-drive-smoke.md +0 -0
  90. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-07-04-infra.md +0 -0
  91. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-07-04-sheets_read.md +0 -0
  92. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/results/2026-07-04.md +0 -0
  93. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/retro-v0.8.0.md +0 -0
  94. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/runs/README.md +0 -0
  95. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/runs/v0.8.0.md +0 -0
  96. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/runs/v0.8.1.md +0 -0
  97. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/setup.md +0 -0
  98. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/tests/calendar.md +0 -0
  99. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/tests/docs.md +0 -0
  100. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/tests/drive.md +0 -0
  101. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/tests/infra.md +0 -0
  102. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/tests/sheets_charts.md +0 -0
  103. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/tests/sheets_read.md +0 -0
  104. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa/tests/sheets_write.md +0 -0
  105. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/docs/qa-checklist.md +0 -0
  106. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/mkdocs.yml +0 -0
  107. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/pyproject.toml +0 -0
  108. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/pyrightconfig.json +0 -0
  109. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/scripts/gen_tool_docs.py +0 -0
  110. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/scripts/oauth_setup.py +0 -0
  111. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/scripts/setup_team.sh +0 -0
  112. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/.env.template +0 -0
  113. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/__init__.py +0 -0
  114. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/auth.py +0 -0
  115. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/cache.py +0 -0
  116. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/http_transport.py +0 -0
  117. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/server.py +0 -0
  118. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/__init__.py +0 -0
  119. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/cache.py +0 -0
  120. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/calendar.py +0 -0
  121. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/docs/__init__.py +0 -0
  122. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/docs/ast.py +0 -0
  123. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/docs/content.py +0 -0
  124. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/docs/emitter.py +0 -0
  125. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/docs/html_parser.py +0 -0
  126. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/docs/layout.py +0 -0
  127. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/docs/style.py +0 -0
  128. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/docs/tables.py +0 -0
  129. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/drive/__init__.py +0 -0
  130. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/drive/activity.py +0 -0
  131. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/drive/files.py +0 -0
  132. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/drive/sharing.py +0 -0
  133. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/drive/transfer.py +0 -0
  134. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/response_limits.py +0 -0
  135. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/sheets/__init__.py +0 -0
  136. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/sheets/data.py +0 -0
  137. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/src/mcp_gee_sweet/tools/sheets/helpers.py +0 -0
  138. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/__init__.py +0 -0
  139. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/drive/__init__.py +0 -0
  140. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/drive/test_activity.py +0 -0
  141. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/drive/test_files.py +0 -0
  142. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/drive/test_sharing.py +0 -0
  143. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/drive/test_transfer.py +0 -0
  144. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/sheets/__init__.py +0 -0
  145. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/sheets/test_data.py +0 -0
  146. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/sheets/test_helpers.py +0 -0
  147. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_auth.py +0 -0
  148. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_cache.py +0 -0
  149. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_calendar.py +0 -0
  150. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_docs_content.py +0 -0
  151. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_docs_core.py +0 -0
  152. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_docs_layout.py +0 -0
  153. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_docs_style.py +0 -0
  154. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_docs_tables.py +0 -0
  155. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_gen_tool_docs.py +0 -0
  156. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_response_limits.py +0 -0
  157. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/tests/test_server.py +0 -0
  158. {mcp_gee_sweet-0.8.2.dev45 → mcp_gee_sweet-0.8.2.dev51}/uv.lock +0 -0
@@ -6,6 +6,7 @@ Merge the current branch's PR and clean up its worktree. Uses `--admin` only to
6
6
  - Every check in `statusCheckRollup` (in particular "Lint and test") must show success. If anything is failing or still pending, stop and report which — do not merge, and do not wait/poll.
7
7
  - `mergeable` must not be `CONFLICTING`.
8
8
  - If the branch's second `/`-separated segment is one of the four dev-lane slot names (`ash`, `sky`, `jay`, `kit` — the type prefix in front varies, `feat`/`fix`/`chore`/etc., don't assume `feat`), it must carry the `qa-approved` label (check `gh pr view <number> --json labels`). If it doesn't, stop — that means the paired QA agent (`/team-member`) hasn't signed off yet; don't merge and don't review it yourself here. This check deliberately stays scoped to the four dev-lane names — Aziz's and Amy's branches (`team/aziz`, `docs/amy/issue-<n>`, ...) aren't part of the Dev/QA pairing and go through normal review instead.
9
+ - **Exception:** a QA-named slot (`sky`/`kit`) authoring its own process/meta PR (e.g. `chore/sky/...`) has no natural QA partner to self-approve — the Dev/QA pairing only exists for the *other* lane's ticket work. There's no label path for this case; stop and ask the user directly whether it's safe to merge without one, same as any missing-label PR. If they confirm (e.g. because it's a prompting/process change with no application-code risk), proceed — that confirmation stands in for the label for this PR only, it doesn't waive the check generally.
9
10
  3. Show the user a summary: PR number, title, URL, check status, and review status (expected to be blocked only on the missing-approval requirement). State plainly that merging will use `--admin` to bypass that review gate. Ask for explicit confirmation before proceeding.
10
11
  4. On confirmation, squash-merge (matching this repo's existing history — commits land on `develop` as a single `title (#number)` commit): `gh pr merge <number> --admin --squash`. The remote branch is auto-deleted on merge (repo setting), so don't pass `--delete-branch`.
11
12
  5. Clean up:
@@ -14,5 +15,6 @@ Merge the current branch's PR and clean up its worktree. Uses `--admin` only to
14
15
  - If this session created the current worktree (i.e. it got here via `/start-worktree` or `/next-issue` earlier in this same session), use `ExitWorktree` with `action: "remove"`.
15
16
  - Otherwise (worktree predates this session), fall back to manual cleanup from the main checkout: `git worktree remove <path>`, then `git branch -d <branch>`, then `git worktree prune`.
16
17
  6. Sweep the other five dev-team lanes for orphaned work on the same ticket. Pull the issue number out of the merged PR's title (e.g. `(#126)`). For each of the other dev-team worktrees (`ash`, `sky`, `jay`, `kit`, `aziz`, `amy`, minus whichever one just merged), run `git -C .claude/worktrees/<name> log --oneline develop..HEAD` and check whether any commit message references that same issue number. A hit means a sibling lane independently started the same ticket and lost the race — since it never became a PR, nothing else would ever clean it up. Don't reset it silently: a squash merge means SHAs (and even diffs) won't match even for genuinely identical content, so show the user the commit list and confirm it's a duplicate before resetting — same idle-reset procedure as step 5 (`git checkout team/<name>`, `git reset --hard origin/develop`, delete the stale branch if it had its own name).
17
- 7. Update the roadmap: from the main checkout on `develop`, `git pull` then check `docs/roadmap.md` for a checkbox line referencing the issue(s) this PR closes (search by issue number). If found, check it off (`- [ ]` → `- [x]`) and append `(PR <number>)` in the existing style (e.g. `(PR #280)`) — see recent `- [x]` entries for the exact convention. If the roadmap has no line item for this issue (not every ticket is roadmap-tracked — chores, follow-up defects, etc.), skip this step silently. Commit directly to `develop` (`docs(roadmap): check off #<issue> (PR <number>)`) and push — `develop`'s branch protection has `enforce_admins: false`, so a direct push by the repo owner is allowed for this kind of small, reversible, docs-only change; don't open a separate PR for it.
18
- 8. Report a summary: the merge commit, the now-merged PR URL, confirmation the worktree was removed, whether any sibling-lane duplicate was found and reset, and whether the roadmap was updated.
18
+ 7. From the main checkout on `develop`, `git pull` — unconditionally, even if step 8 turns out to be a no-op. `gh pr merge` merges via the API; it never touches the main checkout's local branch, so skipping this leaves Kai's live-testing home base stale until the next unrelated pull happens to catch it up.
19
+ 8. Update the roadmap: check `docs/roadmap.md` for a checkbox line referencing the issue(s) this PR closes (search by issue number). If found, check it off (`- [ ]` → `- [x]`) and append `(PR <number>)` in the existing style (e.g. `(PR #280)`) — see recent `- [x]` entries for the exact convention. If the roadmap has no line item for this issue (not every ticket is roadmap-tracked — chores, follow-up defects, etc.), skip this step silently. Commit directly to `develop` (`docs(roadmap): check off #<issue> (PR <number>)`) and push — `develop`'s branch protection has `enforce_admins: false`, so a direct push by the repo owner is allowed for this kind of small, reversible, docs-only change; don't open a separate PR for it.
20
+ 9. Report a summary: the merge commit, the now-merged PR URL, confirmation the worktree was removed, whether any sibling-lane duplicate was found and reset, and whether the roadmap was updated.
@@ -0,0 +1,23 @@
1
+ Process the friction and findings from the unit of work you just finished — a PR reviewed, a ticket implemented, a release cut, a doc pass, an orchestration cycle — into a durable form, so the next session in your seat doesn't rediscover the same thing from scratch.
2
+
3
+ This is discretionary, not a gate. No role's process file requires running this — invoke it when you actually hit friction worth preserving, skip it when a pass was clean. Symmetric with `/team-member`/`/next-issue` on the other end of a work cycle: those are prompts you may follow to *pick up* work; this is the one for *closing out* a piece of it.
4
+
5
+ **Only process real findings from the work you just did.** Don't invent hypothetical friction to fill out the exercise, and don't pad with things this file already tells you to do routinely (e.g. a QA coverage gap that blocks the PR itself — that's handled inline by `qa.md`/`verify-pr.md`, not a retro item). If nothing survives that filter, say so and stop.
6
+
7
+ ## The two dispositions
8
+
9
+ For each real finding, decide which bucket it belongs in — most sessions will have some of both:
10
+
11
+ **Ticket** — a durable product or system finding that needs to be scheduled, prioritized, or fixed by someone later: a bug, a coverage gap, a design inconsistency, tech debt. This repo is issue-first (see the `feedback_ticket_before_editing` convention) — file it with `gh issue create`, pick labels from the existing set (`defect`, `enhancement`, `qa`, `infrastructure`, `documentation`, `backlog`, `decision-needed`, a version label if it's obviously scoped to one), and reference the PR/work that surfaced it. Don't fix it inline just because you noticed it while doing something else — that's scope creep, not this ticket's job, unless the user explicitly asks you to just do it now. Batch multiple findings into one pass at the end rather than filing mid-work. Roadmap grooming (folding the new issue into `docs/roadmap.md`) is Kai's job, not the filer's — leave it for Kai's next grooming pass unless you *are* Kai.
12
+
13
+ Before filing, triage defect vs. hardening honestly: has a failure actually been observed (a wrong result, a crash, a silently-corrupted state), or are you flagging an input this code merely doesn't validate yet? The latter is real and worth a ticket, but label and word it as hardening, not as a confirmed defect — don't let "I found something" inflate its severity.
14
+
15
+ **Command decision** — operational knowledge that should change how the *next* session in this same seat behaves: a process gap, a doc gap, a technique that worked (or didn't), a fixture gotcha, a missing step in a skill file. This isn't roadmap-worthy scope, so skip the ticket — edit the relevant process/skill doc directly, right now, and say what you changed. Examples already in this repo: `docs/qa/run.md`'s Playwright limitations list, `docs/qa/retro-v0.8.0.md`'s action items, a role file's own process fixes.
16
+
17
+ ## Your role's details
18
+
19
+ Read the `## Retro` section in your own role file (`.claude/team-roles/<role>.md`) for the friction categories specific to your seat and which docs each maps to. If that section doesn't exist yet, you're the first to run this from that seat — add one, following the pattern already written for the other roles, and say so in your report.
20
+
21
+ ## Report
22
+
23
+ State what you filed (issue numbers + one-line summaries) and what you changed directly (files + one-line summaries). Don't just say "processed 3 findings" — name them, the same way you'd report any other work.
@@ -0,0 +1,5 @@
1
+ {
2
+ "worktree": {
3
+ "bgIsolation": "none"
4
+ }
5
+ }
@@ -12,3 +12,11 @@ Amy keeps documentation accurate, friendly, comprehensive, and fun — README, `
12
12
  - **On any other branch (mid-ticket):** report status rather than claiming new work.
13
13
 
14
14
  Amy has no dedicated MCP server and doesn't need QA-approved sign-off to merge (docs-only PRs aren't gated by `qa-approved`) — normal `/merge-pr` review still applies.
15
+
16
+ ## Retro
17
+
18
+ Friction Amy typically hits after a doc pass, and where it goes — see `/retro` for the general ticket-vs-command-decision split:
19
+
20
+ - **Doc-vs-reality drift found while writing** — an existing doc described behavior that turned out wrong once checked against actual code or live tool output. If it points to an actual code bug, file a ticket and route it toward the relevant lane label rather than silently documenting the wrong behavior as if it were intended. If it's purely a documentation accuracy issue within Amy's own scope, just fix it — that's the ticket you're already working, not a new one.
21
+ - **Generated-doc drift** — `docs/tools.md` or `docs/configuration.md` out of sync in a way `scripts/gen_tool_docs.py` doesn't catch (the script's job, not this file's, when it does catch it). File an `infrastructure`-labeled ticket, parallel to #308.
22
+ - **Competitive/positioning claims needing re-verification** and **redundant/overlapping issues** already have their own handling above (step 4's roadmap-Tier-4 routing, step 1's consolidation) — not new retro items, don't re-litigate them here.
@@ -15,3 +15,12 @@ Aziz doesn't work a ticket queue — he runs at release cadence: review everythi
15
15
  9. **Sign off.** Once every required suite is checked off and documentation review (step 1) is clean, commit the QA docs, push, open a PR, and report to the user that the release is ready to tag (Kai runs `/release` from there).
16
16
 
17
17
  For a **minor/dev release** that only needs Smoke: same flow, but step 2's audit will usually conclude Smoke alone suffices — Aziz still runs it live and records real results, just against a smaller case set.
18
+
19
+ ## Retro
20
+
21
+ Friction Aziz typically hits after a release pass, and where it goes — see `/retro` for the general ticket-vs-command-decision split:
22
+
23
+ - **Release-scope audit surprises** — a merged PR turns out to lack adequate doc/test coverage, or a QA-tier call feels wrong in hindsight once results are in. If it's a gap in one already-merged feature, file a ticket. If it's the scoped-gating process itself (`docs/qa/runs/README.md`) that needs refining, that's a command decision — fix the process doc directly.
24
+ - **Subagent-sharding friction** — a shard's instructions were ambiguous, or two shards' fixture ownership collided. Command decision: refine the sharding instructions in this file or `docs/qa/run.md`'s mutex section, don't just work around it silently next time.
25
+ - **Bugs found during the compile step** are routine, not a retro item — route them to the responsible Dev lane per step 8 above.
26
+ - **This role already has a heavier version of this pattern**: for a full regression run, Aziz writes `docs/qa/retro-vX.Y.Z.md` (see `retro-v0.8.0.md`) with its own "what went well / what didn't / action items" structure. Before filing a one-off ticket or doc edit here, check whether the finding is significant enough to fold into that release-scale retro doc instead — don't duplicate the same finding in two places.
@@ -15,3 +15,12 @@ Branch naming for this slot always puts `<name>` as the **second** `/`-separated
15
15
  - **On any other branch:** check this branch's PR history: `gh pr list --head <branch> --state all --json number,state,mergedAt`.
16
16
  - **A `MERGED` entry exists:** this ticket already shipped and this slot was never reset (e.g. Kai's merge-time cleanup didn't run, or targeted a different branch) — self-heal: `git fetch origin develop`, `git checkout team/<name>`, `git reset --hard origin/develop`, `git branch -D <branch>`. Then treat this slot as idle and fall through to the idle-branch flow above to pick up the next ticket.
17
17
  - **No `MERGED` entry (open, closed-without-merge, or no PR at all):** mid-ticket — report status: whether a PR is already open, what CI/QA said if anything, and whether it's waiting on QA or on further work — rather than claiming a new ticket. Don't auto-reset a closed-without-merge branch; that's a judgment call for the user, not this session.
18
+
19
+ ## Retro
20
+
21
+ Friction Dev (Ash/Jay) typically hits after finishing a ticket, and where it goes — see `/retro` for the general ticket-vs-command-decision split:
22
+
23
+ - **Design/architecture surprises** — an existing pattern didn't generalize the way expected mid-implementation (a sibling function skipped a step this one needed, a helper needed restructuring to fit a new case). If it's about how future Devs should approach similar work, that's a command decision: add a note to `CLAUDE.md` or a `docs/design/` snapshot. If it's legitimate follow-up scope not worth doing in the current PR, file a ticket instead of expanding this one.
24
+ - **Scope creep discovered while implementing** — related, unshipped bugs or gaps adjacent to the ticket but not part of its acceptance criteria. Ticket, don't fold into the current PR.
25
+ - **Stale or missing `CLAUDE.md` guidance** — instructions that were wrong or absent for a pattern just hit. Command decision: fix `CLAUDE.md` directly, it's this repo's own process doc.
26
+ - **QA-authoring ambiguity** — writing test cases in `docs/qa/tests/` surfaced an unclear tagging rule or fixture assumption in `run.md`/`setup.md`. Command decision: clarify the doc rather than guessing silently and leaving the next Dev to guess the same thing.
@@ -20,3 +20,11 @@ Why this role split exists: any locally-configured MCP server that runs this pro
20
20
  - Release readiness and documentation quality are Aziz's and Amy's territory, not Kai's — when cutting a release, hand off to Aziz (`/team-member Aziz`) for the review/QA-tier/sign-off pass rather than doing it here; route doc gaps found along the way to Amy (`documentation` label) rather than fixing them inline.
21
21
 
22
22
  Do NOT pick up ticket implementation directly in this session — hand it to a worker session via `start-worktree` (or `next-issue`, which does this automatically), or to a dev-team lane via `/team-member` if the team is active.
23
+
24
+ ## Retro
25
+
26
+ Friction Kai typically hits during coordination, and where it goes — see `/retro` for the general ticket-vs-command-decision split:
27
+
28
+ - **Process friction across the team** — another session's role file turned out ambiguous or wrong when actually followed (a stale worktree, a label race, a step that assumed state that wasn't there). Command decision: fix the relevant `.claude/team-roles/*.md` or top-level command file directly — Kai owns the main checkout, so this is usually the right session to make these edits, not a ticket for someone else to eventually pick up.
29
+ - **Roadmap drift** — a shipped PR wasn't checked off in `docs/roadmap.md`, or a version label doesn't match where the work actually landed. Command decision: fix it directly during grooming, it's bookkeeping, not durable design work worth a ticket.
30
+ - **Systemic bugs spotted while merging or triaging that don't belong to the ticket at hand** — file a ticket rather than expanding scope on someone else's PR.
@@ -0,0 +1,23 @@
1
+ QA role (Sky / Kit). Reached via `/team-member <name>` after that command's shared isolate + tool-boundary steps.
2
+
3
+ Find the partner Dev's open PR by matching the branch's second `/`-separated segment against the partner's lowercase name — not a `feat/`-specific prefix, since the Dev's branch type varies: `gh pr list --state open --json number,headRefName,url --jq '[.[] | select((.headRefName | split("/"))[1] == "<partner>")]'`. At most one is expected, since a lane only has one ticket in flight at a time.
4
+
5
+ - **None found:** self-heal first — `git fetch origin develop`. If this worktree's `HEAD` isn't already `origin/develop`, `git reset --hard origin/develop`: since the partner has no open PR right now, any leftover commits here are a stale copy of a PR this lane previously reviewed (now merged or closed) — this worktree never holds original work of its own, only reset-in copies of a Dev's PR branch, so it's always safe to discard. Then report that Lane {A/B} has nothing to verify right now.
6
+ - **One found:** this is now essentially `/verify-pr`'s steps 4 onward, but simpler — this worktree already IS a dedicated review space, so skip `/verify-pr`'s steps 1–3 (the main-checkout precondition and the `review/<branch>` fetch trick don't apply here):
7
+ 1. `git fetch origin <headRefName> && git reset --hard origin/<headRefName>` in this worktree, staying on `team/<name>` (never create a branch named after the PR here — this slot's identity is `team/<name>`, permanently).
8
+ 2. Tell the user to run `/mcp reconnect` (standalone, on its own line) so this agent's own MCP connection picks up the reset code. Wait for confirmation.
9
+ 3. Run `/code-review` at `high` effort against `origin/develop...HEAD`.
10
+ 4. Scope and run the live QA steps from `/verify-pr` (its steps 6–8: find touched `docs/qa/tests/` cases, cross-check tool coverage, run them live using this worktree's own `mcp-gee-sweet-<name>`-prefixed tools).
11
+ 5. Record `**Result**` entries for every case actually run.
12
+ 6. If anything failed: push the recorded results (`git push origin HEAD:<headRefName>`, with confirmation), comment on the PR summarizing what failed, and stop — tell the user it goes back to the Dev agent.
13
+ 7. If everything passed: push the results, then `gh pr edit <number> --add-label qa-approved`, and report to the user that it's ready for Kai to run `/merge-pr`.
14
+
15
+ ## Retro
16
+
17
+ Friction QA (Sky/Kit) typically hits after a pass, and where it goes — see `/retro` for the general ticket-vs-command-decision split:
18
+
19
+ - **Fixture drift/pollution** — the shared spreadsheet/doc accumulates stray objects (charts, temp sheets/rows, leftover permissions) from earlier test runs, breaking `docs/qa/setup.md`'s "Known fixture state" assumptions or blocking visual verification. If a specific test category is the source (e.g. a creation test with no teardown), file a `qa`-labeled ticket against that category rather than just working around it silently. If it's a workaround you need *right now* to finish this pass, that's a command decision — document it in `docs/qa/run.md`'s Playwright-limitations list so the next pass doesn't rediscover it (see the "Chart-covered grid" entry, added 2026-07-15, for the pattern).
20
+ - **Playwright verification gaps** — an element is structurally unreachable or invisible to the browser tools (outside the viewport, canvas-rendered with no accessible geometry, obscured by other content). Command decision: add it to `run.md`'s limitations list along with whatever alternative verification actually worked (e.g. `get_sheet_data(..., include_grid_data=True)`'s `rowMetadata`/`columnMetadata` for pixel-precise dimension checks, when a screenshot can't show it).
21
+ - **Test tag drift** — `⚠️ requires-oauth` or `**Playwright: required**` no longer matches a test case's actual behavior. Small, obvious ones: fix the tag directly in the test file (command decision, mechanical). Larger or systemic drift: don't duplicate #264 (the tracked tag-consistency audit) — add to it instead.
22
+ - **Code-review findings that are minor or systemic rather than PR-blocking** — input-validation gaps, duplicated helpers, style inconsistencies that the new code merely repeats from an existing convention rather than introduces. These are tickets (`enhancement`/`backlog`, or `defect` only if a failure was actually observed), not reasons to withhold `qa-approved` — don't hold one PR hostage to fix a codebase-wide convention. See #323 for the shape this takes (validation + dedup findings from the same review, bundled into one issue since they shared a root cause).
23
+ - **Coverage gaps in the PR itself** (a changed tool with no QA test case at all) are not a retro item — that blocks the pass and is handled inline per this file's step 4 / `verify-pr.md` step 6, not deferred here.
@@ -32,7 +32,7 @@ Tests live in `tests/` and can be run with `uv run pytest`.
32
32
  Logic is split across `src/mcp_gee_sweet/`: `server.py` (MCP setup, tool decorator, resources), `auth.py` (lifespan, `SpreadsheetContext`), and `tools/` (domain-based layout):
33
33
 
34
34
  - `tools/sheets/data.py` — read/write cell data (`get_sheet_data`, `get_sheet_formulas`, `get_multiple_*`, `find_in_spreadsheet`, `clear_values`, `update_cells`, `batch_update_cells`, `batch_update`)
35
- - `tools/sheets/structure.py` — sheet structure (`list_sheets`, `copy_sheet`, `duplicate_sheet`, `rename_sheet`, `create_sheet`, `delete_sheet`, `add_rows`, `add_columns`, `delete_rows`, `delete_columns`, `hide_rows`, `unhide_rows`, `hide_columns`, `unhide_columns`, `format_cells`, `merge_cells`, `unmerge_cells`, `freeze`, `update_sheet_properties`, `sort_range`, `add_chart`)
35
+ - `tools/sheets/structure.py` — sheet structure (`list_sheets`, `copy_sheet`, `duplicate_sheet`, `rename_sheet`, `create_sheet`, `delete_sheet`, `add_rows`, `add_columns`, `delete_rows`, `delete_columns`, `hide_rows`, `unhide_rows`, `hide_columns`, `unhide_columns`, `resize_rows`, `resize_columns`, `format_cells`, `update_borders`, `merge_cells`, `unmerge_cells`, `freeze`, `update_sheet_properties`, `sort_range`, `add_chart`)
36
36
  - `tools/sheets/helpers.py` — A1 notation helpers (`_parse_a1_notation`, `_column_index_to_letter`, etc.)
37
37
  - `tools/drive/files.py` — file/folder operations (`create_spreadsheet`, `import_csv_to_sheet`, `list_spreadsheets`, `list_files`, `search_files`, `create_folder`, `copy_file`, `move_file`, `rename_file`, `delete_file`, `list_shared_with_me`, `list_recent_files`, `get_storage_quota`, etc.)
38
38
  - `tools/drive/sharing.py` — permissions (`share_spreadsheet`, `share_file`, `list_permissions`, `update_permission`, `remove_permission`)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-gee-sweet
3
- Version: 0.8.2.dev45
3
+ Version: 0.8.2.dev51
4
4
  Summary: MCP server for Google Workspace — Sheets, Drive, Docs, and Calendar. 60+ tools for AI clients.
5
5
  Project-URL: Homepage, https://github.com/khuisman/mcp-gee-sweet
6
6
  Project-URL: Bug Tracker, https://github.com/khuisman/mcp-gee-sweet/issues
@@ -27,7 +27,7 @@ Description-Content-Type: text/markdown
27
27
  ![GitHub License](https://img.shields.io/github/license/khuisman/mcp-gee-sweet)
28
28
  </div>
29
29
 
30
- An MCP server that gives AI clients reliable, direct access to Google Workspace — Sheets, Drive, Docs, and Calendar. 90 tools across four domains.
30
+ An MCP server that gives AI clients reliable, direct access to Google Workspace — Sheets, Drive, Docs, and Calendar. 101 tools across four domains.
31
31
 
32
32
  As of mid-2026, Google's own Workspace MCP servers (Developer Preview) cover Gmail, Drive, Calendar, People, and Chat — Sheets and Docs still have no official server at all, and Drive/Calendar coverage there is a fraction of what's here. Stable releases ship to PyPI behind a QA regression gate, with a raw `batch_update` passthrough as an escape hatch for anything a named tool doesn't cover yet. See [Why it exists](https://khuisman.github.io/mcp-gee-sweet/#why-it-exists) for the full, sourced comparison against both the official servers and community alternatives.
33
33
 
@@ -124,7 +124,7 @@ See [Client Setup](https://khuisman.github.io/mcp-gee-sweet/latest/client-setup/
124
124
 
125
125
  ## Docs
126
126
 
127
- - [Tools](https://khuisman.github.io/mcp-gee-sweet/latest/tools/) — full tool reference (90 tools)
127
+ - [Tools](https://khuisman.github.io/mcp-gee-sweet/latest/tools/) — full tool reference (101 tools)
128
128
  - [Authentication](https://khuisman.github.io/mcp-gee-sweet/latest/auth/) — all four auth methods
129
129
  - [Configuration](https://khuisman.github.io/mcp-gee-sweet/latest/configuration/) — env vars, caching, tool filtering
130
130
  - [Client Setup](https://khuisman.github.io/mcp-gee-sweet/latest/client-setup/) — MCP client config examples
@@ -5,7 +5,7 @@
5
5
  ![GitHub License](https://img.shields.io/github/license/khuisman/mcp-gee-sweet)
6
6
  </div>
7
7
 
8
- An MCP server that gives AI clients reliable, direct access to Google Workspace — Sheets, Drive, Docs, and Calendar. 90 tools across four domains.
8
+ An MCP server that gives AI clients reliable, direct access to Google Workspace — Sheets, Drive, Docs, and Calendar. 101 tools across four domains.
9
9
 
10
10
  As of mid-2026, Google's own Workspace MCP servers (Developer Preview) cover Gmail, Drive, Calendar, People, and Chat — Sheets and Docs still have no official server at all, and Drive/Calendar coverage there is a fraction of what's here. Stable releases ship to PyPI behind a QA regression gate, with a raw `batch_update` passthrough as an escape hatch for anything a named tool doesn't cover yet. See [Why it exists](https://khuisman.github.io/mcp-gee-sweet/#why-it-exists) for the full, sourced comparison against both the official servers and community alternatives.
11
11
 
@@ -102,7 +102,7 @@ See [Client Setup](https://khuisman.github.io/mcp-gee-sweet/latest/client-setup/
102
102
 
103
103
  ## Docs
104
104
 
105
- - [Tools](https://khuisman.github.io/mcp-gee-sweet/latest/tools/) — full tool reference (90 tools)
105
+ - [Tools](https://khuisman.github.io/mcp-gee-sweet/latest/tools/) — full tool reference (101 tools)
106
106
  - [Authentication](https://khuisman.github.io/mcp-gee-sweet/latest/auth/) — all four auth methods
107
107
  - [Configuration](https://khuisman.github.io/mcp-gee-sweet/latest/configuration/) — env vars, caching, tool filtering
108
108
  - [Client Setup](https://khuisman.github.io/mcp-gee-sweet/latest/client-setup/) — MCP client config examples
@@ -70,7 +70,7 @@ Access logs are emitted at `INFO` level — they appear when `DEBUG_LEVEL` is `D
70
70
 
71
71
  <!-- Auto-generated by `scripts/gen_tool_docs.py` — do not edit by hand, your changes will be overwritten on the next commit. -->
72
72
 
73
- By default all 100 tools are registered. Use `ENABLED_TOOLS` (or `--include-tools` on the CLI) to restrict the server to exactly the tools you need. This reduces the AI's context window cost — each registered tool is a name the model must reason about on every call.
73
+ By default all 103 tools are registered. Use `ENABLED_TOOLS` (or `--include-tools` on the CLI) to restrict the server to exactly the tools you need. This reduces the AI's context window cost — each registered tool is a name the model must reason about on every call.
74
74
 
75
75
  ```bash
76
76
  # Environment variable
@@ -36,6 +36,7 @@ When a test case is tagged `**Playwright: required**`, after the tool call the c
36
36
 
37
37
  - **Footer / header content** — Google Docs renders headers and footers outside the main document canvas. For short documents `window.scrollTo` does not bring the footer into the viewport. When a test involves `create_footer` or `create_header`, use the API response as confirmation; a Playwright snapshot of the body is still useful but will not show the footer content.
38
38
  - **Permission changes** — sharing confirmations are not visible in the Drive UI without navigating to the file's "Share" dialog. Use `list_permissions` API response as the confirmation source for share tests.
39
+ - **Chart-covered grid (Sales sheet)** — repeated `add_chart` test runs leave floating chart objects on the Sales sheet (they're never cleaned up between runs), and as of 2026-07-15 there were ~12 stacked overlapping charts covering roughly rows 1–22. This blocks visual verification of anything in that region — row-height/column-width changes (`resize_rows`/`resize_columns`), cell formatting, etc. are not visible in a screenshot, and Playwright's accessibility snapshot doesn't expose per-cell grid geometry either (only the charts' own accessible text). When a test in that area needs precise confirmation, use `get_sheet_data(..., range=<affected range>, include_grid_data=True)` instead — the raw response includes `rowMetadata`/`columnMetadata` with each row/column's actual `pixelSize`, which is more precise than a screenshot anyway. Longer term, `add_chart` QA test cases should delete the chart they create at the end of each run (see `docs/qa/tests/sheets_charts.md`) so the fixture doesn't accumulate; that cleanup is not yet in place.
39
40
 
40
41
  ### Coordinating Playwright across parallel shards
41
42
 
@@ -642,6 +642,174 @@ Tests marked **⚠️ destructive** rename or delete sheets — reset fixtures a
642
642
 
643
643
  ---
644
644
 
645
+ ## `resize_rows` / `resize_columns`
646
+
647
+ ### TC-S73: Resize a single row to an explicit pixel height ⚠️ destructive
648
+
649
+ **Prompt**
650
+ **Playwright: required**
651
+ > "Set row 5 (0-based index 4) on the Sales sheet in {SPREADSHEET_ID} to 60 pixels tall"
652
+
653
+ **Checks**
654
+ - `updateDimensionProperties` request sent with `dimension: ROWS`, `startIndex: 4`, `endIndex: 5`
655
+ - `properties.pixelSize: 60`, `fields: pixelSize`
656
+ - Row 5 visibly taller in the Sheets UI
657
+
658
+ **Result (2026-07-15) ✅ PASS** `resize_rows(spreadsheet_id, sheet="Sales", start_row=4, pixel_size=60)` → `{"replies":[{}]}`, no error. Playwright was skipped for this run — the shared fixture's Sales sheet currently has ~12 overlapping chart objects left over from other QA passes, which visually cover rows 1–22 and make row-height differences unreadable in a screenshot. Verified precisely instead via `get_sheet_data(..., range="A1:E6", include_grid_data=True)`, which returns `rowMetadata[].pixelSize` — confirmed row index 4 read back 60 immediately after this call (before being overwritten by TC-S74/TC-S75 below).
659
+
660
+ ---
661
+
662
+ ### TC-S74: Resize a range of rows ⚠️ destructive
663
+
664
+ **Prompt**
665
+ **Playwright: required**
666
+ > "Set rows 3 through 5 (0-based indices 2–4) on the Sales sheet in {SPREADSHEET_ID} to 40 pixels tall"
667
+
668
+ **Checks**
669
+ - `startIndex: 2`, `endIndex: 5` in the request (inclusive end_row=4 translated to exclusive 5)
670
+ - All three rows resize in the UI
671
+
672
+ **Result (2026-07-15) ✅ PASS** `resize_rows(spreadsheet_id, sheet="Sales", start_row=2, end_row=4, pixel_size=40)` → `{"replies":[{}]}`, no error. Confirmed via `get_sheet_data(..., range="A1:E6", include_grid_data=True)`: `rowMetadata` for row indices 2 and 3 both read back `pixelSize: 40` after the full test sequence (index 4 was subsequently auto-resized by TC-S75, as expected).
673
+
674
+ ---
675
+
676
+ ### TC-S75: Auto-resize rows to fit content ⚠️ destructive
677
+
678
+ **Prompt**
679
+ **Playwright: required**
680
+ > "Auto-fit the height of row 5 (0-based index 4) on the Sales sheet in {SPREADSHEET_ID} to its content"
681
+
682
+ **Setup:** Row 5 previously set to an oversized pixel height (e.g. TC-S73).
683
+
684
+ **Checks**
685
+ - `autoResizeDimensions` request sent with `dimensions.dimension: ROWS`, `startIndex: 4`, `endIndex: 5`
686
+ - Row 5 shrinks back to content-fit height in the Sheets UI
687
+
688
+ **Result (2026-07-15) ✅ PASS** `resize_rows(spreadsheet_id, sheet="Sales", start_row=4, auto_resize=True)` → `{"replies":[{}]}`, no error. Confirmed via `get_sheet_data(..., range="A1:E6", include_grid_data=True)`: row index 4's `pixelSize` read back as `21` (Sheets' default/content-fit height for plain text), down from the `40` set by TC-S74 moments earlier — confirms `autoResizeDimensions` fired and took effect.
689
+
690
+ ---
691
+
692
+ ### TC-S76: Resize rows — neither pixel_size nor auto_resize given returns error
693
+
694
+ **Prompt**
695
+ > "Resize row 0 on the Sales sheet in {SPREADSHEET_ID} without specifying a size or auto-fit"
696
+
697
+ **Checks**
698
+ - Response contains `error` field
699
+ - No `batchUpdate` call made
700
+
701
+ **Result (2026-07-15) ✅ PASS** `resize_rows(spreadsheet_id, sheet="Sales", start_row=0)` → `{"error":"Specify pixel_size or set auto_resize=True"}`. Returned before any batchUpdate call.
702
+
703
+ ---
704
+
705
+ ### TC-S77: Resize rows — both pixel_size and auto_resize given returns error
706
+
707
+ **Prompt**
708
+ > "Resize row 0 on the Sales sheet in {SPREADSHEET_ID} to 50 pixels and also auto-fit it"
709
+
710
+ **Checks**
711
+ - Response contains `error` field
712
+ - No `batchUpdate` call made
713
+
714
+ **Result (2026-07-15) ✅ PASS** `resize_rows(spreadsheet_id, sheet="Sales", start_row=0, pixel_size=50, auto_resize=True)` → `{"error":"Specify only one of pixel_size or auto_resize"}`. Returned before any batchUpdate call.
715
+
716
+ ---
717
+
718
+ ### TC-S78: Resize rows — sheet not found returns error
719
+
720
+ **Prompt**
721
+ > "Set row 0 to 50 pixels tall on a sheet called 'NoSuchSheet' in {SPREADSHEET_ID}"
722
+
723
+ **Checks**
724
+ - Response contains `error` field
725
+
726
+ **Result (2026-07-15) ✅ PASS** `resize_rows(spreadsheet_id, sheet="NoSuchSheet", start_row=0, pixel_size=50)` → `{"error":"Sheet 'NoSuchSheet' not found"}`.
727
+
728
+ ---
729
+
730
+ ### TC-S79: Resize a single column to an explicit pixel width ⚠️ destructive
731
+
732
+ **Prompt**
733
+ **Playwright: required**
734
+ > "Set column B (0-based index 1) on the Sales sheet in {SPREADSHEET_ID} to 200 pixels wide"
735
+
736
+ **Checks**
737
+ - `updateDimensionProperties` request sent with `dimension: COLUMNS`, `startIndex: 1`, `endIndex: 2`
738
+ - `properties.pixelSize: 200`, `fields: pixelSize`
739
+ - Column B visibly wider in the Sheets UI
740
+
741
+ **Result (2026-07-15) ✅ PASS** `resize_columns(spreadsheet_id, sheet="Sales", start_column=1, pixel_size=200)` → `{"replies":[{}]}`, no error. Playwright skipped — see "Chart-covered grid" note in `docs/qa/run.md`. Verified via `get_sheet_data(..., range="A1:E6", include_grid_data=True)`: column index 1's `pixelSize` read back `200` immediately after this call (before being overwritten by TC-S81 below).
742
+
743
+ ---
744
+
745
+ ### TC-S80: Resize a range of columns ⚠️ destructive
746
+
747
+ **Prompt**
748
+ **Playwright: required**
749
+ > "Set columns C through E (0-based indices 2–4) on the Sales sheet in {SPREADSHEET_ID} to 50 pixels wide"
750
+
751
+ **Checks**
752
+ - `startIndex: 2`, `endIndex: 5` in the request
753
+ - All columns in range resize in the UI
754
+
755
+ **Result (2026-07-15) ✅ PASS** `resize_columns(spreadsheet_id, sheet="Sales", start_column=2, end_column=4, pixel_size=50)` → `{"replies":[{}]}`, no error. Confirmed via `get_sheet_data(..., range="A1:E6", include_grid_data=True)`: column indices 2, 3, and 4 all read back `pixelSize: 50`.
756
+
757
+ ---
758
+
759
+ ### TC-S81: Auto-resize columns to fit content ⚠️ destructive
760
+
761
+ **Prompt**
762
+ **Playwright: required**
763
+ > "Auto-fit the width of column B (0-based index 1) on the Sales sheet in {SPREADSHEET_ID} to its content"
764
+
765
+ **Setup:** Column B previously set to an oversized pixel width (e.g. TC-S79).
766
+
767
+ **Checks**
768
+ - `autoResizeDimensions` request sent with `dimensions.dimension: COLUMNS`, `startIndex: 1`, `endIndex: 2`
769
+ - Column B shrinks back to content-fit width in the Sheets UI
770
+
771
+ **Result (2026-07-15) ✅ PASS** `resize_columns(spreadsheet_id, sheet="Sales", start_column=1, auto_resize=True)` → `{"replies":[{}]}`, no error. Confirmed via `get_sheet_data(..., range="A1:E6", include_grid_data=True)`: column index 1's `pixelSize` read back `28` (content-fit for the short numeric values in column B), down from the `200` set by TC-S79 — confirms `autoResizeDimensions` fired and took effect.
772
+
773
+ ---
774
+
775
+ ### TC-S82: Resize columns — neither pixel_size nor auto_resize given returns error
776
+
777
+ **Prompt**
778
+ > "Resize column 0 on the Sales sheet in {SPREADSHEET_ID} without specifying a size or auto-fit"
779
+
780
+ **Checks**
781
+ - Response contains `error` field
782
+ - No `batchUpdate` call made
783
+
784
+ **Result (2026-07-15) ✅ PASS** `resize_columns(spreadsheet_id, sheet="Sales", start_column=0)` → `{"error":"Specify pixel_size or set auto_resize=True"}`. Returned before any batchUpdate call.
785
+
786
+ ---
787
+
788
+ ### TC-S83: Resize columns — both pixel_size and auto_resize given returns error
789
+
790
+ **Prompt**
791
+ > "Resize column 0 on the Sales sheet in {SPREADSHEET_ID} to 100 pixels and also auto-fit it"
792
+
793
+ **Checks**
794
+ - Response contains `error` field
795
+ - No `batchUpdate` call made
796
+
797
+ **Result (2026-07-15) ✅ PASS** `resize_columns(spreadsheet_id, sheet="Sales", start_column=0, pixel_size=100, auto_resize=True)` → `{"error":"Specify only one of pixel_size or auto_resize"}`. Returned before any batchUpdate call.
798
+
799
+ ---
800
+
801
+ ### TC-S84: Resize columns — sheet not found returns error
802
+
803
+ **Prompt**
804
+ > "Set column 0 to 100 pixels wide on a sheet called 'NoSuchSheet' in {SPREADSHEET_ID}"
805
+
806
+ **Checks**
807
+ - Response contains `error` field
808
+
809
+ **Result (2026-07-15) ✅ PASS** `resize_columns(spreadsheet_id, sheet="NoSuchSheet", start_column=0, pixel_size=100)` → `{"error":"Sheet 'NoSuchSheet' not found"}`.
810
+
811
+ ---
812
+
645
813
  ## `format_cells`
646
814
 
647
815
  ### TC-S33: Apply bold and background color to a range ⚠️ destructive
@@ -761,6 +929,99 @@ Tests marked **⚠️ destructive** rename or delete sheets — reset fixtures a
761
929
 
762
930
  ---
763
931
 
932
+ ## `update_borders`
933
+
934
+ ### TC-S85: Apply a solid border around all four edges of a range ⚠️ destructive
935
+
936
+ **Prompt**
937
+ **Playwright: required**
938
+ > "Add a black solid border around all four edges of A1:D5 on the Sales sheet"
939
+
940
+ **Checks**
941
+ - `updateBorders` request sent with `top`, `bottom`, `left`, `right` all `style="SOLID"`
942
+ - `color` set to black on each edge
943
+ - `range` covers A1:D5
944
+ - No error in response
945
+
946
+ **Result (2026-07-16) ✅ PASS (API-verified, not visual)** The Sales sheet's A1:D5 region is fully covered by the known stacked-chart fixture pollution (see `run.md`'s "Chart-covered grid" entry), so a screenshot can't show the border. Used `get_sheet_data(range="A1:D5", include_grid_data=True)` instead: perimeter cells (row 1 all columns = top; row 5 all columns = bottom; column A all rows = left; column D all rows = right) all show `{"style": "SOLID", "color": {}}` (empty color = black), exactly matching the request. No error in the batchUpdate response.
947
+
948
+ ---
949
+
950
+ ### TC-S86: Apply dashed inner gridlines inside a range ⚠️ destructive
951
+
952
+ **Prompt**
953
+ **Playwright: required**
954
+ > "Add dashed inner horizontal and vertical borders inside A1:C3 on the Sales sheet"
955
+
956
+ **Checks**
957
+ - `updateBorders` request includes `innerHorizontal` and `innerVertical`, both `style="DASHED"`
958
+ - `top`/`bottom`/`left`/`right` are not set
959
+ - No error in response
960
+
961
+ **Result (2026-07-16) ✅ PASS (API-verified, not visual)** Same chart-coverage limitation as TC-S85 — verified via `get_sheet_data(range="A1:C3", include_grid_data=True)`. Interior cell edges between rows/columns show `DASHED`, while the pre-existing perimeter `SOLID` borders from TC-S85 (which this call's request did not include top/bottom/left/right keys for) were left completely untouched — confirming the tool only sends the edges it was given and doesn't clobber unspecified ones. No error in response.
962
+
963
+ ---
964
+
965
+ ### TC-S87: Clear an existing border edge with style NONE ⚠️ destructive
966
+
967
+ **Prompt**
968
+ **Playwright: required**
969
+ > "Remove the border from the right edge of A1:D5 on the Sales sheet"
970
+
971
+ **Checks**
972
+ - `updateBorders` request includes `right.style="NONE"`
973
+ - No error in response
974
+
975
+ **Result (2026-07-16) ✅ PASS (API-verified, not visual)** Same chart-coverage limitation. Verified via `get_sheet_data(range="D1:D5", include_grid_data=True)`: the `right` border is absent from every cell in column D after the call, while `top`/`bottom` borders from TC-S85 remain — confirming only the targeted edge was cleared. No error in response.
976
+
977
+ ---
978
+
979
+ ### TC-S88: update_borders — no border params returns error
980
+
981
+ **Checks (unit test)**
982
+ - Calling `update_borders` with no edge params returns `{"error": ...}`
983
+ - No batchUpdate API call made
984
+
985
+ **Result (2026-07-16) ✅ PASS** `test_no_params_returns_error` passes.
986
+
987
+ ---
988
+
989
+ ### TC-S89: update_borders — border spec missing style returns error
990
+
991
+ **Checks (unit test)**
992
+ - An edge dict without a `"style"` key returns `{"error": ...}` before any API call
993
+
994
+ **Result (2026-07-16) ✅ PASS** `test_missing_style_returns_error` passes.
995
+
996
+ ---
997
+
998
+ ### TC-S90: update_borders — invalid style value returns error
999
+
1000
+ **Checks (unit test)**
1001
+ - An unrecognized `style` value (e.g. `"SQUIGGLY"`) returns `{"error": ...}` listing valid styles, before any API call
1002
+
1003
+ **Result (2026-07-16) ✅ PASS** `test_invalid_style_returns_error` passes.
1004
+
1005
+ ---
1006
+
1007
+ ### TC-S91: update_borders — sheet not found returns error
1008
+
1009
+ **Checks (unit test)**
1010
+ - Sheet name not in spreadsheet → `{"error": "Sheet 'X' not found"}`
1011
+
1012
+ **Result (2026-07-16) ✅ PASS** `test_returns_error_when_sheet_not_found` passes.
1013
+
1014
+ ---
1015
+
1016
+ ### TC-S92: update_borders — non-string style value returns error, does not crash
1017
+
1018
+ **Checks (unit test)**
1019
+ - Calling `update_borders` with an edge dict whose `"style"` value is not a string (e.g. `top={"style": 5}` or `top={"style": None}`) returns `{"error": ...}`, same as the existing "invalid style" and "missing style" cases.
1020
+
1021
+ **Result (2026-07-16) ✅ PASS — fix verified** Originally failed: validation only checked `"style" not in border` (key presence) before calling `.upper()`, so a non-string style (e.g. `top={"style": 5}`) reached `border["style"].upper()` and crashed with an unhandled `AttributeError` instead of a clean error. Fixed by adding `if not isinstance(border["style"], str): return {"error": ...}` before the `.upper()` call. Verified three ways: unit test `test_non_string_style_returns_error` passes (covers both `5` and `None`); confirmed live against the real `update_borders` MCP tool with `top={"style": 5}` and `top={"style": null}` — both return `{"error": "Border spec for 'top' has a non-string 'style' value"}` with no crash. TC-S92 closed.
1022
+
1023
+ ---
1024
+
764
1025
  ## `freeze`
765
1026
 
766
1027
  ### TC-S42: Freeze the header row ⚠️ destructive
@@ -105,7 +105,7 @@ No new tools. Stabilize on what Tier 1 shipped before starting Tier 2 feature wo
105
105
  **Sheets**
106
106
  - [ ] `update_borders` — border style, width, color on a range ([#122](https://github.com/khuisman/mcp-gee-sweet/issues/122)) _(freema/mcp-gsheets)_
107
107
  - [x] `hide_rows` / `hide_columns` / unhide — toggle row or column visibility ([#123](https://github.com/khuisman/mcp-gee-sweet/issues/123)) _(freema/mcp-gsheets)_ (PR #311)
108
- - [ ] `resize_rows` / `resize_columns` — set pixel height/width, or auto-fit to content ([#124](https://github.com/khuisman/mcp-gee-sweet/issues/124)) _(freema/mcp-gsheets)_
108
+ - [x] `resize_rows` / `resize_columns` — set pixel height/width, or auto-fit to content (PR #321) ([#124](https://github.com/khuisman/mcp-gee-sweet/issues/124)) _(freema/mcp-gsheets)_
109
109
  - [ ] `add_data_validation` / `get_data_validation` — dropdowns, checkboxes, value constraints ([#125](https://github.com/khuisman/mcp-gee-sweet/issues/125)) _(freema/mcp-gsheets)_
110
110
  - [x] `update_sheet_properties` — tab color, hide/show gridlines (PR #301) ([#126](https://github.com/khuisman/mcp-gee-sweet/issues/126)) _(freema/mcp-gsheets)_
111
111
  - [x] `duplicate_sheet` — copy a sheet within the same spreadsheet (PR #286) ([#127](https://github.com/khuisman/mcp-gee-sweet/issues/127))
@@ -119,7 +119,7 @@ No new tools. Stabilize on what Tier 1 shipped before starting Tier 2 feature wo
119
119
  - [ ] `list_all_events` — query all subscribed calendars in parallel _(decision needed — also tracked in Decisions Needed)_ ([#194](https://github.com/khuisman/mcp-gee-sweet/issues/194))
120
120
 
121
121
  **Docs**
122
- - [ ] `insert_page_break` — explicit page break at an index ([#148](https://github.com/khuisman/mcp-gee-sweet/issues/148))
122
+ - [x] `insert_page_break` — explicit page break at an index ([#148](https://github.com/khuisman/mcp-gee-sweet/issues/148)) (PR #314)
123
123
  - [x] `merge_table_cells` — merge cells in an existing table (distinct from write-time colspan) ([#150](https://github.com/khuisman/mcp-gee-sweet/issues/150)) (PR #310)
124
124
  - [ ] Comments API — list, add, resolve doc comments ([#151](https://github.com/khuisman/mcp-gee-sweet/issues/151))
125
125
  - [ ] `create_named_range` / `create_bookmark` — anchor points for internal links ([#152](https://github.com/khuisman/mcp-gee-sweet/issues/152))
@@ -2,7 +2,7 @@
2
2
 
3
3
  <!-- Auto-generated by `scripts/gen_tool_docs.py` — do not edit by hand, your changes will be overwritten on the next commit. -->
4
4
 
5
- 100 tools. All tool names are lowercase with underscores — use these exact strings with `ENABLED_TOOLS` or `--include-tools`.
5
+ 103 tools. All tool names are lowercase with underscores — use these exact strings with `ENABLED_TOOLS` or `--include-tools`.
6
6
 
7
7
  ## Sheets — data
8
8
 
@@ -38,7 +38,10 @@
38
38
  | `unhide_rows` | Unhide previously hidden rows in a sheet. | `spreadsheet_id`, `sheet`, `start_row`, `end_row?` |
39
39
  | `hide_columns` | Hide columns in a sheet from view. | `spreadsheet_id`, `sheet`, `start_column`, `end_column?` |
40
40
  | `unhide_columns` | Unhide previously hidden columns in a sheet. | `spreadsheet_id`, `sheet`, `start_column`, `end_column?` |
41
+ | `resize_rows` | Set an explicit pixel height for rows, or auto-fit them to content. | `spreadsheet_id`, `sheet`, `start_row`, `end_row?`, `pixel_size?`, `auto_resize?` |
42
+ | `resize_columns` | Set an explicit pixel width for columns, or auto-fit them to content. | `spreadsheet_id`, `sheet`, `start_column`, `end_column?`, `pixel_size?`, `auto_resize?` |
41
43
  | `format_cells` | Apply formatting to a cell range (background color, font, alignment, number format). | `spreadsheet_id`, `sheet`, `range`, `bold?`, `italic?`, `strikethrough?`, `font_size?`, `font_color?`, `background_color?`, `horizontal_alignment?`, `vertical_alignment?`, `number_format_type?`, `number_format_pattern?` |
44
+ | `update_borders` | Apply or clear borders on the edges of a cell range. | `spreadsheet_id`, `sheet`, `range`, `top?`, `bottom?`, `left?`, `right?`, `inner_horizontal?`, `inner_vertical?` |
42
45
  | `merge_cells` | Merge a range of cells into one cell. | `spreadsheet_id`, `sheet`, `range`, `merge_type?` |
43
46
  | `unmerge_cells` | Unmerge all merged cells in a range. | `spreadsheet_id`, `sheet`, `range` |
44
47
  | `freeze` | Freeze rows and/or columns in a sheet. | `spreadsheet_id`, `sheet`, `rows?`, `columns?` |