Skip to main content
Glama

Create, replace or delete a data table

set_data
Destructive

Attach a data table to a page, replace it entirely, delete it, or open/close reader write-back. Tables are independent of versions: editing data never republishes the page and pushing a new version never changes tables. Call get_data first and pass the revision back unchanged: 0 creates, the current value updates; a mismatch is rejected (409) and requires re-reading, never blind overwrites. Provide rows (array of objects, optional columns for order) or csv (text, first line headers), not both; delete=true removes the table and its appended rows. append_open=true lets viewers append one row from the page with a plain form or POST ./_data/ (or the optional SDK space.data.append) (sign-ups, check-ins, votes, feedback): off by default, per table; passing append_open alone only flips the switch. Appended rows are rate-limited, moderated before other viewers see them, and readable only through list_data_rows; rows the author or another workspace member submits while signed in on the live page carry by=member. members_only=true accepts rows from workspace members only (visitors get 403) and, like append_open, can be passed on its own. In the page read (fetch('./_data/.json') / space.data.get) every viewer row carries _row_id, _at (submission time) and _status (approved / held); rows the current viewer submitted carry _mine: true and submitters can read their own held rows (never other people's); when the viewer is a member, member rows add _by (nickname). A submitter can withdraw their own row within 24 hours with DELETE ./_data//<row_id>. Columns the table does not have are accepted but not stored, and the receipt carries warnings (unknown_columns). Table names start with a lowercase letter and contain only letters, digits and underscores. The receipt states the per-table, per-page and workspace limits with current usage.

Input Schema

NameRequiredDescriptionDefault
csvNoCSV text, first line is the header; either this or rows
rowsNoArray of objects, one per row, keys are column names; either this or csv
tableYesTable name, e.g. items or sales_2026
deleteNotrue = delete this table (no rows or csv needed)
columnsNoOptional: column order and selection (rows only)
identityNoReader WeChat profile: off = anonymous (default) · wechat = only readers who tapped “Join with WeChat”, each row carries _by (nickname, avatar) · wechat_optional = rows carry the profile when the reader authorised, anonymous otherwise. The page reads the current reader with space.me() and asks for authorisation with space.me.request(). Passing it alone only flips the switch
revisionYes0 to create; the current value from get_data to replace or delete
vote_keyNoWhich column per_reader=vote counts one vote per reader per value on (must be a table column, e.g. item). Can be passed with per_reader or alone, with `revision`.
per_readerNoOne row per identity: off (default) allows repeats; one rejects repeats with 409; latest shows only the latest row per person on the page and keeps history in list_data_rows; vote allows one vote per reader per value (also pass vote_key=<column>; a repeat vote for the same value gets 409 reader_already_voted; withdrawing your own row frees it, with no 24-hour limit). Requires identity=wechat or wechat_optional. Anonymous rows are unrestricted; members use their user id. Withdrawal does not free a one slot. Can be set alone with `revision`.
append_openNo读者写回开关:true 开、false 关。单独传 = 只翻开关(底表不动,仍要带 revision)
proposal_idYes
members_onlyNoAccept write-back from workspace members only: when true, visitor submissions get 403. Passed alone = only flips the switch (`revision` still required)
notify_emailsNo新提交邮件通知:最多 3 个收件邮箱,读者每交一行(过审)发一封邮件给它们,附全部字段;新地址先收确认信、点确认后才发;[] = 不再通知。可单独传
identity_visibilityNoWho sees participants' nicknames and avatars: all = every reader (default) · author = only the author and workspace members. Passing it alone only flips the switch

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changed
    • changedInput schema / properties / per_reader / description
      Previous value: -"One row per identity: off (default) allows repeats; one rejects repeats with 409; latest shows only the latest row per person on the page and keeps history in list_data_rows. Requires identity=wechat or wechat_optional. Anonymous rows are unrestricted; members use their user id. Withdrawal does not free a one slot. Can be set alone with `revision`."New value: +"One row per identity: off (default) allows repeats; one rejects repeats with 409; latest shows only the latest row per person on the page and keeps history in list_data_rows; vote allows one vote per reader per value (also pass vote_key=<column>; a repeat vote for the same value gets 409 reader_already_voted; withdrawing your own row frees it, with no 24-hour limit). Requires identity=wechat or wechat_optional. Anonymous rows are unrestricted; members use their user id. Withdrawal does not free a one slot. Can be set alone with `revision`."
    • changedInput schema / properties / per_reader / enum
      Previous value: -[
      -  "off",
      -  "one",
      -  "latest"
      -]New value: +[
      +  "off",
      +  "one",
      +  "latest",
      +  "vote"
      +]
    • addedInput schema / properties / vote_key
      Added value: +{
      +  "anyOf": [
      +    {
      +      "maxLength": 64,
      +      "minLength": 1,
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "Which column per_reader=vote counts one vote per reader per value on (must be a table column, e.g. item). Can be passed with per_reader or alone, with `revision`."
      +}
  2. Changed1 schema field changed
    • addedInput schema / properties / per_reader
      Added value: +{
      +  "description": "One row per identity: off (default) allows repeats; one rejects repeats with 409; latest shows only the latest row per person on the page and keeps history in list_data_rows. Requires identity=wechat or wechat_optional. Anonymous rows are unrestricted; members use their user id. Withdrawal does not free a one slot. Can be set alone with `revision`.",
      +  "enum": [
      +    "off",
      +    "one",
      +    "latest"
      +  ],
      +  "type": "string"
      +}
  3. Changed1 schema field changed
    • changedInput schema / properties / identity / description
      Previous value: -"Reader WeChat profile (pilot workspaces only): off = anonymous (default) · wechat = only readers who tapped “Join with WeChat”, each row carries _by (nickname, avatar) · wechat_optional = rows carry the profile when the reader authorised, anonymous otherwise. The page reads the current reader with space.me() and asks for authorisation with space.me.request(). Passing it alone only flips the switch"New value: +"Reader WeChat profile: off = anonymous (default) · wechat = only readers who tapped “Join with WeChat”, each row carries _by (nickname, avatar) · wechat_optional = rows carry the profile when the reader authorised, anonymous otherwise. The page reads the current reader with space.me() and asks for authorisation with space.me.request(). Passing it alone only flips the switch"
  4. Changed2 schema fields changed
    • addedInput schema / properties / identity
      Added value: +{
      +  "description": "Reader WeChat profile (pilot workspaces only): off = anonymous (default) · wechat = only readers who tapped “Join with WeChat”, each row carries _by (nickname, avatar) · wechat_optional = rows carry the profile when the reader authorised, anonymous otherwise. The page reads the current reader with space.me() and asks for authorisation with space.me.request(). Passing it alone only flips the switch",
      +  "enum": [
      +    "off",
      +    "wechat",
      +    "wechat_optional"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / identity_visibility
      Added value: +{
      +  "description": "Who sees participants' nicknames and avatars: all = every reader (default) · author = only the author and workspace members. Passing it alone only flips the switch",
      +  "enum": [
      +    "all",
      +    "author"
      +  ],
      +  "type": "string"
      +}
  5. Changed1 schema field changed
    • addedInput schema / properties / notify_emails
      Added value: +{
      +  "description": "新提交邮件通知:最多 3 个收件邮箱,读者每交一行(过审)发一封邮件给它们,附全部字段;新地址先收确认信、点确认后才发;[] = 不再通知。可单独传",
      +  "items": {
      +    "maxLength": 254,
      +    "minLength": 3,
      +    "type": "string"
      +  },
      +  "maxItems": 3,
      +  "type": "array"
      +}
  6. Changed1 schema field changed
    • addedInput schema / properties / members_only
      Added value: +{
      +  "description": "Accept write-back from workspace members only: when true, visitor submissions get 403. Passed alone = only flips the switch (`revision` still required)",
      +  "type": "boolean"
      +}
  7. First observed

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructive/not-idempotent; the description adds far more: 409 rejection on stale revision, moderation and rate limiting of appended rows, 403 for visitors under members_only, a 24-hour self-withdrawal window, and unknown-column warnings in the receipt. These are consequences an agent cannot infer from the annotation flags.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The actions are front-loaded correctly, but the body is a single dense run-on paragraph stacking parentheticals, HTTP verbs, SDK calls and reader-view field names. Sizeable chunks describe downstream page-read behavior (_row_id, _at, _status, _mine) that belongs to list_data_rows or the page runtime rather than to this call, diluting the operative instructions.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 14-parameter, destructive, no-output-schema tool, the description covers the risky paths (revision conflict, delete, limits reported in the receipt) and explains the receipt since no output schema exists. It stops short of introducing five of the parameters that only appear in the schema, but with 93% schema coverage that gap is modest.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 93%, so the schema already carries most parameter meaning; the description nonetheless adds real semantics for the highest-risk ones — revision 0-vs-current behavior, rows/csv exclusivity, columns-as-order, and default-off append_open. It says nothing about notify_emails, identity, per_reader, vote_key or identity_visibility, leaving those entirely to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence gives a specific verb set and resource: "Attach a data table to a page, replace it entirely, delete it, or open/close reader write-back." It also implicitly separates this write tool from the read siblings by telling the agent to call get_data first and noting appended rows are "readable only through list_data_rows".

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit sequencing and conflict policy: "Call get_data first and pass the `revision` back unchanged: 0 creates, the current value updates; a mismatch is rejected (409) and requires re-reading, never blind overwrites." It also names the mutually exclusive input modes (rows vs csv) and states that a lone `append_open`/`members_only` only flips a switch rather than rewriting the table.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources