Generate Skills / Generate and commit skills (push) Has been cancelled
- Add +pull: download project files to local directory with filename sanitization
- Add +open: open script editor in browser
- Add +run: execute functions with cloud-platform scope and contextual error hints
(extracts GCP project number from OAuth client ID for setup guidance)
- Add +logs: view execution logs via processes.listScriptProcesses
- Add .clasp.json support: auto-resolve scriptId/rootDir for all helpers
- Add clasp_config.rs module with path traversal validation
- Add validate_script_filename() for safe file writes during +pull
- Regenerate skills for new helper commands
* feat: add gws mcp server
Adds a new `gws mcp` subcommand that starts a Model Context Protocol
(MCP) server over stdio, exposing Google Workspace APIs as structured
tools to any MCP-compatible client.
- New `src/mcp_server.rs`: JSON-RPC stdio transport, handles
`initialize`, `tools/list`, and `tools/call`
- Tool discovery dynamically builds schemas from Google Discovery Docs
- Filtering via `-s <services>` flag (e.g. `-s drive,gmail` or `-s all`)
- `-w/--workflows` and `-e/--helpers` flags for optional extras
- stderr startup warning when no services are configured
- Refactored `executor::execute_method` to support output capture
(returns `Option<Value>` instead of printing to stdout) so the MCP
transport is not corrupted
- Updated README.md with MCP Server section and usage examples
* fix: address PR review comments
- Add stderr warning when discovery doc fails to load (mcp_server.rs)
- Remove redundant 'all' string check in service validation (mcp_server.rs)
- Validate upload path to prevent arbitrary file reads - security fix (mcp_server.rs)
- Remove redundant inner capture_output check in handle_binary_response (executor.rs)
- Add changeset for minor version bump
* fix: resolve CI lint, fmt, and test failures
- cargo fmt: format all changed files
- clippy: add #[allow(clippy::too_many_arguments)] on private handle_json_response
- clippy: collapse else { if } to else if in executor.rs
- clippy: replace svc_name.clone() with std::slice::from_ref in mcp_server.rs
- clippy: replace index-based loop with iterator in walk path resolution
- test: add ::<()> turbofish annotation to handle_error_response test calls
to fix E0282 type inference errors
* docs(gws-shared): add community issue and starring guidance
* feat: add community links to gws help output
* fix(ci): move community section into generate-skills template + add changeset
- YAML: only emit block scalar (|) for strings with genuine newlines;
single-line strings containing '#' or ':' are now double-quoted instead,
e.g. 'drive#file' renders as '"drive#file"' not a block scalar.
- --page-all: CSV/table formats no longer re-emit column headers on
every page; headers appear only on the first page. A new public
format_value_paginated() helper replaces the now-removed
format_value_compact().
- Add unit tests for both fixes (8 new test cases in formatter.rs).
* fix: narrow default OAuth scopes to avoid restricted_client, add --full flag, improve non-interactive setup UX
Fixes#24, #25
- DEFAULT_SCOPES now aliases MINIMAL_SCOPES (no pubsub/cloud-platform)
which avoids Google's restricted_client 403 on unverified OAuth apps
- Add FULL_SCOPES and --full flag for users who need the broader set
- Replace cryptic 'run setup interactively' error with step-by-step
manual OAuth console instructions including URLs, options A/B/C
* chore: add changeset
* chore: cargo fmt
* fix: refactor format! with backslash continuations to concat! macro
Address Gemini review (PR #30): replace hard-to-read backslash line
continuations in large format! macros with concat! for clearer structure:
- manual_oauth_instructions(): full step-by-step guide
- stage_configure_oauth() wizard show_message: interactive prompt text
No functional change; output text is identical.
* feat(error): detect accessNotConfigured and guide users to enable APIs
When the Google API returns a 403 with reason accessNotConfigured,
gws now:
- Extracts the GCP Console enable URL from the error message.
- Adds an optional enable_url field to the JSON error output.
- Prints an actionable hint with the enable URL to stderr.
Also adds extract_enable_url() helper with tests, and a Troubleshooting
section to README.
Fixes#31
* fix(error): trim trailing punctuation from accessNotConfigured enable URL
* fix(auth): stabilize encryption key fallback across runs
* chore: add changeset for auth encryption key fix
* chore: cargo fmt
* fix(auth): address Gemini review comments - OnceLock expect + permission warnings
- Replace unwrap_or(candidate) with expect() in cache_key closure for clearer
OnceLock race invariant: if set() fails, get() is guaranteed to return Some
- Emit eprintln! warnings (rather than silently ignoring) when set_permissions
fails on the encryption key directory, matching the warning pattern used
throughout the codebase (src/auth_commands.rs, helpers/workflows.rs, etc.)
* refactor: replace manual urlencoded() with reqwest .query() builder
Remove duplicate hand-rolled urlencoded() functions from workflows.rs
and calendar.rs. All query parameters are now passed via reqwest's
.query() API, which handles percent-encoding correctly and completely.
* fix: percent-encode path parameters to prevent path traversal
Use percent_encoding::utf8_percent_encode for calendar_id, cal.id,
message_id, and file_id before interpolating into URL path segments.
Addresses code review feedback on security regression.
* fix: add shared URL safety helpers for path params
Add encode_path_segment() for single-segment IDs and
validate_resource_name() for multi-segment resource names.
encode_path_segment: percent-encodes all non-alphanumeric chars,
used for calendar IDs, file IDs, and message IDs.
validate_resource_name: rejects path traversal (..) and control
chars while preserving intentional / structure, used for Chat
space names, task list IDs, and subscription names. Returns clear
error messages for LLM callers.
* test: add AI edge case tests for URL safety helpers
Cover query/fragment injection, double-encoding, unicode, spaces,
path traversal via encoding, control chars (CR/tab), and clear
error message assertions for LLM callers.
* fix: warn on stderr when API calls fail silently
- Daily briefing calendar events fetch
- Daily briefing tasks fetch
- Daily summary calendar events fetch
- Daily summary unread email count fetch
Addresses PR review feedback about confusing silent failures,
especially for LLM callers that cannot see visual cues.
* fix: harden input validation for AI/LLM callers
- Add src/validate.rs with validate_safe_output_dir, validate_msg_format,
and validate_safe_dir_path helpers
- Validate --output-dir against path traversal in gmail +watch and
events +subscribe
- Validate --msg-format against allowlist in gmail +watch
- Validate --dir against path traversal in script +push
- Add clap value_parser constraint for --msg-format
- Document input validation patterns in AGENTS.md
Closes#23
* chore: add changesets for PR #21 commits
* test: add comprehensive test coverage for input validation handlers
* docs: document input validation and URL safety patterns in AGENTS.md and CONTRIBUTING.md
* fix: address PR review comments — reject ?/# in resource names, validate subscription arg, remove redundant validate_msg_format
* fix: store validated PathBuf, remove dead code, delete duplicate SubscribeConfig
Addresses review comments:
- Store validated PathBuf from validate_safe_output_dir instead of
discarding it (output_dir is now Option<PathBuf>)
- Remove duplicate SubscribeConfig from events/mod.rs
- Delete unused validate_msg_format (clap value_parser handles this)
- Remove all #[allow(dead_code)] annotations
* fix: per-segment traversal check in validate_resource_name, fix docs
* fix: harden security validation and deduplicate logic
---------
Co-authored-by: jpoehnelt-bot <jpoehnelt-bot@users.noreply.github.com>
* fix(docs): improve README typography and spacing
- Remove center alignment for tagline and badges to match left-aligned body
- Add `<br>` after badges for visual separation before install block
- Increase whitespace above install block to emphasize it
- Add an empty line above `> [!IMPORTANT]` block to decouple it from previous paragraph
Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>
* Update README.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
* docs: improve README typography and layout
- Remove center alignment from tagline and badges
- Add space below badges
- Adjust spacing around install code block (remove borders, add empty line above)
- Add empty line above IMPORTANT callout
Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>
* docs: refine copy after install code block
- Change "When Google adds an API endpoint" to "When Google Workspace adds an API endpoint or method" to be more accurate.
Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>
* docs: remove horizontal borders from README
Per user request, removed all remaining Markdown horizontal rules (`---`) throughout `README.md` to create a cleaner, borderless design. All previous typography and spacing improvements remain intact.
Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>
---------
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: jpoehnelt <3392975+jpoehnelt@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>