Skip to content

Latest commit

 

History

History
372 lines (282 loc) · 9.58 KB

File metadata and controls

372 lines (282 loc) · 9.58 KB
title MCP server
description Expose typed, allowlisted gog tools to MCP clients without a generic command runner.

MCP server

gog mcp runs a Model Context Protocol server over stdio. It is for agent clients that need Google Workspace tools but should not receive a generic shell or arbitrary gog command bridge.

The server registers a small set of typed tools such as gmail_search, docs_get, and sheets_read_range. Each tool has a fixed schema, maps to one specific gog operation, and returns a structured result containing the tool name, service, risk level, exit code, parsed stdout, and stderr.

Quick start

Start a read-only server for one account:

gog --account you@example.com mcp

List the tools this server would expose and exit:

gog --account you@example.com mcp --list-tools

Limit the server to Gmail search and Docs reads:

gog --account you@example.com mcp \
  --allow-tool gmail_search,docs_get

Expose Docs read/write tools:

gog --account you@example.com mcp \
  --allow-write \
  --allow-tool docs.*

--allow-write is always required for write tools. A write tool that matches --allow-tool is still hidden until --allow-write is present.

Why this is not gog_exec

MCP clients are often LLM-driven. A generic "run this command" tool would expose every current and future CLI behavior through one broad capability, including commands that were not reviewed for MCP use.

gog mcp uses a narrower contract:

  • no generic command execution tool
  • no model-supplied argv passthrough
  • fixed tool schemas with unknown fields rejected
  • read-only tools by default
  • write tools require explicit server startup flags
  • existing gog account, auth, dry-run, no-input, and command safety flags are preserved

This keeps MCP useful for agents while making the permission surface visible at server startup.

Tool selection

By default, all read tools are registered and write tools are hidden.

Use --allow-tool to narrow the registered set. Values can be comma-separated or repeated:

gog mcp --allow-tool gmail_search --allow-tool docs_get
gog mcp --allow-tool gmail_search,docs_get

Accepted selectors:

Selector Meaning
gmail_search One exact tool
gmail All Gmail tools allowed by risk mode
gmail.* All Gmail tools allowed by risk mode
read All read tools
write All write tools, only when --allow-write is also set
* or all All tools allowed by risk mode

Examples:

# Read-only Gmail tools.
gog mcp --allow-tool gmail

# Only Docs tools, including writes.
gog mcp --allow-write --allow-tool docs.*

# Read-only server, but only Calendar and Sheets reads.
gog mcp --allow-tool calendar,sheets

# All current write tools. Read tools are not included unless also selected.
gog mcp --allow-write --allow-tool write

Initial tools

Read tools:

Tool Purpose
gmail_search Search Gmail messages with Gmail query syntax.
gmail_get_message Read one Gmail message by ID. Sanitized content is on by default.
gmail_get_thread Read one Gmail thread by ID. Sanitized content is on by default.
drive_search Search Drive files by text or Drive query language.
drive_get Read Drive file metadata by ID.
docs_get Read a Google Doc as wrapped text, optionally one tab or all tabs.
sheets_read_range Read values from a Sheets range.
calendar_events List Calendar events.

Write tools, hidden unless --allow-write:

Tool Purpose
docs_write Append or replace Google Docs text, optionally as Markdown.
sheets_update_range Update values in a Sheets range from a literal JSON 2D array.

The generated command reference for the server itself is gog mcp.

Client configuration

MCP clients usually need a command and an argument list. Put account selection and safety policy on the server command, not inside tool calls.

Minimal stdio configuration:

{
  "command": "gog",
  "args": ["--account", "you@example.com", "mcp"]
}

Read-only Docs and Sheets configuration:

{
  "command": "gog",
  "args": [
    "--account", "you@example.com",
    "--enable-commands-exact", "docs.cat,sheets.get",
    "mcp",
    "--allow-tool", "docs_get,sheets_read_range"
  ]
}

Docs read/write configuration:

{
  "command": "gog",
  "args": [
    "--account", "you@example.com",
    "--enable-commands-exact", "docs.cat,docs.write",
    "--no-input",
    "mcp",
    "--allow-write",
    "--allow-tool", "docs.*"
  ]
}

For headless services, set GOG_KEYRING_BACKEND=file and GOG_KEYRING_PASSWORD on the MCP client process or service unit. A successful interactive shell check does not prove the MCP client inherited those variables; verify through the same process manager that launches the server.

mcporter examples

List registered tools and their schemas:

mcporter list \
  --stdio gog \
  --stdio-arg --account \
  --stdio-arg you@example.com \
  --stdio-arg mcp \
  --stdio-arg --allow-tool \
  --stdio-arg docs.* \
  --schema \
  --json

