Skip to content

feat: add gws mcp server#58

Merged
jpoehnelt merged 3 commits intomainfrom
feat/mcp-server
Mar 4, 2026
Merged

feat: add gws mcp server#58
jpoehnelt merged 3 commits intomainfrom
feat/mcp-server

Conversation

@jpoehnelt
Copy link
Copy Markdown
Member

Summary

Adds a new gws mcp subcommand that starts a Model Context Protocol server over stdio, exposing Google Workspace APIs as structured tools to any MCP-compatible LLM client (Claude Desktop, Gemini CLI, VS Code, etc.).

Changes

New: src/mcp_server.rs

  • JSON-RPC 2.0 stdio transport (newline-delimited, no external MCP SDK)
  • Handles initialize, tools/list, and tools/call
  • Dynamic tool schema generation from Google Discovery Documents
  • Service filtering via -s flag (-s drive,gmail or -s all)
  • -w/--workflows and -e/--helpers flags for optional tool categories
  • Startup warning to stderr when no services are configured

Modified: src/executor.rs

  • execute_method now accepts a capture_output flag
  • Returns Option<Value> instead of printing directly to stdout when capturing, keeping the MCP stdio transport clean

Modified: src/helpers/*, src/main.rs

  • Updated all execute_method call sites to pass capture_output: false (preserving existing behavior)

Modified: README.md

  • Added MCP Server section with usage examples, config snippet, and flag reference

Usage

gws mcp -s drive,gmail,calendar
{
  "mcpServers": {
    "gws": {
      "command": "gws",
      "args": ["mcp", "-s", "drive,gmail,calendar"]
    }
  }
}

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
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 4, 2026

🦋 Changeset detected

Latest commit: b0c25ed

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@googleworkspace/cli Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the gws CLI by integrating a Model Context Protocol (MCP) server. This new gws mcp subcommand allows external AI clients, such as LLMs, to discover and invoke Google Workspace APIs as structured tools via a standard JSON-RPC over stdio interface. The change involves adding the server implementation, adapting the existing API execution logic to support output capture, and updating the project's documentation to reflect this new capability.

Highlights

  • New gws mcp subcommand: Introduced a new command to start a Model Context Protocol (MCP) server over stdio.
  • Google Workspace APIs as structured tools: The MCP server exposes Google Workspace APIs, workflows, and helpers as structured tools for LLM clients.
  • Dynamic tool schema generation: Tool schemas are dynamically generated from Google Discovery Documents, ensuring up-to-date API definitions.
  • Output capture in execute_method: The core execute_method function was refactored to allow capturing output as a serde_json::Value instead of printing directly to stdout.
  • Updated documentation: The README.md was updated with a dedicated section for the MCP server, including usage instructions and configuration examples.
Changelog
  • README.md
    • Added a new "MCP Server" section detailing its purpose, usage, and configuration.
    • Included examples for starting the server and configuring it in an MCP client.
    • Added a table of flags for the mcp subcommand.
    • Minor formatting adjustments (removed blank lines, updated table alignment).
  • src/executor.rs
    • Modified handle_json_response and handle_binary_response to conditionally capture output into a Vec<Value> or Option<Value> respectively, based on a new capture_output flag.
    • Changed the return type of execute_method from Result<(), GwsError> to Result<Option<Value>, GwsError> to allow returning captured output.
    • Introduced a capture_output boolean parameter to execute_method and related internal functions.
  • src/helpers/calendar.rs
    • Updated execute_method calls to explicitly pass capture_output: false.
  • src/helpers/chat.rs
    • Updated execute_method calls to explicitly pass capture_output: false.
  • src/helpers/docs.rs
    • Updated execute_method calls to explicitly pass capture_output: false.
  • src/helpers/drive.rs
    • Updated execute_method calls to explicitly pass capture_output: false.
  • src/helpers/gmail/send.rs
    • Updated execute_method calls to explicitly pass capture_output: false.
  • src/helpers/script.rs
    • Updated execute_method calls to explicitly pass capture_output: false.
  • src/helpers/sheets.rs
    • Updated execute_method calls to explicitly pass capture_output: false.
  • src/main.rs
    • Added mod mcp_server; to include the new MCP server module.
    • Introduced a new if first_arg == "mcp" block to handle the gws mcp subcommand, delegating to mcp_server::start.
    • Modified the main execute_method call to pass false for capture_output and map the Result<Option<Value>, GwsError> to Result<(), GwsError> to maintain the original CLI output behavior.
  • src/mcp_server.rs
    • Added a new file containing the full implementation of the MCP server.
    • Defined ServerConfig for service, workflow, and helper exposure.
    • Implemented build_mcp_cli for argument parsing.
    • Implemented start function to set up stdio JSON-RPC communication and handle incoming requests (initialize, tools/list, tools/call).
    • Implemented handle_request to dispatch to specific handlers based on the MCP method.
    • Implemented build_tools_list to dynamically generate tool schemas from Google Discovery Documents and include predefined workflow tools.
    • Implemented walk_resources to recursively process API resources and methods to create tool definitions.
    • Implemented handle_tools_call to parse MCP tool call arguments, resolve the corresponding Google API method, and invoke executor::execute_method with capture_output: true to get the result.
Activity
  • The pull request introduces a new feature, indicated by the feat: prefix in the title.
  • The author jpoehnelt has provided a detailed summary of the changes in the pull request description.
  • No specific reviewer comments or interactions have been recorded in the provided context.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a gws mcp subcommand to start a Model Context Protocol server, which involves refactoring src/executor.rs and implementing core server logic in src/mcp_server.rs to handle JSON-RPC requests and expose Google Workspace APIs as tools. A critical security vulnerability has been identified where the upload argument in tool calls allows for arbitrary local file reads, potentially leading to sensitive data exfiltration via prompt injection; strict path validation is required to address this. Furthermore, there are opportunities to improve error handling and simplify code for enhanced robustness and clarity.

- 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
- 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
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 4, 2026

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@jpoehnelt jpoehnelt merged commit 670267f into main Mar 4, 2026
25 of 26 checks passed
@jpoehnelt jpoehnelt deleted the feat/mcp-server branch March 4, 2026 18:58
shigechika pushed a commit to shigechika/gws-cli that referenced this pull request Mar 20, 2026
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant