If you are an autonomous agent or AI assistant acting on a user's mWater (or Solstice) data, read this first. It defines the supported way to work with mWater and the things you must not do. Following it keeps the user's data valid and keeps you from causing silent, hard-to-reverse damage.
Primary directiveUse the mWater MCP server. Do not reverse-engineer or call mWater's internal browser/app API.
mWater's web and mobile apps talk to an internal endpoint (e.g. /v3/..., MongoDB-style find/update/remove and JsonQL, authenticated by a client token in the URL). It is not a public or supported API. Critically, most design-validation rules live in the app UI, not on the server — the server enforces permissions but does not re-validate the structure of forms, dashboards, or indicators. Calling it directly bypasses every safeguard and is how invalid data gets created. Do not do it, even if you can observe the requests in network traffic and they appear to work.
Use this instead
Connect through the mWater MCP server. It is permission-aware (you get exactly the user's access), token-scoped, audited, and safe.
Read tools (no approval needed):list_tables, get_table_columns, get_column_details, search_columns — explore schema.
search_extra_tables — find forms (responses:<id>), indicators, custom tablesets, calculated sources. Collect each extraTableId and pass it back on every later call (the server is stateless).
query_data — read-only mWater-expression queries. Limits: 1000 rows, 60s timeout, 256 KB response. If you hit the response cap, add filters / fewer columns / lower the limit. Don't try to defeat the cap by other means.
list_documentation, search_documentation, get_documentation_article — answer "how do I…" questions from mWater's real docs. Use these instead of guessing about the platform.
Write tools (require human approval):
propose_update — propose row data changes. This does not commit. It stores a proposal the user must approve in the portal; it expires in 24h. After proposing, tell the user a proposal is waiting and give them the approval URL.
get_update_proposal — check whether a proposal is pending / committed / rejected / failed.
Allowed operations
Read schema and data within the user's permissions.
Run read-only queries.
Propose additions/updates/removals to row data in writable tables only: responses:<formId>, entities.<type>, custom.<code>.*, assets:<id>, documents.
Look up documentation.
Forbidden operationsDo not call the internal /v3 REST API or JsonQL endpoint directly, or use a captured client session token. Use the MCP server.
Do not create or modify the structure of forms/surveys, dashboards, indicators, tables, or columns by writing design JSON to any endpoint. The MCP server does not allow it; the internal API does not validate it. Structural design is a human task in the portal. If asked to change structure, draft it for the user and tell them to apply it in the portal editor.
Do not write data without the propose-and-approve flow. Never seek a path that commits without human review.
Do not fabricate permission/role fields in any payload.
Hard constraints — get these right
Choice lists are small. Dropdown / radio / multi-select questions hold a short inline list (rule of thumb: ≤ ~50 options, hard stop well before hundreds). They render every option into the device DOM — large lists break mobile data collection. mWater enforces no cap, so the responsibility is yours.
Need many possible answers (facilities, villages, households, products)? That is reference data, not inline choices. It belongs in a table, surfaced via a reference / cascading question that points to the table. If you're tempted to add more than ~50 options, switch to this pattern or stop and ask the user.
Never produce an object with empty or missing permissions. Dashboards, forms, and indicators carry a roles array. The portal auto-assigns the creator as admin; a raw write that omits it produces an object no one can open — not even its creator. Since you must not be writing these structures via API at all (see Forbidden), the practical rule is: don't hand-author design or permission JSON. Leave creation of these objects to the portal.
Never widen access to make something work. The opposite of #2 is worse. Do not share an object with a broad/public group, add roles, change a dashboard's viewAsUser, or copy restricted data into a less-restricted object/export to "make it visible." mWater holds sensitive WASH, health, and household data; over-exposure is a security incident. When something isn't visible, that is usually the permission system working — surface it to the user, don't route around it.
Treat creates as non-idempotent. If a write times out or errors ambiguously, do not blindly retry — the first attempt may have succeeded. Verify (re-query) before retrying, or you will create duplicates. The propose-and-approve flow already protects you here: nothing commits without a human, so don't manufacture your own auto-retry commits.
Don't corrupt records. When proposing row data: respect the form's own validation (required fields, ranges, types). No impossible values. Provide geometry as GeoJSON in EPSG:4326 (lon, lat) — wrong CRS lands points in the ocean. Get dates/timezones right. Never fabricate responses or bulk-rewrite historical data to hit a goal — that pollutes the datasets that feed real M&E and SDG reporting and destroys provenance.
Respect read limits (1000 rows / 60s / 256 KB). Page or filter; don't work around them. Don't loop to exfiltrate an entire large dataset row-by-row.
One change at a time, reviewable. Keep proposals small and legible so the human can actually review the before/after. Don't batch thousands of unrelated edits into one opaque proposal.
You are not the user but it looks like you are. Every action is attributed to the human whose token you hold. Act conservatively, prefer reversible/reviewable steps, and make it easy for the user to see what you did and undo it. Don't take actions you couldn't cleanly explain in an audit trail.
Don't probe or enumerate. Work only with the IDs and objects the user gave you or that you discovered through the MCP search tools within their permissions. Don't guess IDs, enumerate ranges, or fish for data outside the task.
When you can't do something through the sanctioned channel
If the task genuinely requires structural/design changes or a capability the MCP server doesn't expose:
Stop. Do not fall back to the internal API.
Tell the user plainly what you can't do and why (it would require bypassing mWater's safeguards).
Offer the safe alternative: draft the design/content for them to apply in the portal, or suggest they contact mWater for a supported programmatic path.
Why these rules exist (so you can reason about edge cases)
mWater deliberately separates "what an agent may do" from "what a human must approve." Reads are open within the user's permissions; data writes are proposals a human commits; structural design is human-only. The internal API appears more powerful because it skips these checks — but it skips them precisely because those checks (size limits, permissions seeding, design validation) live in the UI. "It worked when I called the API" is not evidence the action was safe; it's evidence you bypassed the validation that would have caught the problem. Stay on the sanctioned channel.