Dry-run a Docs write through MCP:

mcporter call \
  --stdio gog \
  --stdio-arg --account \
  --stdio-arg you@example.com \
  --stdio-arg --dry-run \
  --stdio-arg mcp \
  --stdio-arg --allow-write \
  --stdio-arg --allow-tool \
  --stdio-arg docs_write \
  docs_write \
  '{"document_id":"DOCUMENT_ID","text":"MCP smoke test\n","append":true}'

Read a Sheet range:

mcporter call \
  --stdio gog \
  --stdio-arg --account \
  --stdio-arg you@example.com \
  --stdio-arg mcp \
  --stdio-arg --allow-tool \
  --stdio-arg sheets_read_range \
  sheets_read_range \
  '{"spreadsheet_id":"SPREADSHEET_ID","range":"Sheet1!A1:C10"}'

Update a Sheet range:

mcporter call \
  --stdio gog \
  --stdio-arg --account \
  --stdio-arg you@example.com \
  --stdio-arg mcp \
  --stdio-arg --allow-write \
  --stdio-arg --allow-tool \
  --stdio-arg sheets_update_range \
  sheets_update_range \
  '{"spreadsheet_id":"SPREADSHEET_ID","range":"Sheet1!A1:B1","values_json":"[[\"status\",\"ok\"]]","input":"RAW"}'

sheets_update_range.values_json must be literal JSON. MCP rejects @file, @-, and - expansion forms so a model cannot cause the server process to read arbitrary local files or stdin.

Safety model

Tool calls run as subprocesses of the same gog executable. The server adds a non-interactive, agent-oriented root context to every child command:

  • --json
  • --wrap-untrusted
  • --no-input
  • --color=never

The server also preserves selected parent root flags:

  • --account
  • --client
  • --home
  • --dry-run
  • --results-only
  • --select
  • direct access tokens

And it preserves command safety flags:

  • --gmail-no-send
  • --enable-commands
  • --enable-commands-exact
  • --disable-commands

Use both MCP tool allowlists and command allowlists when the server is exposed to an untrusted or semi-trusted agent:

gog --account you@example.com \
  --enable-commands-exact docs.cat,docs.write \
  --disable-commands gmail.send,gmail.drafts.send \
  --gmail-no-send \
  mcp \
  --allow-write \
  --allow-tool docs.*

If a tool maps to a disabled command, the tool call returns a non-zero exit code and the child command error in stderr.

Output shape

Successful calls return structured MCP content shaped like:

{
  "tool": "docs_get",
  "service": "docs",
  "risk": "read",
  "exit_code": 0,
  "stdout": {
    "documentId": "..."
  },
  "stderr": ""
}

If a child command prints valid JSON, stdout is parsed as JSON with numeric literals preserved. Otherwise stdout is returned as a string. Empty stdout is omitted.

If the child command exits non-zero, the MCP result is marked as an error and includes the same structured fields with exit_code and stderr.

Limits and timeouts

Each tool call has a subprocess timeout and bounded stdout/stderr capture:

gog mcp --timeout-seconds 30 --max-output-bytes 262144

Defaults:

  • timeout: 60 seconds
  • max captured stdout/stderr: 102400 bytes each

Use command-specific limits too. For example, docs_get has a max_bytes argument, and search tools have max arguments.

Authentication

The MCP server uses normal gog auth. Before wiring a client, verify the same account and scopes from a shell:

gog --account you@example.com auth doctor --check
gog --account you@example.com mcp --list-tools

Then verify through the MCP client entrypoint. In services and desktop MCP clients, most auth failures are environment inheritance problems: missing GOG_ACCOUNT, missing file-keyring password, different GOG_HOME, or a different OAuth client selected by --client.

Troubleshooting

no MCP tools enabled

: Your --allow-tool filters excluded everything, or you selected only write tools without --allow-write.

command "..." is disabled

: The MCP tool was registered, but the child gog command was blocked by --enable-commands, --enable-commands-exact, --disable-commands, or a baked safety profile.

Tool missing in the client

: Run gog mcp --list-tools with the same flags. If the tool is not listed, fix --allow-tool or add --allow-write for write tools. If it is listed, refresh or restart the MCP client.

Auth works in Terminal but not in the MCP client

: Compare --account, --client, --home, GOG_HOME, GOG_KEYRING_BACKEND, and GOG_KEYRING_PASSWORD in the process that starts the MCP server.

Large output is truncated

: Increase --max-output-bytes, narrow the request, or use tool arguments such as max, max_bytes, date ranges, or Drive field masks.