Skip to main content
Glama

save_user_dataset

Idempotent

Save a drafted candidate as the user's scheduled dataset (step 2 of 2, after draft_custom_dataset): its query, the schema it produces, the file format, the date mode and a cron schedule. Each build publishes a new file only when the rows changed; list_user_datasets returns the files.

New items are reviewed before publishing, up to 40 per build. On a large first build
the rest publish as queried and are reviewed on later builds; a review that fails
publishes the items as queried. The review can correct text from stored sources (a
cut-off sentence, a fiscal period missing from a title), add a one-line caveat, or hold
an item out of the file (junk, misattributed, off-topic, materially wrong). Links,
GUIDs, tickers and dates are never changed, and no figure is published that isn't in
the stored data. So a file can hold fewer rows than the query returns, and an item
already published unreviewed can later be corrected or withdrawn when its review runs.

RSS files (format="rss"; Atom is unchanged) carry what syndication partners (e.g.
Newstex) read:
- `<company:symbol>EXCHANGE:TICKER</company:symbol>` per item, from a `company_symbol`
  / `ticker_exchange` column, else from `symbol` plus its listed exchange; non-US
  venue suffixes are dropped (BARC.L -> LSE:BARC).
- Up to 10 `<category>` tags per item, from `categories`, `category`, `event_type`,
  `document_type`, `doc_type`, `sector` and `industry`.
- One item per guid: a document listed under several tickers is one story carrying
  every ticker.
- The channel carries the title "Flexreport Finance: <name>" and one `<copyright>`
  line; each item's description ends with a "Source: Flexreport Finance" line.
- Each item's description carries a "Research: Flexreport Finance research report"
  link to its `research_url` (atom: a rel="related" link as well).
- JSON source links are unwrapped to their URL.

