All notable changes to GravityKit MCP (formerly GravityMCP) will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Guidance for side-by-side (horizontal) search bars. Asked to arrange a View's search fields in one horizontal row, agents set the search bar's
search_layoutsetting, which persists but changes nothing, leaving the fields stacked. The server instructions now document the mechanism GravityView actually renders: add anarea_settingsentry withlayout: "row"into the search bar'ssearch_fields_sectionposition bucket (read it withgv_view_config_get, write it back withgv_view_widget_patch). A newsearch.horizontal-layoutrelease-gate task guards this end to end on a small model.
2.4.1 - 2026-06-25
This release lets the field tools work with custom and third-party field types (not just the ones built into Gravity Forms), and tightens input handling and security across the server.
gf_add_fieldnow accepts custom and third-party field types. Field types added by other plugins were previously rejected because they aren't in the built-in registry. They are now created normally, with a note when type-specific defaults or sub-inputs aren't available; passinputs/choicesexplicitly for custom compound or choice fields.- Compound field sub-inputs stay consistent with the field's id. When a field's id is auto-assigned or differs from the one supplied, its sub-input ids (e.g.
5.1,5.2) are rebased to match, soname,address, and custom compound fields save to the right inputs. gf_update_fieldno longer saves a change it then reports as blocked. When a field had dependent conditional logic andforcewasn't set, the update was written before the "use force to proceed" response, so the check protected nothing. The dependency check now runs before the write (matchinggf_delete_field).- Hardened tool-input handling. Malformed or hostile input to the field, validation, and dependency helpers (empty/
null/non-string field types,nullproperties or position, anullentry in a form'sfields, non-scalar filter values, self-referential objects) now returns a clean error or is handled safely instead of failing opaquely. - Security and validation hardening. Loopback detection no longer treats a remote
127.xdomain as local (which could have allowed Basic auth over plain HTTP);Cookieheaders and values are masked in logs; confirmation-redirect URL validation accepts dotless hosts (localhost/intranet); and duplicate or out-of-range explicit field ids are corrected so generated forms stay valid (an out-of-range id can no longer stall form creation).
2.4.0 - 2026-06-19
This update adds additional guards to make sure Gravity Forms entries save correctly for every field type, so an AI assistant gets the entry format right the first time. Adds explicit support for the password field type and Gravity Wiz Nested Forms, plus a benchmark suite that ensures the MCP works well with small models.
passwordfield type in the registry.- Expanded
entry_inputhints ingf_list_field_typessummary mode for every field type whose entry format isn't an obvious plain string. - Nested Form (
form) field config in the registry +gf_list_field_types --detail: documents the GP Nested FormsgpnfForm(child form id) andgpnfFields("Summary Fields", which child fields show in the nested summary).
gf_create_formauto-assigns field ids when omitted, preventing an AI round-trip with smaller models.gf_delete_form/gf_delete_entrydescriptions now state the safe Trash default explicitly and instruct the model to proceed with Trash unless the user asks to permanently delete- Server
instructionsnow point to GravityView's search-bar flow. - Fixes GravityKit tool fetching with one-shot clients. Clients that read the ability catalog once (e.g.
claude -p) now wait to receive the GravityKit ability list.
- No-input GravityView tools (e.g.
gv_forms_list) failed with "input is not of type object". Readonly abilities called with no arguments sent the/runrequest with noinputparameter, which the WordPress Abilities API rejected as a non-object (400). The loader now always sends an object-shaped input (input=on GET/DELETE, which WordPress reads as an empty object;{input:{}}on POST), so tools that take no arguments work. - Improved support for complex field types, including
address,chainedselect,survey_rank,date, and the survey/quiz/poll fields. - Corrected storage structures for many field types, helping improve first-time success rates.
sorting.is_numericis interpreted strictly. Sorting is now valid only when it genuinely means true (true,1,"true","1") and omitted otherwise so GF falls back to lexical ordering.- Improved cleanup Any crashed or improperly-killed client left an orphaned process running.
- Adds dev-only benchmark suites (not shipped in the npm package):
npm run bench: the AI release gate that drives the full MCP surface through a small model (claude-haiku-4-5) and grades real Gravity Forms/GravityView state.npm run bench:field-output: a deterministic field-output smoke suite.npm run bench:field-storage: field-storage validation against real add-ons.npm run bench:nested-forms: a front-end render test confirming a parent View shows a nested form's Summary Fields (directory shows child ids; single entry renders the child table).
2.3.0 - 2026-06-16
A second correctness pass on the gf_* plane — three tools that failed on valid input — plus clearer server instructions. Verified against live Gravity Forms.
gf_add_fieldandgf_update_fieldcrashed on every call withgetWarnings is not a function.FieldManagercalled a validator method that did not exist, so both tools threw before reaching the API.FieldAwareValidator.getWarnings()now exists (returns warnings for a missing label or a choice field with no choices; never throws) and both tools work.gf_validate_formcreated a real entry instead of validating. Like the 2.2.0gf_validate_submissionfix, it POSTed to/submissions; it now uses the dedicated/forms/{id}/submissions/validationroute and returns{valid, validation_messages, page_number}without persisting an entry.field_valueswas typed as an object ongf_submit_form_dataandgf_validate_form— the inverse of Gravity Forms, which declares it as a string/array of dynamic-population data and rejects an object with a 400. It now accepts a query string or array; objects are rejected client-side with a message pointing to theinput_Nkeys for submitted values.sorting.is_numeric: falseforced numeric ordering. GF never casts the flag, so the string"false"read as truthy.is_numericis now sent only when truthy and omitted otherwise.
- Server
instructionsrewritten from a second-person playbook into declarative two-plane prose. The imperative phrasing was echoed back by some non-Claude-Code clients as injected commands; the tools are self-describing, so the instructions now just state thegf_*/gv_*planes and point at thegv_*_listdiscovery tools andgk_reload_abilities.
2.2.0 - 2026-06-16
A correctness pass on the Gravity Forms (gf_*) plane, verified against Gravity Forms 2.10.3 source and a live GF site (self-seeding npm run test:live harness).
gf_list_entriespagination, sorting, and exclude were silently ignored.paging/sortingwere JSON-encoded, but GF reads them as bracketed array query params, so it fell back to the first 10 entries (page 1) andid/DESC. They are now serialized to GF's actual wire contract — pagination, sorting, and multi-form (form_ids) queries work. (#4)gf_validate_submissionperformed a real submission and threw on invalid input. It POSTed to/submissionswith an ignoredvalidation_onlyflag and the HTTP client threw on GF's normal400 {is_valid:false}response. It now uses the dedicated/forms/{id}/submissions/validationroute and returns{valid, validation_messages, page_number}without creating an entry.gf_submit_form_datareturns{success:false, validation_messages}on a rejected submission instead of discarding the messages.gf_send_notificationsnever sent. It posted anotification_idsbody array, but GF reads_notifications(comma-separated) and_eventas query params and returns a bare array. Request/response shapes corrected; null/empty IDs are rejected rather than silently triggering "send all".gf_list_formstotal_countwas always 0 (it read anX-WP-Totalheader GF doesn't send for/forms); it now reflects the number of forms returned.search.mode(any/all) was ignored — it was placed at the search-object top level, but GF reads it insidefield_filters; OR/AND now apply.field_filtersIN/NOT IN/NOTINwith array values were flattened to a scalar (broke membership matching;NOTINcaused a PHP fatal 500). Array values are preserved.- ID validation silently coerced bad input — hex strings (
"0x10"→16), booleans (true→1), scientific notation, and integers beyondMAX_SAFE_INTEGERproduced wrong-but-valid IDs. These are now rejected. gf_list_entriesresponse normalization always returns an entries array and a numerictotal_count(no morenull/empty-string/fabricated entries on unexpected bodies).- Field-filter operator validation is case-insensitive (matches GF);
value: nullis rejected instead of matching the literal text"null";entry_id: 0reports "must be a positive integer".
gf_list_entriesnow supports and advertises GF's nativeinclude(fetch-by-ID, returns entries of any status),paging.offset,sorting.is_numeric, and querying multiple forms at once.- Self-seeding live end-to-end test harness (
npm run test:live) that provisions its own throwaway forms/entries against a real Gravity Forms site and tears them down. - Adversarial
*-hardeningtest suites (client, validation, sanitize, schema) covering hostile and edge-case input.
includeuses GF's native fast-path (any status);excludemaps to anid NOT INsearch filter.gf_list_formsno longer accepts thestatus/active/excludeparams that GF's/formsendpoint ignores.
sanitize()now masks common secret field names (secret,client_secret,private_key,*_secret_key,password);sanitizeUrl()masksoauth_signatureand HTTP Basicuser:pass@credentials in logged URLs.
2.1.0 - 2026-03-31
- Checkbox field values created via MCP now use proper Gravity Forms dot-notation sub-inputs instead of JSON array strings. Values are matched against choices by value then text, with HTML entity decoding for ampersands. Closes #1
- Multiselect arrays normalized to comma-separated strings (REST API v2 format)
- Radio/select arrays take first element; list/chainedselect arrays pass through unchanged
- Hidden inputs (e.g., Select All) skipped during checkbox expansion
- Update entry correctly clears stale checkbox sub-inputs via fetch-then-merge
- Field registry: corrected storage definitions for checkbox (compound/dotNotation, not array/json), multiselect (commaSeparated, not json), consent (3 sub-inputs, not 2), chainedselect (compound, not single)
- Field registry: added variant-specific storage for product, option, post_category, post_custom_field, quiz, poll
- Field registry: added base
surveytype with all 8 inputType variants; moved hasChoices to variant level so text/textarea variants don't require choices - Field validation: fixed compound/array ordering so checkbox hits array branch (not compound) in getFieldValue, processSubmissionData, extractSubmissionValue
- Validation: removed unused imports, fixed validator name references, added JSON string→array parsing for MCP clients that serialize arrays as strings
_normalizeArrayValues()in GravityFormsClient: fetches form schema to match array values to correct sub-input IDs for all choice-based field types- 41 array normalization tests covering checkbox, multiselect, radio, select, option, quiz, poll, survey, post_category, post_custom_field, list, entry_tags, HTML entity decoding, and mixed-form scenarios
- 25 field registry tests verifying storage definitions and variant-specific overrides
- Compound field fallback: logs warning and stores as single value when subInput mapping is missing
2.0.0 - 2026-03-31
- Renamed project from GravityMCP to GravityKit MCP
- npm package:
@gravitykit/gravitymcp→@gravitykit/mcp - GitHub repo:
GravityKit/GravityMCP→GravityKit/MCP - MCP server name:
gravitymcp→gravitykit-mcp - CLI binary:
gravitymcp→gkmcp - Environment variable:
GRAVITYKIT_MCP_TEST_MODE(legacyGRAVITYMCP_TEST_MODEstill supported) - User-Agent header updated to
GravityKit MCP/2.0.0
- The old
@gravitykit/gravitymcpnpm package is published as a bridge that depends on@gravitykit/mcpwith a deprecation notice — existing installs continue working - GitHub auto-redirects old repo URL (
GravityKit/GravityMCP) to the new one GRAVITYMCP_TEST_MODEenvironment variable still works alongside newGRAVITYKIT_MCP_TEST_MODE
1.4.1 - 2026-03-20
- Race condition in concurrent fetch-then-merge updates: added per-resource mutex to serialize mutations on the same form/entry/feed
FieldManagerdouble-fetch eliminated: newreplaceForm()does direct PUT without re-fetching (3 HTTP calls → 2 per field op)console.logcalls in 7 files replaced withlogger.info/logger.warnto prevent JSON-RPC stdout corruptionmcp.jsonphantomgf_submit_formtool removed, 4 field operation tools added, version synced_variant/_metainternal metadata stripped from field objects before sending to API- Field operation errors now propagate to
wrapHandlerwithisError: trueinstead of being silently swallowed - Name field sub-input IDs corrected (
.2=prefix,.3=first, matching Gravity Forms) - Feature filter
conditionalnow maps to correct registry keysupportsConditionalLogic gf_delete_feeddescription now mentionsALLOW_DELETErequirement
ResourceMutexutility (utils/mutex.js) withacquire/releaseandwithLock()for safe concurrent operationsreplaceForm(formId, formData)client method for direct PUT without re-fetch- MCP tool annotations on all 26 tools (
readOnlyHint,destructiveHint,openWorldHint) - Server-level
instructionsstring documenting compact mode (sent once at session start) - 31 new tests: 22 bug regression tests + 9 mutex concurrency tests
- Tool descriptions stripped of repeated compact boilerplate (~130 tokens saved per
tools/listcall) compactproperty description shortened to "Return raw uncompacted data"
- Redundant
gf_list_form_feedstool (gf_list_feedswithform_iddoes the same thing plus addon filtering) - Deprecated
cryptoand unusedform-datanpm dependencies - False
batch_operations: trueclaim frommcp.json
1.4.0 - 2026-03-20
- Test mode environment resolution: when
GRAVITYMCP_TEST_MODE=true, the client automatically usesGRAVITY_FORMS_TEST_*env vars (base URL, consumer key/secret) instead of live credentials testConfig.resolveEnv()method inconfig/test-config.jsas the canonical place for environment resolution- Init log now shows
(TEST MODE)indicator when connecting to test site - Support for
GRAVITY_FORMS_TEST_BASE_URLenv var (in addition to existingGRAVITY_FORMS_TEST_URL)
- Removed 4 unused variable warnings (
responsein delete methods,safeHeadersin request interceptor)
1.3.0 - 2026-03-10
- Compact mode:
stripEmpty()recursively removesnulland""values from all responses to reduce token usage - Entry meta stripping: plugin-added meta keys (e.g.,
gv_revision_*,helpscout_conversation_id) are stripped by default viastripEntryMeta() - Pass
compact=falsefor full raw data
- Updated axios and MCP SDK to patch security vulnerabilities
1.1.0 - 2026-03-10
- Reduced token usage across all tool responses: no pretty-print, no redundant
messagestrings, no echo-back of input IDs - Updated AGENTS.md and CLAUDE.md for token optimization documentation
- Granted
contents:writepermission in publish CI workflow
1.0.5 - 2026-02-18
- Fixed OAuth signature generation in
validateRestApiAccessto pass full URL, method, and params togetAuthHeaders() - Fixed confirmations and notifications validation to accept objects keyed by ID instead of arrays, matching Gravity Forms' actual data format
- Added defensive optional chaining for
httpClient.defaults.baseURL
- Updated test helpers: added
defaults.baseURLto MockHttpClient - Updated test data and validation tests to use object format for confirmations and notifications
1.0.4 - 2025-01-13
- Comprehensive data sanitization for secure logging
- GitHub Actions workflows for automated testing and publishing
- Self-signed SSL certificate support for local development
- Auto-generate inputs array for compound fields in
gf_create_form - Load
.envfrom working directory with project fallback
- Updated CodeQL Action to v3
- Removed local Claude settings from version control
1.0.3 - 2024-12-09
- Renamed package from
gravity-mcptoGravityMCPfor consistency - Updated all documentation references to use new naming
- Improved Claude Desktop configuration example
- Removed obsolete rename script
- GitHub Actions workflow for automated npm publishing
- GitHub Actions workflow for continuous testing
1.0.2 - 2024-12-09
- Fixed logging for MCP and test modes
1.0.1 - 2024-12-09
- Initial release of GravityMCP
- Full Gravity Forms REST API v2 coverage
- 28 MCP tools for complete forms management
- OAuth 1.0a and Basic authentication support
- Advanced search and filtering capabilities
- File upload support
- Comprehensive test suite
- Dual environment configuration (test/production)
- Forms management (6 tools)
- Entries management (6 tools)
- Field operations (4 tools)
- Form submissions (2 tools)
- Add-on feeds (7 tools)
- Notifications (1 tool)
- Field filters (1 tool)
- Results/Analytics (1 tool)