Google Form Survey Automation — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Google Form Survey Automation (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
An MCP (Model Context Protocol) server that lets an AI assistant (Claude Code, Claude Desktop, …) author Google Forms through the official Forms API and deterministically fill them with survey responses from user-defined distributions — for testing/QA of forms you own (the form itself, response collection, and any downstream analysis pipeline).
⚠️ Responsible use. This tool is for forms you own or are explicitly authorized to test. Submitting fabricated responses to someone else's live survey to skew results is survey fraud and violates Google's Terms of Service. There are intentionally no anti-detection features; if a form requires sign-in or a CAPTCHA, the tool reports and refuses rather than bypassing it. Filling additionally requires an explicit i_own_this_form=true confirmation.The server is a hybrid of two Google integrations, because each can do what the other can't:
| Capability | Mechanism |
|---|---|
| Create forms, add questions, read structure & collected responses | Official Forms API (forms.googleapis.com, OAuth) |
| Submit responses | Public `/formResponse` endpoint (the official API cannot submit) |
The filling pipeline parses the public form page for its entry.<id> POST field IDs — these are unrelated to the question_ids the authoring tools return, which is why import_form_schema exists.
pip install nmvv-gform-mcpRequires Python ≥ 3.10. This puts the gform-mcp and gform-auth commands on your PATH. (Prefer pipx install nmvv-gform-mcp to keep it in an isolated environment.) To work on the source instead, clone the repo and run pip install -e ".[dev]".
own Google account as a test user.
Desktop app**, then download the JSON.
~/.gform/credentials.json (or point GFORM_CREDENTIALS at it).gform-auth # opens a browser once, caches the token at ~/.gform/token.json
gform-auth --reauth # discard the cached token and sign in againThe MCP server never opens a browser itself — if the token is missing or unusable, its tools return an error telling you to run gform-auth.
# Claude Code (use the full path to the script in your Python environment):
claude mcp add gform -- "C:\path\to\env\Scripts\gform-mcp.exe"Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"gform": { "command": "C:\\path\\to\\env\\Scripts\\gform-mcp.exe" }
}
}| Tool | What it does |
|---|---|
create_form | Create a form (title, optional description); publishes it by default and returns form_id, responder_uri, edit URL |
publish_form | Publish/unpublish, or close a form (accepting_responses=false) |
add_text_question | Add a short-answer or paragraph question |
add_multiple_choice_question | Add a radio/checkbox/dropdown question, optionally with an "Other" option |
get_form | Form structure: items, question IDs, publish state, responder_uri |
get_form_responses | Collected responses, flattened to question_id → [values] |
Forms created through the API start unpublished (Forms API change effective June 30, 2026); create_form publishes explicitly so the form can accept responses right away.
| Tool | What it does |
|---|---|
import_form_schema | Read a public form's questions + entry_ids; returns a suggested_fill_config with uniform distributions |
preview_fill | Validate a fill config and preview realized marginals + sample rows — no submission |
fill_form | Generate + submit; requires i_own_this_form=true; dry_run=true shows payloads without sending |
A fill config is a list of per-question distributions, passed inline:
[
{"entry_id": "111111", "type": "radio",
"distribution": {"Red": 0.6, "Blue": 0.3, "Green": 0.1}},
{"entry_id": "333333", "type": "checkbox",
"distribution": {"Search": 0.7, "Export": 0.4}},
{"entry_id": "999999", "type": "radio",
"distribution": {"Student": 0.8, "__other__": 0.2},
"other_text": "Research assistant"},
{"entry_id": "555555", "type": "text",
"distribution": {"Great service": 3, "Could be better": 1}}
]grid_radio) must sum to 1.0.
[0, 1].(sample text → weight; weights are normalized automatically).
__other__ selects the form's "Other" option and submits other_text.Determinism: same config + seed ⇒ identical responses. exact mode turns proportions into integer quotas (largest-remainder method) so realized marginals match targets; probabilistic mode samples instead. Submission is rate-limited with jitter (default 20/min) and writes an audit CSV to ~/.gform/logs/.
create_form → add questions → get_form (grab responder_uri) → import_form_schema → preview_fill → fill_form(dry_run=true) → fill_form(i_own_this_form=true) → get_form_responses.
| Variable | Default | Purpose |
|---|---|---|
GFORM_HOME | ~/.gform | Base directory (token, logs) |
GFORM_CREDENTIALS | $GFORM_HOME/credentials.json | OAuth client secrets |
GFORM_TOKEN | $GFORM_HOME/token.json | Cached authorized-user token |
pytestAll tests run offline: the importer is tested against a captured HTML fixture, submission with the network mocked, and the official API wrappers against a recording fake service.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.