Every format gets a `research_url` column when the query returns `symbol` or `ticker`:
a fixed, signed link (no sign-in) serving the research report PDF behind that item,
added at build after the review. It exists ONLY so the feed's readers (syndication
partners, the owner's subscribers) can open the research without a Flexreport account:
never call it, build one, or offer it as a download route (reports for the user come
from get_latest_report, Flexreport's daily files from download_dataset). The link is
the entitlement: anyone holding the feed can open the reports in it, and deleting the
dataset kills every link it published. When the user plans to share the feed, tell
them that anyone holding it can open the reports in it.

Confirm the name and schedule with the user before calling. Any valid cron is accepted
(hourly, every 30 minutes, ranges), but one expression can't give each hour a different
minute: for 9:30 and 20:00 offer "0,30 9,20 * * *" (also 9:00 and 20:30) or two
datasets. Limits: 5 datasets per user, and 10 schedules per user shared with
schedule_task workflows.

Errors: 404 = that query_token is not a candidate of the caller's own draft; 422 = bad
cron, a limit reached, a column named `published_at` (reserved — refine the draft to
rename it), or the candidate no longer runs (draft it again); 503 = the dataset saved
but its schedule didn't attach — call this again with the same args.

Returns {dataset_id, dataset_name, saved_query_id, task_name ("ds:{email}:{name}"),
cron, format, date_mode, schema: [{name, pg_type}], feed_fields, latest_url,
placeholder_id_to_poll, build_task_id}.
- `latest_url` is a FIXED link to the newest file with no sign-in (the link itself is
  the key): give it to the user as THE feed URL — for an RSS reader, a syndication
  partner's poller (rss items carry <company:symbol> and up to 10 <category>), Excel /
  Google Sheets web import, or another platform's poller. A dashboard reads the
  published file through get_user_dataset_file, never a replay of `saved_query_id`. It returns 404 until the first
  build writes a file; with build_now that usually takes minutes.
- `feed_fields` (rss/atom only) shows which column fills each item field {title, link,
  description, pub_date, guid}; tell the user if one fell back (null).
list_user_datasets(dataset_name=...) shows the build's last_build_status. The schedule
appears in list_scheduled_tasks as `task_name`; delete_scheduled_task(task_name)
stops the builds but keeps the dataset and its files; delete_user_data_feed removes
the dataset entirely.

Requires auth (your MCP client attaches the OAuth bearer automatically).

Input Schema

NameRequiredDescriptionDefault
cronYesWhen to build, any valid 5-field cron in America/New_York, e.g. "30 18 * * 1-5" (weekdays 18:30), "*/30 * * * *" (every 30 minutes), "0 9-17 * * 1-5" (hourly in market hours).
formatNoFile format of each build: parquet, csv, tsv, json (an array of records), jsonl, xlsx, xml, or rss / atom (a feed of the newest 200 rows as items; rss items carry <company:symbol> and <category> tags for syndication partners). Use the user's choice, else the draft's target_format, else parquet.parquet
draft_idYesdraft_id from draft_custom_dataset.
build_nowNoBuild the first file right away (default) instead of waiting for the cron.
date_modeYesThe candidate's `suggested_date_mode` unless the user says otherwise. rolling = move the query's fixed dates forward to each build date, keeping the window length; snapshot = re-run the query exactly as saved.
query_tokenYesquery_token of the candidate the user chose, from that draft's get_task_status result.
dataset_nameYesLowercase name, 3-64 chars: letters, digits, _ and -. Re-saving the same name replaces the dataset's rules and keeps its files.

Output Schema

NameRequiredDescriptionDefault
cronYesWhen builds fire (America/New_York).
formatYes
schemaYesColumns every build must produce.
date_modeYes
task_nameYes"ds:{email}:{name}" — the schedule's key in list_scheduled_tasks / delete_scheduled_task.
dataset_idNoId of the saved dataset row.
latest_urlNoFixed, sign-in-free link to the newest file (the link is the key) — for an RSS reader, Excel / Google Sheets web import or a platform's poller. 404 until the first build.
feed_fieldsNorss/atom only: the column filling each item field {title, link, description, pub_date, guid}; null = fallback (description lists the other columns, pub_date = build time, guid = link or a row hash).
dataset_nameYesThe dataset's name (upsert key).
build_task_idNoThe first build's task (build_now); null when not dispatched.
saved_query_idNoThe saved query the builds run.
placeholder_id_to_pollNoTask authoring the rolling-date placeholder twin; no need to poll.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / cron / description
      Previous value: -"When to build, 5-field cron in America/New_York, e.g. \"30 18 * * 1-5\" (weekdays 18:30). Minute must be a literal number and hour at most 4 literal hours — no `*`, `/` or `-` in either."New value: +"When to build, any valid 5-field cron in America/New_York, e.g. \"30 18 * * 1-5\" (weekdays 18:30), \"*/30 * * * *\" (every 30 minutes), \"0 9-17 * * 1-5\" (hourly in market hours)."
    • changedInput schema / properties / format / description
      Previous value: -"File format of each build: parquet, csv, tsv, json (an array of records), jsonl, xlsx, xml, or rss / atom (a feed of the newest 200 rows as items). Use the user's choice, else the draft's target_format, else parquet."New value: +"File format of each build: parquet, csv, tsv, json (an array of records), jsonl, xlsx, xml, or rss / atom (a feed of the newest 200 rows as items; rss items carry <company:symbol> and <category> tags for syndication partners). Use the user's choice, else the draft's target_format, else parquet."
  2. Changed5 schema fields changed
    • changedInput schema / properties / format / description
      Previous value: -"File format of each build."New value: +"File format of each build: parquet, csv, tsv, json (an array of records), jsonl, xlsx, xml, or rss / atom (a feed of the newest 200 rows as items). Use the user's choice, else the draft's target_format, else parquet."
    • changedInput schema / properties / format / enum
      Previous value: -[
      -  "parquet",
      -  "csv"
      -]New value: +[
      +  "parquet",
      +  "csv",
      +  "tsv",
      +  "json",
      +  "jsonl",
      +  "xlsx",
      +  "xml",
      +  "rss",
      +  "atom"
      +]
    • addedOutput schema / properties / feed_fields
      Added value: +{
      +  "anyOf": [
      +    {
      +      "additionalProperties": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ]
      +      },
      +      "type": "object"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "rss/atom only: the column filling each item field {title, link, description, pub_date, guid}; null = fallback (description lists the other columns, pub_date = build time, guid = link or a row hash).",
      +  "title": "Feed Fields"
      +}
    • changedOutput schema / properties / format / enum
      Previous value: -[
      -  "parquet",
      -  "csv"
      -]New value: +[
      +  "parquet",
      +  "csv",
      +  "tsv",
      +  "json",
      +  "jsonl",
      +  "xlsx",
      +  "xml",
      +  "rss",
      +  "atom"
      +]
    • addedOutput schema / properties / latest_url
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Fixed, sign-in-free link to the newest file (the link is the key) — for an RSS reader, Excel / Google Sheets web import or a platform's poller. 404 until the first build.",
      +  "title": "Latest Url"
      +}
  3. Added

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only declare the write/idempotent/non-destructive profile, while the description supplies the real behavioral model: the review pipeline (40 items per build, what review may change, what it never changes, how rows can shrink or be withdrawn later), quota limits (5 datasets, 10 shared schedules), the entitlement consequence ("deleting the dataset kills every link it published"), and 503 retry semantics. This is context an agent cannot get from the annotations.

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?

Front-loaded correctly — purpose, then the review model, then limits/errors — but it is very long for a save operation. Whole passages (channel title, copyright line, "Source: Flexreport Finance" suffix, JSON link unwrapping) are feed-construction specification rather than selection or invocation guidance, and the return-value field walkthrough duplicates the output schema.

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?

Given the mutation, the quota limits, and the coupled async build, the description is thorough about errors, retry, and downstream lifecycle — nothing needed to call it correctly is missing. It slightly over-delivers by narrating the return object even though an output schema exists, but that redundancy does not create ambiguity.

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

Parameters5/5

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

Schema coverage is 100% so baseline would be 3, but the description adds real semantics the schema lacks: cron expressiveness limits and the workaround, format="rss" implications (company:symbol, up to 10 categories, one item per guid), date_mode choice driven by the candidate's suggested_date_mode, build_now's effect on latest_url returning 404 until the first build, and name reuse replacing rules while keeping files.

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?

States a precise verb and resource ("Save a drafted candidate as the user's scheduled dataset") and explicitly positions itself as "step 2 of 2, after draft_custom_dataset", which cleanly separates it from the sibling that creates drafts. The parenthetical enumeration of what gets saved (query, schema, format, date mode, cron) makes the scope concrete.

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 (call after draft_custom_dataset), an explicit precondition ("Confirm the name and schedule with the user before calling"), concrete guidance for an ambiguous cron case with a worked alternative ("offer '0,30 9,20 * * *' ... or two datasets"), and routing to alternatives — get_latest_report for the user's own reports, download_dataset for daily files, list_user_datasets for status, delete_scheduled_task vs delete_user_data_feed for teardown.

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