Simpler.Asia
mcp remote · streamable-http · v1.0.0 · source: crawl
https://simpler.asia/mcp
Free back office for small businesses in Singapore and Southeast Asia: invoices, expenses, stock.
Works
80
Verified Oct 31, 2026 · p50 1930 ms · p95 2307 ms
Worth
no data
No outcomes reported yet. Agents report through report_outcome after a find_agents call.
Checks
| Check | Weight | Result | Evidence |
|---|---|---|---|
| reachable | 20 | pass | 3 of 3 handshakes succeeded; server 'simpler-prod' |
| tools_listed | 15 | pass | 318 tools |
| schema_complete | 15 | pass | 318 of 318 tools have a description and a typed schema |
| latency_p50 | 10 | fail | p50 1930 ms |
| latency_p95 | 5 | pass | p95 2307 ms |
| error_free | 10 | pass | 0 of 3 attempts failed |
| auth_posture | 10 | pass | https, open |
| injection_scan | 10 | fail | invoice_handoff: sends credentials |
| scope | 5 | pass | no execution-style tools |
Unknown counts as fail; n/a is left out of the denominator. How the weights work.
Tools (318)
| Name | Description | Schema |
|---|---|---|
interaction_list | List your interaction rows (newest first). | typed |
interaction_read | Read one interaction by id. | typed |
simpler.describe_service | DISCOVERY TIER 2 of 3 — one service's operations and entity shapes from the live catalog, token-dense (op lines name the underlying tool). No auth required. NEXT: simpler.invoke {service, operation, a | typed |
simpler.directory | DISCOVERY TIER 1 of 3 — the service directory: one token-dense line per service (s:name st:status cost:class ops:N — purpose). START HERE instead of reading every tool. No auth required. NEXT: simpler | typed |
simpler.invoke | DISCOVERY TIER 3 of 3 — execute one operation: dispatches to the underlying generated tool (same gates, same envelope, same idempotency as calling it directly). Requires auth. args = the underlying to | typed |
simpler.outcomes | DISCOVERY TIER 0 — the OUTCOME MENU: one line per common business outcome, each mapped to ONE tool with one-call notes (composites: ONE call creates the whole document). START HERE for a business task | typed |
simpler.approval_status | Check a parked approval by approval_id (returned in an APPROVAL_REQUIRED refusal). States: pending (the account owner has not decided — tell the user, do NOT retry the original call), executed (done — | typed |
agent_note_send_cross_tenant | Send a cross-tenant AI-to-AI message into another tenant's agent_note inbox — the door that turns a cross_tenant_comm consent grant into an actual reach. Both tenants must be KYB-approved and the reci | typed |
contact_upsert | Create-or-merge a contact keyed on email-then-phone identity — the sync door the future desktop harness and ingest lanes write through. Matching probes email first, then phone; a hit MERGES only the f | typed |
expense_create | Logs a new expense — amount_cents must be integer CENTS (a decimal string via `amount` also works, and `category` resolves to a category_id by name). A same-amount, same-UTC-day duplicate for the same | typed |
ai.estimate_cost | Price an AI task BEFORE running it: provider passthrough at wholesale cost, no markup — the per-token platform fee is retired, so text/reasoning passes through at cost. Anonymous — open catalog includ | typed |
expense_submit | Sends your own draft expense into the approval queue — draft only; an already-submitted or resolved expense refuses CONFLICT, and only the expense's own creator may submit it. Nobody is notified autom | typed |
expense_approve | Approves a submitted expense claim — requires the admin or owner role, and only a 'pending' expense qualifies (CONFLICT otherwise). Stamps approved_by and approved_at with the caller and the current t | typed |
interaction_create | Log an interaction — call, meeting, email, message, visit, payment, or other — against a contact. The ONE activity-logging door every lane funnels through, so the contact's last_contact_at freshness b | typed |
invoice_create | ONE call creates the whole document: claims the next invoice number, then writes the header plus every line in `items` ([{description, quantity, unit_price_cents}], integer CENTS). client_name finds a | typed |
invoice_adjustment_record | [REQUIRES APPROVAL] Records a credit note, write-off or post-issue discount on an issued invoice. A credit_note is numbered from the credit note series, holds its tax at the invoice's rate and takes r | typed |
consent_grant_list | List your consent_grant rows (newest first). | typed |
consent_grant_read | Read one consent_grant by id. | typed |
invoice_payment_record | Records a money-in fact row against an invoice (by invoice_id or its invoice_number) in ONE call: money is integer CENTS via amount_cents, or a decimal STRING via amount — never multiply or divide you | typed |
myinvois_invoice_generate | Mint a sealed LHDN e-invoice in ONE call: invoice_type, line_items (unit_price_cents in integer CENTS, tax_rate_bps in basis points), and a buyer as customer_id or an inline buyer object. Refuses unti | typed |
myinvois_invoice_record_submission | Record the UUID the LHDN MyInvois portal assigned after the owner keyed this e-invoice into the portal (its form or LHDN's Excel batch template). Simpler never submits to LHDN and never calls the MyIn | typed |
myinvois_invoice_read | Read one sealed e-invoice by id, with its portal_field_sheet: the document's values laid out to key into the LHDN MyInvois portal form (e-invoice details, supplier, buyer, each line, totals), coded va | typed |
quote_create | ONE call creates the whole document: claims the next atomic quote number, then writes the header plus every line in `items` ([{description, quantity, unit_price_cents}], integer CENTS) together. clien | typed |
quote_convert | Converts a quote into its invoice in ONE call: claims the quote's 'converted' status first (so a lost race never creates an orphan invoice), copies every live line item across, and records converted_i | typed |
expense_aggregate | Aggregate (count/sum) over your expense rows. | typed |
settlement_proposal_propose_cross_tenant | Record a payment obligation against a KYB-verified partner tenant's settlement_proposals — the record-don't-move on-ramp: this writes the row only, no money moves until a later settlement-rails door e | typed |
sticky_note_create | Create a sticky_note. | typed |
stock_item_adjust | Move stock in or out by id or item name, in one atomic write with its movements-ledger row: stock-out clamps at zero (never negative) and applied_quantity reports what actually moved. An unmatched nam | typed |
team_assignment_create | [REQUIRES APPROVAL] Delegates a task to a teammate (or yourself) as a new team_assignment; status is workflow-owned and always starts 'pending' — passing status yourself fails validation instead of be | typed |
workflow_create | Create a workflow — an AI operator's job: validates definition_json (a { nodes, edges, schedule? } graph) against the platform's node vocabulary, refusing unknown node types and any comms/message-shap | typed |
workflow_prepared_outputs | List this tenant's APPROVED prepared outputs: drafts a workflow's prepare_output nodes parked for review, which a human then approved in the platform inbox. Pending and rejected drafts never appear he | typed |
ai.budget | Your prepaid wallet, period spend, caps, and runway as a compact line DSL (~8 lines). Requires auth (your balance is closed data). Read this BEFORE committing paid actions; pair with ai.estimate_cost | typed |
expense_budget_create | Create a expense_budget. | typed |
sales_receivables | Who owes you, by client: each client's unpaid balance aged by days past its due date — current (not yet due), 1-30, 31-60, 61-90 and over 90 days — counted in the business's own days (the sales_settin | typed |
sales_document_show | Show one invoice, quote or receipt as the document itself. When the result has a second content block, it is the document as copy-ready plain text (title, business, billed to, dates, one line per item | typed |
invoice_message_prepare | Prepare what a business sends a client about one issued invoice: purpose 'invoice', 'reminder' (overdue), 'receipt' (paid in full) or 'promise_follow_up' (promised date passed); left out, the one that | typed |
invoice_reminders_due | Today's collection list, in the business's days (its sales_settings time zone). reminders: each issued invoice still owed that is 3 days before its due date, on it, or 7 or 14 days after, as its clien | typed |
statement_prepare | A client's statement of account over a period of the business's own days (the sales_settings time zone): the balance they owed before it (opening), each invoice issued, payment received, credit and wr | typed |
invoice_handoff | Get one issued invoice ready to give the client, in one call: the document, the client link (made if it has none), the PDF (printed or the stored one) and the prepared message (invoice_message_prepare | typed |
forecast.run | WHAT-IF / scenario lane: runs monthly data YOU supply through a seeded 5,000-path simulation of monthly revenue and costs; bands are simulation outputs, not calibrated probabilities. The paths are clu | typed |
forecast.run_stored | Run the tenant's REAL forecast from the books — cash receipts (recorded invoice payments by payment date, plus paid invoices with no recorded payment at their paid date, flagged) and expenses by expen | typed |
forecast.read | Read the tenant's STORED forecast — the verify-read for this rail. view picks the answer, one of summary, monthly, variance, scenarios, weekly (default summary). summary: the outcome bands (label, gro | typed |
image.generate | [paid: $0.042/image max] Generate 1-3 images from a text prompt on the first lane that delivers, tried in order: gemini-2.5-flash-image via the Cloudflare AI Gateway, square requests only ($0.0406/ima | typed |
document.extract | Fetch a document from a URL, classify its type (personal/medical/business/unknown) with keyword + PII-pattern heuristics (documents containing actual PII data are NEVER business), and return extracted | typed |
spreadsheet.create_with_content | Create a spreadsheet in the user's library from CSV content in ONE call: the platform stores the bytes (honest text/csv) and registers the file row. Free — storage costs nothing; only AI lanes bill. R | typed |
agent_note_mark_read | Confirm receipt of a note in your cross-tenant agent_note inbox — the ONLY edit a recipient holds, moving status unread to read under the registry's transition guard. Idempotent: re-confirming an alre | typed |
agent_note_list | List your agent_note rows (newest first). | typed |
agent_note_read | Read one agent_note by id. | typed |
brand_assets_read | Read one brand_assets by id. | typed |
brand_assets_list | List your brand_assets rows (newest first). | typed |
contact_create | Create a contact and, in the same call, log its first note and/or first interaction — the composite first-touch door. Children validate before the contact write; if the contact commits but a child the | typed |
contact_update | Update a contact you own (optionally compare-and-set via expected_updated_at). | typed |
contact_delete | Delete a contact you own. | typed |
contact_read | Read one contact by id. | typed |
contact_list | List your contact rows (newest first). | typed |
contact_search | Search your contact rows by text. | typed |
contact_note_create | Add a note to a contact — the same door as the granular tool, extended only to accept contact_name, contact_email or contact_phone in place of contact_id. A name match must be unique: more than one hi | typed |
contact_note_list | List your contact_note rows (newest first). | typed |
contact_note_read | Read one contact_note by id. | typed |
contact_note_delete | Delete a contact_note you own. | typed |
desk_surface_create | Pins one widget or a saved artifact onto the operator's home canvas. kind='widget' requires widget_key from the shipped enum; kind='artifact' requires content_ref (an assistant artifact id) — the door | typed |
desk_surface_update | Moves, resizes, or restacks a surface already on the desk canvas — x/y/w/h/z_index are real column writes, not a layout cache. The surface's identity is frozen here: kind, widget_key, and content_ref | typed |
desk_surface_read | Read one desk_surface by id. | typed |
desk_surface_list | List your desk_surface rows (newest first). | typed |
desk_surface_delete | Delete a desk_surface you own. | typed |
edit_project_create | Create a canvas project from a Fabric.js toJSON serialization (canvas_json, required): every embedded data:image src is pulled out, hashed, and written to a tenant-scoped, content-addressed R2 key bef | typed |
edit_project_update | Save changes to an existing canvas project by id — the autosave door: send only the fields that changed (name, canvas_json, width, height, thumbnail_data_url), everything else on the row is left alone | typed |
edit_project_read | Read one edit_project by id. | typed |
edit_project_list | List your edit_project rows (newest first). | typed |
edit_project_delete | Delete a edit_project you own. | typed |
expense_budget_update | Update a expense_budget you own (optionally compare-and-set via expected_updated_at). | typed |
expense_budget_delete | Delete a expense_budget you own. | typed |
expense_budget_read | Read one expense_budget by id. | typed |
expense_budget_list | List your expense_budget rows (newest first). | typed |
expense_update | Edits an expense's own fields only — status and approval stamps refuse with VALIDATION_ERROR here since those are transitions (expense_submit, expense_approve, expense_reject, expense_reimburse). amou | typed |
expense_delete | Deletes an expense you created — draft and rejected rows only. Pending, approved, and reimbursed rows are approval-trail records and refuse with CONFLICT (approval_locked: true), and the lock is pinne | typed |
expense_reject | Rejects a submitted expense claim — requires the admin or owner role, and only a 'pending' expense qualifies (CONFLICT otherwise). rejection_reason (up to 500 chars) is optional but records why; rejec | typed |
expense_reimburse | Marks an approved expense as paid out — restricted to the tenant owner because it moves real money, and only an 'approved' expense qualifies (CONFLICT otherwise). Stamps reimbursed_at, after which the | typed |
expense_read | Read one expense by id. | typed |
expense_list | List your expense rows (newest first). | typed |
expense_search | Search your expense rows by text. | typed |
expense_category_create | Adds a custom category to your tenant's category table — slug must be 1-50 chars of lowercase a-z, 0-9, '-' or '_' and unique per tenant (CONFLICT if taken). is_default is server-owned: supplying it a | typed |
expense_category_update | Edits a category's name, icon, color, or sort_order — slug and is_default are the category's fixed identity, and any attempt to change either refuses with VALIDATION_ERROR. color, when given, must be | typed |
expense_category_delete | Deletes a custom category — categories are tenant-shared, so any tenant member can remove one regardless of who created it; the 9 seeded defaults are undeletable and refuse with CONFLICT (default_cate | typed |
expense_category_ensure_defaults | Seeds the 9 canonical default categories (Food & Dining, Transport, Utilities, Shopping, Entertainment, Healthcare, Travel, Office & Supplies, Other) into your tenant, skipping any slug that already e | typed |
expense_category_read | Read one expense_category by id. | typed |
expense_category_list | List your expense_category rows (newest first). | typed |
expense_recurrence_create | Create a expense_recurrence. | typed |
expense_recurrence_update | Update a expense_recurrence you own (optionally compare-and-set via expected_updated_at). | typed |
expense_recurrence_delete | Delete a expense_recurrence you own. | typed |
expense_recurrence_read | Read one expense_recurrence by id. | typed |
expense_recurrence_list | List your expense_recurrence rows (newest first). | typed |
interaction_upsert | Create-or-update a interaction keyed on source_ref. | typed |
invoice_update | Edits an invoice's header fields and status. status 'paid' cannot be set here — it derives from the payment ledger, so call invoice_payment_record instead. Status moves are machine-checked (draft to s | typed |
invoice_share | Returns share_url, the client's view link for this invoice, and the full document (parties, lines, totals in integer CENTS) in one call. action: 'get' (default) returns the live link; 'rotate' replace | typed |
invoice_payer_confirmation | Acts on a payer's report, sent from the invoice's client page, that they have paid. action 'accept' records the payment with the same writer as invoice_payment_record, graded counterparty_confirmed: t | typed |
invoice_debit_note | [REQUIRES APPROVAL] Issues a numbered debit note that raises what an issued ('sent' or 'paid') invoice is owed: an extra charge, or a price or tax correction. It is numbered from the debit note series | typed |
invoice_adjustment_delete | [REQUIRES APPROVAL] Retires a dilution fact row — the only correction lane (adjustments are append-only; amounts are never edited). If the retired row was a credit that settled the invoice, the status | typed |
invoice_reissue | Voids a 'sent' invoice with no money on it and reissues it under the next number: 'sent', dated today, same client, currency, notes, terms and lines, tax on today's rules, the old days to pay unless d | typed |
invoice_promise_set | Records the date a client promised to pay an issued invoice that still has money owed: promised_payment_date 'YYYY-MM-DD', the business's own date, today or later. clear true removes it. invoice_read | typed |
invoice_read | Returns one invoice with its money and state worked out on read, in integer CENTS: subtotal_cents, tax_cents, total_cents, paid_cents, credited_cents, adjusted_cents, remaining_cents (copy remaining_c | typed |
invoice_list | Lists your invoices, newest first (200 at most; pass limit and cursor to page). Every row carries the same worked-out money and state as invoice_read: total_cents, remaining_cents, state, is_overdue, | typed |
invoice_search | Finds invoices whose text fields (invoice number, notes, payment terms) contain every word of q. Rows carry the same worked-out money and state as invoice_read: total_cents, remaining_cents, state, is | typed |
invoice_adjustment_read | Read one invoice_adjustment by id. | typed |
invoice_adjustment_list | List your invoice_adjustment rows (newest first). | typed |
invoice_client_create | Create a invoice_client. | typed |
invoice_client_upsert | Create-or-update a invoice_client keyed on email. | typed |
invoice_client_update | Update a invoice_client you own (optionally compare-and-set via expected_updated_at). | typed |
invoice_client_delete | Delete a invoice_client you own. | typed |
invoice_client_read | Read one invoice_client by id. | typed |
invoice_client_list | List your invoice_client rows (newest first). | typed |
invoice_client_search | Search your invoice_client rows by text. | typed |
invoice_client_link_tenant | [REQUIRES APPROVAL] Asserts that a billing client IS an on-platform tenant (or pass counterparty_tenant_id null to unlink) and retro-stamps that client's existing invoices with the link in the same ca | typed |
invoice_item_create | Adds one line item to an invoice. unit_price_cents is integer CENTS, 0 or more ($15.00 → 1500); quantity is 0.001 to 1,000,000 with up to 3 decimals (1.5 hours → 1.5); unit is an optional label (hr, k | typed |
myinvois_settings_list | List the supplier profile: at most one row per tenant. An empty list means setup is not done, and myinvois_invoice_generate refuses until it is: call myinvois_settings_save with the company, TIN, BRN, | typed |
invoice_item_update | Edits a line item's description, quantity, unit, price or discount, or re-parents it to another invoice. expected_updated_at is required: the line's updated_at from your read; without it nothing is wr | typed |
invoice_item_delete | Soft-deletes a line item — it leaves the invoice and its derived total immediately, but the row is retired for audit history, never removed. expected_updated_at is required: the line's updated_at from | typed |
invoice_item_read | Read one invoice_item by id. | typed |
invoice_item_list | List your invoice_item rows (newest first). | typed |
invoice_payment_read | Read one invoice_payment by id. | typed |
invoice_payment_list | List your invoice_payment rows (newest first). | typed |
invoice_payment_delete | [REQUIRES APPROVAL] Retires a payment fact row — the only correction lane (payments are append-only; amounts are never edited). If retiring it un-settles the invoice, the reversal itself rolls the sta | typed |
invoice_recurring_create | Create a invoice_recurring. | typed |
myinvois_template_create | Save a reusable line-item preset so a repeat invoice's items do not get re-typed. line_items_json is parsed and each item validated by the SAME checker myinvois_invoice_generate uses (description, qua | typed |
invoice_recurring_update | Update a invoice_recurring you own (optionally compare-and-set via expected_updated_at). | typed |
invoice_recurring_delete | Delete a invoice_recurring you own. | typed |
invoice_recurring_read | Read one invoice_recurring by id. | typed |
invoice_recurring_list | List your invoice_recurring rows (newest first). | typed |
invoice_recurring_skip | Skips a recurring template's next invoice: next_due moves one period on (the template's own weekly, monthly or yearly day) and no invoice is made. A skip does not count toward max_invoices. Refuses NO | typed |
market_signal_create | Post to one of the tenant's 8 market-signal wish-bar slots — a buy, sell, swap, capacity-offer or capacity-request visible ONLY to platform-matched partners, never the wider network. The door counts y | typed |
market_signal_update | Update a market_signal you own (optionally compare-and-set via expected_updated_at). | typed |
market_signal_list | List your market_signal rows (newest first). | typed |
market_signal_read | Read one market_signal by id. | typed |
myinvois_customer_create | Register a buyer in the LHDN buyer registry so it attaches to future e-invoices with one pick (customer_id) instead of typing the party every time. Validates the TIN format, and validates state_code a | typed |
studio_environment_read | Read one studio_environment by id. | typed |
myinvois_customer_update | Edit a registered buyer's LHDN details — send only the fields you are changing. When tin is included it is re-checked against the same format gate create runs, and when state_code is included it is re | typed |
myinvois_customer_delete | Delete a registered buyer. E-invoices already generated for this buyer keep their sealed copy of the buyer party and are never touched. Refuses an id outside your tenant with NOT_FOUND: call myinvois_ | typed |
myinvois_customer_read | Read one registered buyer by id: name, TIN, BRN, SST number, address and contact. myinvois_invoice_generate seals the name, TIN, BRN, address and contact; the buyer's SST number stays on this record a | typed |
myinvois_customer_list | List registered buyers, newest first, to pick a customer_id for myinvois_invoice_generate. An empty list means none are registered yet: call myinvois_customer_create, or send an inline buyer {name, ti | typed |
myinvois_customer_search | Find registered buyers by text: every word must match one of the buyer's text fields, such as name, TIN, BRN, email or address. Refuses an empty q with VALIDATION_ERROR. No match returns an empty list | typed |
myinvois_invoice_list | List your myinvois_invoice rows (newest first). | typed |
myinvois_invoice_search | Find generated e-invoices by text: every word must match one of the document's text fields, such as invoice number, buyer name or buyer TIN. Refuses an empty q with VALIDATION_ERROR. Rows carry no fie | typed |
myinvois_settings_save | [REQUIRES APPROVAL] Save the one-time LHDN supplier profile — the door checks for an existing row on your tenant and creates or updates in place, so this is the only write you ever call. Validates the | typed |
myinvois_settings_read | Read the supplier profile by id: the party printed on every e-invoice (company, TIN, BRN, SST and tourism tax numbers, MSIC code, address). Refuses an id outside your tenant with NOT_FOUND: call myinv | typed |
myinvois_template_update | Edit a saved line-item preset. When line_items_json is included it is re-parsed and every item re-validated exactly as create does, so an edited template cannot drift into a shape myinvois_invoice_gen | typed |
myinvois_template_delete | Delete a saved line-item preset. E-invoices generated from it are never touched: each one sealed its own lines. Refuses an id outside your tenant with NOT_FOUND: call myinvois_template_list for valid | typed |
myinvois_template_read | Read one line-item preset by id. Its line_items_json holds generate-ready items: pass them as line_items to myinvois_invoice_generate. Refuses an id outside your tenant with NOT_FOUND: call myinvois_t | typed |
myinvois_template_list | List saved line-item presets, newest first. Each line_items_json is generate-ready: pass its items as line_items to myinvois_invoice_generate. An empty list means none are saved yet: call myinvois_tem | typed |
quote_update | Edits a quote's header fields and bookkeeping status (draft, sent, accepted, declined move freely). status 'converted' and converted_invoice_id are convert-flow-owned — hand-setting either refuses, an | typed |
quote_share | Returns share_url, the client's view link for this quote, and the full document (parties, lines, totals in integer CENTS) in one call. action: 'get' (default) returns the live link; 'rotate' replaces | typed |
quote_read | Returns one quote with subtotal_cents, tax_cents and total_cents worked out from its live lines (integer CENTS) and effective_status, which reads 'expired' once a sent quote's valid_until has passed ( | typed |
quote_list | Lists your quotes, newest first (200 at most; pass limit and cursor to page). Every row carries total_cents (integer CENTS) and effective_status, so an expired quote reads 'expired'. Refuses a limit o | typed |
quote_search | Finds quotes whose text fields (quote number, notes) contain every word of q; rows carry total_cents (integer CENTS) and effective_status. Refuses an empty q with VALIDATION_ERROR: send the quote numb | typed |
quote_item_create | Adds one line item to a quote. unit_price_cents is integer CENTS, 0 or more ($15.00 → 1500); quantity is 0.001 to 1,000,000 with up to 3 decimals (1.5 hours → 1.5); unit is an optional label (hr, kg); | typed |
quote_item_update | Edits a quote line's description, quantity, unit, price or discount, or moves it to another quote. expected_updated_at is required: the line's updated_at from your read; without it nothing is written | typed |
quote_item_delete | Soft-deletes a quote line — it leaves the quote and its totals immediately, but the row is retired for audit history, never removed. expected_updated_at is required: the line's updated_at from your re | typed |
quote_item_read | Read one quote_item by id. | typed |
quote_item_list | List your quote_item rows (newest first). | typed |
sales_settings_upsert | [REQUIRES APPROVAL] Saves your business identity and document defaults (one row per business; scope is 'default'). timezone is the business clock: an invoice turns overdue at midnight in that zone aft | typed |
studio_environment_list | List your studio_environment rows (newest first). | typed |
sales_settings_numbering_set | [REQUIRES APPROVAL] Sets where a document type's numbers continue, for example after moving from another invoicing tool. doc_type: invoice, quote, credit_note, debit_note or receipt. next_number is th | typed |
sales_settings_list | List your sales_settings rows (newest first). | typed |
sales_settings_read | Read one sales_settings by id. | typed |
settlement_proposal_accept | Accept a settlement obligation recorded against your tenant as payee — moves status proposed to accepted and stamps accepted_at under the registry's transition guard. Calling it again on an already-ac | typed |
settlement_proposal_list | List your settlement_proposal rows (newest first). | typed |
settlement_proposal_read | Read one settlement_proposal by id. | typed |
spreadsheet_file_create | Register a spreadsheet file row in the library for bytes that already sit in R2: r2_key must be a spreadsheets/<your tenant>/ key minted by the upload route or spreadsheet.create_with_content — a call | typed |
spreadsheet_file_update | Edit a spreadsheet file's metadata — title, tags, folder_id, or the AI-analysis fields — without touching the underlying R2 object. r2_key and source are birth facts: including either field in the cal | typed |
studio_environment_update | Update a studio_environment you own (optionally compare-and-set via expected_updated_at). | typed |
spreadsheet_file_delete | Soft-delete a spreadsheet file: stamps deleted_at on the row so it drops out of the library and folder listings, while the row and its R2 object both survive untouched — there is no purge or restore l | typed |
spreadsheet_file_read | Read one spreadsheet_file by id. | typed |
spreadsheet_file_list | List your spreadsheet_file rows (newest first). | typed |
spreadsheet_file_search | Search your spreadsheet_file rows by text. | typed |
spreadsheet_folder_create | Create a spreadsheet_folder. | typed |
spreadsheet_folder_update | Update a spreadsheet_folder you own (optionally compare-and-set via expected_updated_at). | typed |
spreadsheet_folder_delete | Delete a spreadsheet_folder you own. | typed |
spreadsheet_folder_read | Read one spreadsheet_folder by id. | typed |
spreadsheet_folder_list | List your spreadsheet_folder rows (newest first). | typed |
sticky_note_list | List your sticky_note rows (newest first). | typed |
sticky_note_update | Update a sticky_note you own (optionally compare-and-set via expected_updated_at). | typed |
sticky_note_delete | Delete a sticky_note you own. | typed |
sticky_note_due | Read this tenant's sticky notes whose reminder time (triggers_at) has arrived — the poll the desktop host runs to know what to fire as a local notification, since the web itself has no send channel. R | typed |
studio_environment_delete | Delete a studio_environment you own. | typed |
sticky_note_dismiss | Clear a sticky note's reminder (triggers_at back to NULL) so it drops out of the sticky_note_due poll — call this after the host fires the local notification for it. Runs through the same tenant-scope | typed |
stock_item_create | Create a stock_item. | typed |
stock_item_update | Update a stock_item you own (optionally compare-and-set via expected_updated_at). | typed |
stock_item_delete | Soft-delete a stock item by id: sets is_active to 0 while its movements-ledger history stays intact. stock_item_adjust then refuses the id as NOT_FOUND and stops resolving it by name, so a later deliv | typed |
stock_item_read | Read one stock_item by id. | typed |
stock_item_list | List your stock_item rows (newest first). | typed |
stock_item_search | Search your stock_item rows by text. | typed |
studio_character_create | Create a studio_character. | typed |
studio_character_read | Read one studio_character by id. | typed |
studio_character_list | List your studio_character rows (newest first). | typed |
studio_character_update | Update a studio_character you own (optionally compare-and-set via expected_updated_at). | typed |
studio_character_delete | Delete a studio_character you own. | typed |
studio_environment_create | Create a studio_environment. | typed |
studio_project_create | Create a video studio project — the composition document (scenes, tracks, clips, captions) starts empty and is built up afterward through the studio.* director tools. thumbnail_key is server-owned: se | typed |
studio_project_read | Read one studio_project by id. | typed |
studio_project_list | List your studio_project rows (newest first). | typed |
studio_project_update | Rename a project, change its status, or replace its thumbnail on a project you own — send thumbnail_data_url, never thumbnail_key, which is server-owned and computed by this door the same way studio_p | typed |
studio_project_delete | Delete a studio_project you own. | typed |
team_assignment_update | Edits an assignment's content (title/description/priority/due_at/attachment) — only the assigner may call this, and only before the job reaches a terminal state. assigned_to cannot move here even thou | typed |
team_assignment_delete | Deletes an assignment outright — only the assigner may call this. The row is removed first, then its attachment and any job photos are best-effort deleted from R2 afterward, so a storage hiccup never | typed |
user_setting_list | List your user_setting rows (newest first). | typed |
team_assignment_accept | Accepts a pending job — only the assignee may call this, and only while the assignment is still 'pending'; it stamps accepted_at and moves status to 'accepted'. NEXT: team_assignment_start once you be | typed |
team_assignment_start | Marks a job as started — only the assignee, and only from status 'accepted'; it stamps started_at and moves status to 'in_progress'. NEXT: team_assignment_add_photo for proof, then team_assignment_com | typed |
team_assignment_complete | Finishes a job — only the assignee, and only from status 'in_progress'; it stamps completed_at, moves status to 'completed', and stores completion_notes when you supply them. Completed is terminal: th | typed |
team_assignment_decline | Declines a job — only the assignee, and only while it is 'pending' or 'accepted'; decline_reason is required and is stamped alongside declined_at. Declined is terminal, same as completed: the assignme | typed |
user_setting_search | Search your user_setting rows by text. | typed |
user_setting_delete | Delete a user_setting you own. | typed |
team_assignment_reassign | Hands an assignment to a different tenant member — only the original assigner or an admin+, never the current assignee reassigning themself, and never onto a terminal (completed/declined) row. It rese | typed |
team_assignment_undo_reassign | Reverts an assignment's most recent reassignment — restores the previous assignee and status. Only the person who performed that reassignment may call it, and only within the 30-second window after it | typed |
team_assignment_add_photo | Attaches a job photo to an assignment — only the assignee, and only while the job is 'accepted', 'in_progress', or 'completed'. photo_key must be one minted by POST /api/desk/assignments/upload for th | typed |
team_assignment_read | Read one team_assignment by id. | typed |
team_assignment_list | List your team_assignment rows (newest first). | typed |
user_interest_upsert | Create-or-update a user_interest keyed on interest. | typed |
user_interest_list | List your user_interest rows (newest first). | typed |
user_interest_delete | Delete a user_interest you own. | typed |
user_setting_upsert | Create-or-update a user_setting keyed on key. | typed |
user_setting_read | Read one user_setting by id. | typed |
workflow_update | Edit a workflow's fields or its definition graph: every call re-validates the definition — yours if resent, else the stored one decoded back — against the resulting trigger_type, so a plain rename can | typed |
workflow_read | Read one workflow by id. | typed |
workflow_list | List your workflow rows (newest first). | typed |
workflow_delete | Delete a workflow you own. | typed |
invoice_pdf | Make the PDF of an issued invoice (or of its receipt once paid): the same document as its print-ready page, printed on A4 with the business's fonts, brand colours and logo, and kept, so asking again f | typed |
sales_settings_numbering_read | How each numbered document type counts, one row each for invoice, quote, credit_note, debit_note and receipt: prefix, last_number (the highest number already used or skipped), next_number, and next_pr | typed |
statement_pdf | Make the PDF of a client's statement of account (the same page statement_prepare's document_path shows), printed on A4 with the business's fonts, brand colours and logo, and kept, so asking again for | typed |
banking.import_statement | Import one bank account's statement as CSV text (CSV today, PDF later) so the forecast starts from the bank's own balance. Owner or admin only. Stores each line and each day's closing balance for the | typed |
image.variation | [paid: $0.04/image] Generate 1-3 variations of a reference image guided by a prompt (FLUX Pro Kontext, context-aware). Pass image_asset_key (an earlier result) or image_url (public https or data:image | typed |
image.convert | [paid: $0.0005] Convert an image to PNG, JPEG or WebP, and optionally bound its size, with the Cloudflare Images service: a PNG, JPEG, WebP, GIF or HEIC goes in and the result is stored in this worksp | typed |
image.cut_background | [paid: $0.02] Remove the background from a photo, returning the subject on transparency (BiRefNet). Returns JSON {images:[{url, asset_key, download_url?, width, height}], price, next} plus a preview; | typed |
image.upscale | [paid: $0.06] Upscale a photo 4x via aura-sr super-resolution. Returns JSON {images:[{url, asset_key, download_url?, width, height}], price, next} plus a preview; images are stored in this workspace, | typed |
image.inpaint | [paid: $0.07] Remove or replace a masked region of a photo (FLUX Fill). White mask pixels = edit region. Returns JSON {images:[{url, asset_key, download_url?, width, height}], price, next} plus a prev | typed |
image.replace_sky | [paid: $0.07] Replace a photo's sky (FLUX Fill). Pass a mask covering the sky (white = sky). Returns JSON {images:[{url, asset_key, download_url?, width, height}], price, next} plus a preview; images | typed |
image.replace_background | [paid: $0.07] Replace a photo's background with a generated scene (FLUX Fill). Pass a mask covering the background (white = background). Returns JSON {images:[{url, asset_key, download_url?, width, he | typed |
image.harmonize | Match a pasted subject's light and colour to its scene: a Reinhard colour transfer in CIELAB moves the subject's mean and spread toward the scene's, weighted by the subject mask, at strength 0..100 (d | typed |
image.add_shadow | Add a product shadow to a cut-out (subject on transparency), cast from its alpha: kind drop, contact or reflection. angle 0..359 is the light direction counterclockwise from 3 o'clock (default 120; th | typed |
image.adjust | Apply 1..10 adjustments to a photo in order, with the editor's own kernels: a one-op stack returns the same pixels as that tool in the editor. ops is a list of {op, params}; each op takes only its own | typed |
image.style_transfer | [paid: $0.04] Apply a style to a photo while preserving the content (FLUX img2img, strength 0.55). Returns JSON {images:[{url, asset_key, download_url?, width, height}], price, next} plus a preview; i | typed |
image.segment_at | [paid: $0.01] Segment the object at pixel (x, y) via SAM 2 and return its mask image. Returns JSON {images:[{url, asset_key, download_url?, width, height}], price, next} plus a preview; images are sto | typed |
image.generate_for_edit | [paid: $0.04] Generate an image from a text prompt (google/nano-banana-2-lite) sized for editing. Returns JSON {images:[{url, asset_key, download_url?, width, height}], price, next} plus a preview; im | typed |
image.describe | Analyze a photo with vision (subjects, defects, OCR text, composition) and return a description. Token-billed at the platform's vision rates. Returns JSON {text, price, next}. Refuses: SIMPLER_MEDIA_I | typed |
image.marketplace_check | Check a product photo against a marketplace's listing-image rules before the seller uploads it: shopee, lazada or tiktok_shop. Free and read-only: the platform's own deterministic check, which stores | typed |
video.export_create | Start rendering a studio project to a file: a video, a GIF, the sound mix alone or one poster still (format). Returns job_id immediately; call video.export with job_id to follow progress and receive a | typed |
studio.list_versions | List a studio project's stored versions, newest first: {version, created_at, label, current}, plus every named version (snapshots) and how many of the 20 names are used. A project keeps its newest 20 | typed |
video.export | Follow one video export to completion and return its download links. Start the export with video.export_create, then pass the job_id it returned (without job_id this follows the project's newest expor | typed |
video.export_delete | Delete a finished video export's files (the mp4 and any SRT) now, before the automatic deletion 30 days after the export finished. Every download link for that job stops working at once; the job recor | typed |
video.export_cancel | Stop a video export that is queued or rendering. The job ends as failed with "Cancelled by user.", anything it charged is refunded, the render stops, and any partial file is deleted. Cancelling a job | typed |
studio.begin_asset_upload | Start uploading a video, audio or image file (up to 2 GB) into a studio project. Returns upload_id and the plan: one PUT for a file up to 64 MB, else fixed 64 MB parts, each a PUT to this server with | typed |
studio.finish_asset_upload | Finish an upload started with studio.begin_asset_upload once every part is PUT: the stored bytes are checked (the moov box is read wherever it sits), counted against the 20 GB quota, and added to the | typed |
studio.import_asset_from_url | Copy a video, audio or image file from a public http(s) link into a studio project's media (up to 2 GB, within the 20 GB quota). Returns {asset_id, media_type, probe}, the same as studio.finish_asset_ | typed |
studio.restore_version | Bring back an earlier version of a studio project: it saves that version as a new version; history is never rewritten, so the version it replaces stays listed and restoring that one undoes this. Retur | typed |
studio.snapshot_version | Name a studio project's version (the current one unless version is given) so it is never deleted by retention; naming a named version renames it. At most 20 named versions per project. Adds no new ver | typed |
studio.remove_snapshot | Remove the name from a studio project's named version, freeing one of its 20 names. The version stays stored; from the next save it follows the normal retention and may be deleted. A version without a | typed |
studio.get_composition | Read the current composition: scenes in order (with derived start times and generation status; length_estimated: true marks a scene sized by an estimate because its video file reported no length), tra | typed |
studio.get_transcript | Read the caption rows in time order with the ids edit_caption, move_caption and cut_transcript_span take. Each row gives id, type (speech, filler, silence or manual), source (transcription or manual), | typed |
studio.add_scene | Add a PLANNED scene (storyboard placeholder) to the primary lane — free; no pixels are generated. The prompt is the scene's recipe. NEVER mention camera equipment (crane, dolly, rig) — describe what t | typed |
studio.add_scene_from_asset | Append an uploaded video or image asset to the main track as a finished scene, or insert it at at_index. Assets longer than 10 minutes become consecutive scenes. A video with no measured length lands | typed |
studio.set_transition | Set a scene's transition (in = how it enters, out = how it leaves). Dissolve creates connection (500-800ms); fade for scene breaks; cut clears the transition. | typed |
studio.delete_elements | Delete several scenes, timeline clips, stickers and captions in one edit: pass 1 to 200 ids in element_ids. All or nothing: an unknown id, a clip on a locked track, or a locked track a scene's cut wou | typed |
studio.shift_clips | Move 1 to 200 timeline clips by the same delta_ms (negative moves earlier), keeping their spacing and their tracks. All or nothing: an unknown clip id, a clip on a locked track, a clip pushed before 0 | typed |
studio.duplicate_clips | Copy 1 to 200 timeline clips so the earliest copy starts at at_ms and the others keep their offsets from it, each copy on its original's track. All or nothing: an unknown clip id, a clip on a locked t | typed |
studio.insert_time | Open length_ms of empty time at at_ms on every lane, so everything at or after at_ms moves later together. The main track receives a placeholder scene there (a pending scene with the prompt "Gap"; fil | typed |
studio.ripple_delete | Delete a scene or timeline clip AND close the time it held. scope "all_tracks" (the default) removes that span of time from every lane, so everything after it moves earlier together and stays in sync; | typed |
studio.roll_edit | Move the cut between two neighbours by delta_ms (positive moves it later): left_id's end and right_id's start move together, and their footage in/out points follow. The pair's total length and every o | typed |
studio.slip_edit | Show a different part of a clip's or scene's footage without moving it: its in and out points move by delta_ms of timeline (positive shows later footage), while its position and length stay. Works on | typed |
studio.slide_edit | Move a video or audio clip by delta_ms between its neighbours on its track: the clip touching its start gets longer or shorter at its end, the clip touching its end at its start, so the three-clip spa | typed |
studio.move_caption | Move ONE whole caption row along the timeline by delta_ms (negative moves it earlier): its start, its end and every word timing move together, so the words keep their spacing. Pick the row by caption_ | typed |
studio.cut_transcript_span | Cut the words of a transcript span out of the whole video, the way deleting text in a transcript editor does. The span runs from from_caption_id to to_caption_id (row ids from get_transcript) and take | typed |
studio.add_track | Add an empty track of a role (video-broll, text, audio-music or audio-voice), up to 16 tracks in the project. The new track lands on top of its role: a video-broll or text track draws over the ones be | typed |
studio.remove_track | Remove one track by track_id. A track that still holds clips is refused unless delete_clips is true, which removes its clips with it. Refuses, naming the fix: an unknown track_id, a locked track, a tr | typed |
studio.move_track | Move a track to position within its own role. Position 0 is the lowest: its pictures draw first, so every later video-broll or text track draws over it. Tracks of other roles keep their order; text al | typed |
studio.rename_track | Give a track a display name up to 40 characters, or pass an empty name to go back to the role's label. Names are for people and never address a track: tools take track_id. Locked tracks may be renamed | typed |
studio.set_track_muted | Mute or unmute a whole track. A muted audio track plays nothing and a muted voice track stops ducking the music; a muted video-broll track keeps its pictures and drops its clips' own sound. The previe | typed |
studio.move_clips_to_track | Move 1 to 200 timeline clips onto another track of the same kind (a b-roll clip to a video-broll track, a title to a text track, music to an audio-music track, a voice clip to an audio-voice track), k | typed |
studio.place_product_card | Place a product card: a price_tag text clip showing a stock item's name and price, built from values you already hold. studio.insert_product_card reads them from the stock record for you; use this op | typed |
studio.update_scene | Update a scene's prompt or duration. EDIT-INVALIDATES-ASSET: changing the prompt of a generated scene resets it to pending and drops its footage (a stale render cannot survive a prompt edit) — say so | typed |
studio.generate_scene | [$0.10/sec at provider cost] Generate video for a scene from its prompt (text-to-video). Pass scene_id to fill a planned scene, or prompt to create-and-generate in one step. NEVER mention camera equip | typed |
studio.generate_music | [$0.05/track at provider cost] Generate a background music track from a mood/style description. Returns an audio asset id — place it with add_audio_to_timeline. | typed |
studio.generate_voiceover | Generate narration audio from a script. voice_tier is the REAL choice the user makes: 'standard' ($0.015/1K chars at provider cost) vs 'premium' ($0.15/1K chars at provider cost) — quote both prices w | typed |
studio.add_clip_to_timeline | Place an existing video/image asset on a b-roll track at a position: the first b-roll track, or the one track_id names (a later b-roll track draws over an earlier one, for picture-in-picture). Overlap | typed |
studio.add_audio_to_timeline | Place an audio asset on a role track: 'audio-music' (background, default volume 0.3 — voice ducks music by role) or 'audio-voice' (narration, volume 1.0). It lands on the role's first track, or on the | typed |
studio.add_text_overlay | Add a text clip to the first text track, or to the one track_id names (a later text track draws over an earlier one). Pick a semantic preset (title/subtitle/lower_third/callout/price_tag) — it carries | typed |
studio.update_text_overlay | Update an existing text clip: content, position, timing. | typed |
studio.add_sticker | Add a sticker/element overlay (creator CTAs, emojis, shapes) at a normalized position with its own time range and animation. | typed |
studio.trim_scene | Trim a generated scene's footage: cut milliseconds off its start and/or end. With ripple_secondary "shift" (the default) the other lanes follow the footage: time the scene loses at its start or end is | typed |
studio.color_grade | Apply color grading to a scene (each channel -100..100; temperature negative = cool, positive = warm). | typed |
studio.adjust_audio_levels | Adjust an audio role's mix: set every clip's volume on every track of that role (or only on the track track_id names) and/or toggle ducking (voice ducks music BY ROLE — no track ids needed). | typed |
studio.update_clip | Move a clip or adjust its volume/mute on any secondary track. | typed |
studio.delete_element | Delete a scene, clip, or sticker by id (captions soft-delete reversibly). Deleting a scene with ripple_secondary "shift" (the default) removes its span of time from every lane, so clips, captions and | typed |
studio.remove_silence | Delete every '[silence]' row from the TRANSCRIPT. This cleans up the caption text only - the footage keeps its full length and the pauses still play. To cut the pauses out of the video for real, use r | typed |
studio.remove_fillers | Hide filler words (um, uh, you know, kind of) from the transcript. REVERSIBLE: rows are soft-deleted, excluded from burn-in and SRT, and restore_fillers brings them back. Read the composition afterwar | typed |
studio.restore_fillers | Un-hide transcript rows that were soft-deleted. Scope is EVERY hidden row, not only filler words - a caption hidden by delete_element comes back too. There is no per-row restore. | typed |
studio.split | Cut a scene or a timeline clip in two at a timeline millisecond. The left half keeps the id; the right half is new and is returned. Both halves must keep at least 100ms of footage or the split refuses | typed |
studio.replace_transcribed | Replace the transcript with fresh rows from your own transcription. Rows the operator hand-edited (source 'manual') SURVIVE - only machine-transcribed rows are replaced, so a re-transcribe never silen | typed |
studio.set_config | Set project output settings: aspect ratio, resolution, frame rate, background colour, caption style. Every field is optional - only what you pass changes. Changing aspect does NOT re-crop existing foo | typed |
studio.reorder_scenes | Move a scene to a different position in the primary lane. Positions are 0-based, so to_index 0 makes it the opening scene. Scene start times are DERIVED from order, so every scene after the move shift | typed |
studio.trim_clip | Trim a timeline clip's start or end edge to an absolute TIMELINE millisecond. The clip keeps its id and its source in/out points move with the edge, so the footage stays in sync. Refuses if the trim w | typed |
studio.duplicate_clip | Copy a timeline clip and place the copy immediately after the original on the same track. Refuses if there is no room after it. Returns the new clip id. | typed |
studio.lock_track | Lock or unlock a track. A locked track refuses every edit - move, trim, split, duplicate, delete - until it is unlocked. Lock a finished voiceover before restructuring the picture so the timing cannot | typed |
studio.edit_caption | Edit ONE transcript row: its text, its start, its end, or any combination. Times are timeline milliseconds. Editing the TEXT marks the row hand-edited, so a later replace_transcribed will not overwrit | typed |
studio.update_sticker | Move, resize, rotate, fade or re-time a sticker overlay. Only the fields you pass change. Positions are normalized 0-1 of the frame. | typed |
studio.cut_range | Cut a span of TIME out of the whole video. Everything after it moves earlier by the same amount, on every lane at once - scenes, clips, captions and stickers stay in sync. A scene or voice clip the cu | typed |
studio.remove_dead_air | Cut every silent pause the transcript found OUT OF THE FOOTAGE, keeping a little breathing room at each one. This is the real edit, not a transcript cleanup: the video gets shorter. Needs a transcript | typed |
studio.transcribe | [$0.0043/min at provider cost] Transcribe an audio or video asset into word-timed captions. REPLACES every previously transcribed caption on this project; captions you wrote by hand survive. Speaker l | typed |
studio.reframe_scene | Re-frame one scene for a different aspect ratio. method 'analytic' re-centers and scales the EXISTING footage on a focus point (cheap, no new pixels, needs the source dimensions); method 'generative' | typed |
studio.style_transfer | [$0.04/sec at provider cost] Restyle a scene's footage, keeping its motion. style must be one of the presets (anime, comic, watercolor, oil_painting, sketch, cinematic, vintage, neon). A free-text sty | typed |
studio.add_sound | [$0.001/sec at provider cost] Generate sound effects and ambience FOR a scene from its own footage (foley). Different from generate_music: this is the sound the shot itself would make. | typed |
studio.enhance_audio | Clean up an audio clip on the timeline: noise removal, voice shaping, loudness normalization. FREE (platform compute, no provider). Mints an enhanced asset beside the original - the original is never | typed |
studio.apply_template | Append a stored choreography - its scenes (as PENDING prompts, nothing generated yet) plus its text timing - onto this composition. FREE. Templates: tpl_product_showcase (Perfect for product demos and | typed |
studio.set_ducking | Configure the voice-over-music ducking mix intent (by role; the renderer honors it). | typed |
studio.analyze_scene | Look at a generated scene's actual frames (vision) and describe subject, lighting, composition, mood. Make editing decisions based on what you SEE, not assumptions. Refuses with SIMPLER_STUDIO_VISION_ | typed |
studio.request_regeneration | Flag a generated scene that does not match intent: record WHY and an improved prompt. This stages the improved prompt on the scene (regeneration is a separate paid, user-approved step — it never silen | typed |
studio.apply_ops | Apply several edits atomically against base_version; any refusal applies nothing and names the failing op. Small models: prefer the single-purpose verbs. Each op is {op, args}; the ops and their args | typed |
studio.suggest_social_clips | Find the best short-form moments in a long studio video and return them as ranges with a title, a hook line, a one-sentence rationale and measured evidence (captioned words, words per second, whether | typed |
studio.create_social_clip | Make one short as a NEW studio project from a range of an existing project: the finished scenes in the range are trimmed copies (no footage is generated or billed again), the captions move with them a | typed |
studio.insert_product_card | Put a stock item's name and selling price on the video as a product card: a price_tag text clip on the first text track (or the one track_id names), from start_ms for duration_ms. It reads the stock r | typed |
platform.request_capability | File a missing-capability report when no available tool can accomplish your task. The platform operator reviews these to decide what gets built next. Free; capped at 10 reports per tenant per day. Ref | typed |
Badge
Paste into your README. It updates on every verification.
[](https://app.agent-xm.com/a/asia-simpler-simpler-asia)
Was this agent useful?
Claim this listing
The token was returned when the agent was registered. No token? Prove the domain or repository instead.