MCP server for Google Forms.
npx skills add https://github.com/udecode/google-forms-mcp --skills google-formsThen run /google-forms in Claude Code to complete setup.
git clone https://github.com/udecode/google-forms-mcp.git ~/.claude/mcp/google-forms-mcp
cd ~/.claude/mcp/google-forms-mcp
bun install && bun run build- Enable Google Forms API + Google Drive API at console.cloud.google.com
- Create OAuth 2.0 credentials (Desktop app)
- Get refresh token:
cd ~/.claude/mcp/google-forms-mcp GOOGLE_CLIENT_ID="..." GOOGLE_CLIENT_SECRET="..." bun run token
- Add to
.mcp.json:{ "mcpServers": { "google-forms-mcp": { "command": "bun", "args": ["/Users/YOUR_USERNAME/.claude/mcp/google-forms-mcp/build/index.js"], "env": { "GOOGLE_CLIENT_ID": "...", "GOOGLE_CLIENT_SECRET": "...", "GOOGLE_REFRESH_TOKEN": "..." } } } }
Build locally:
docker build -t google-forms-mcp:local .Build and push to Docker Hub (same interface as creden-mcp-test):
printf '%s' "$DOCKER_HUB_TOKEN" | ./docker-build.sh YOUR_USERNAME/google-forms-mcp latest YOUR_USERNAMEThe script defaults to linux/amd64. Set PLATFORMS=linux/amd64,linux/arm64
to publish both platforms. The Docker Hub token is read from stdin.
The Docker image starts a stateless Streamable HTTP server at /mcp by default:
docker run --rm -p 8000:8000 \
-e GOOGLE_CLIENT_ID \
-e GOOGLE_CLIENT_SECRET \
-e GOOGLE_REFRESH_TOKEN \
google-forms-mcp:localIn Centermcp, save the three Google credentials in this MCP's environment before starting it. The application defaults, including Docker, are MCP_TRANSPORT=http, HOST=0.0.0.0, and PORT=8000. MCP_TRANSPORT=streamable-http is also supported. Override PORT and the published port together when needed.
Standalone CLI invocations also default to HTTP. Set MCP_TRANSPORT=stdio when using a stdio client. For Docker:
docker run --rm -i \
-e MCP_TRANSPORT=stdio \
-e GOOGLE_CLIENT_ID \
-e GOOGLE_CLIENT_SECRET \
-e GOOGLE_REFRESH_TOKEN \
google-forms-mcp:localExport these three variables in your shell first. Use -i to keep stdin open
for the MCP client.
| Tool | Description |
|---|---|
create_form |
Create form |
get_form |
Get form details |
list_forms |
List all forms |
update_form |
Update title/description |
delete_form |
Delete form |
add_section |
Add visual divider (no page break) |
add_page |
Add page break (requires Next button) |
add_text_question |
Add text question |
add_multiple_choice_question |
Add radio/checkbox question |
update_question |
Modify question |
delete_question |
Remove question |
get_form_responses |
Get responses |
All items are added at index 0. The LAST item you add appears FIRST.
For a form with sections, add in reverse:
create_form → update_form
add: last question
add: last section header
...
add: first question
add: first section header ← LAST (appears first)
Options support both formats:
- Simple:
["Option A", "Option B"] - With description:
[{ "label": "Option A", "description": "Details" }]
Set multiSelect: true for checkboxes, omit for radio buttons.
MIT
npx tsc
node --test tests/transport.test.mjsThe transport tests use dummy credentials and verify MCP initialization, tool discovery, concurrent HTTP requests, and stdio without calling Google APIs.