{"ok":true,"site":{"host":"enclave-bay.vercel.app","url":"https://enclave-bay.vercel.app/app","type":"live","desc":"A browser-only analysis workbench. Your CSV never leaves the tab; an AI agent drives the analysis through sixteen WebMCP tools without ever seeing a row.","tools":[{"name":"get_schema","kind":"answer","impl":"imperative","description":"Describe the loaded dataset: every column with its SQL type, and the total row count. Call this first. The queryable table is always named `data`.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"profile_column","kind":"act","impl":"imperative","description":"Profile one column: null count, distinct count, min, max, and the ten most frequent values. Use this to understand a column before charting it.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"column":{"type":"string","description":"Column name, exactly as get_schema reports it"}},"required":["column"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"sample_rows","kind":"answer","impl":"imperative","description":"Return a handful of raw rows so you can see the shape of the data. Capped at 20 rows. Prefer aggregate queries via run_sql — this tool exists only for orientation.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"limit":{"type":"number","description":"How many rows, 1-20"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"run_sql","kind":"answer","impl":"imperative","description":"Run a read-only DuckDB SQL SELECT against the table `data` and return the result. This is your main instrument. DuckDB dialect: bucket months with strftime(order_date, '%Y-%m'), and compare dates as ISO strings. Group by several dimensions at once rather than issuing one query per dimension. Results are capped at 50 rows and 4 KB, so aggregate rather than selecting raw rows. `data` already reflects any global filter.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"sql":{"type":"string","description":"A SELECT statement referencing the table `data`"}},"required":["sql"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"add_kpi","kind":"act","impl":"imperative","description":"Add a single-number card to the board. The SQL must return one row whose first column is the number to display.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"title":{"type":"string"},"sql":{"type":"string","description":"SELECT returning one row, one numeric column"},"format":{"type":"string","enum":["number","currency","percent"],"description":"Defaults to number"},"span":{"type":"number","description":"Card width in grid columns, 1 (narrow), 2, or 3 (full width). Defaults to 1."}},"required":["title","sql"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"add_chart","kind":"act","impl":"imperative","description":"Add a chart to the board. The SQL result supplies the data; x and y name columns in that result. Use series to split into multiple lines or bars.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"title":{"type":"string"},"chartType":{"type":"string","enum":["bar","line","area","scatter","pie"]},"sql":{"type":"string"},"x":{"type":"string","description":"Column in the result used for the category or x axis"},"y":{"type":"string","description":"Column in the result used for the value or y axis"},"series":{"type":"string","description":"Optional column to split the data by"},"span":{"type":"number","description":"Card width in grid columns, 1 (narrow), 2, or 3 (full width). Defaults to 1."}},"required":["title","chartType","sql","x","y"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"add_table","kind":"act","impl":"imperative","description":"Add a table card showing the result of a query. Keep the row count small.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"title":{"type":"string"},"sql":{"type":"string"},"span":{"type":"number","description":"Card width in grid columns, 1 (narrow), 2, or 3 (full width). Defaults to 1."}},"required":["title","sql"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"add_note","kind":"act","impl":"imperative","description":"Add a Markdown note to the board. Use this to record what you found — the finding is the point of the analysis, not the chart.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"title":{"type":"string"},"markdown":{"type":"string"},"span":{"type":"number","description":"Card width in grid columns, 1 (narrow), 2, or 3 (full width). Defaults to 1."}},"required":["markdown"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"update_card","kind":"act","impl":"imperative","description":"Change the title, query, or chart configuration of a card already on the board.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"sql":{"type":"string"},"chartType":{"type":"string","enum":["bar","line","area","scatter","pie"]},"x":{"type":"string"},"y":{"type":"string"},"markdown":{"type":"string"}},"required":["id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"remove_card","kind":"act","impl":"imperative","description":"Delete a card from the board by its id. Use read_dashboard first if you do not know the id. The deletion can be reversed with the undo tool.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"reorder_cards","kind":"act","impl":"imperative","description":"Set the order of cards on the board. Pass every card id in the order you want. Ids you omit are appended at the end.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"}}},"required":["ids"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"resize_card","kind":"act","impl":"imperative","description":"Set how many of the three grid columns a card spans.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"id":{"type":"string"},"span":{"type":"number","description":"Card width in grid columns, 1 (narrow), 2, or 3 (full width). Defaults to 1."}},"required":["id","span"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"highlight_points","kind":"act","impl":"imperative","description":"Emphasise specific x-axis values on a chart — the months that dipped, the outlying regions. Highlighted points render in the accent colour while the rest fade back.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"id":{"type":"string"},"values":{"type":"array","items":{"type":"string"},"description":"x values to emphasise"}},"required":["id","values"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"read_dashboard","kind":"answer","impl":"imperative","description":"Read what is currently on the board: every card with its id, kind, title and query, plus the active global filter. Call this before modifying cards you did not create.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"set_global_filter","kind":"act","impl":"imperative","description":"Apply one SQL WHERE clause across the entire board at once. Every card re-runs its query against the filtered data. Call with no arguments to clear the filter. Write the clause without the WHERE keyword, for example: region = 'EMEA' AND order_date >= '2025-01-01'.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"where":{"type":"string","description":"A SQL boolean expression, without the WHERE keyword. Omit to clear."}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"undo","kind":"act","impl":"imperative","description":"Revert the last change to the board — a card added, edited, removed, reordered, or a filter applied. Never touches the loaded dataset.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"search_orders","kind":"answer","impl":"imperative","description":"Search Northwind order lines by region, status, product or date range. Returns the matching orders, newest first. Use this to see the individual orders behind a trend you found in the analytics board.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"region":{"type":"string","description":"EMEA, AMER, APAC or LATAM"},"status":{"type":"string","enum":["fulfilled","refunded","cancelled"]},"product_id":{"type":"string"},"from":{"type":"string","description":"Inclusive start date, YYYY-MM-DD"},"to":{"type":"string","description":"Exclusive end date, YYYY-MM-DD"},"limit":{"type":"number","description":"How many to return, up to 50"}},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"get_product","kind":"answer","impl":"imperative","description":"Look one product up by its product_id or by part of its name, and return its category, supplier, price, current stock and reorder level.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{"query":{"type":"string","description":"A product_id, or part of the name"}},"required":["query"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"list_low_stock","kind":"answer","impl":"imperative","description":"List every product at or below its reorder level, worst first. This is where a supply problem shows up as a fact rather than an inference.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"list_restock_orders","kind":"answer","impl":"imperative","description":"List the restock orders raised in this session, newest first.","annotations":{"readOnlyHint":true},"inputSchema":{"type":"object","properties":{},"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"create_restock_order","kind":"transact","impl":"imperative","description":"Raise a restock order for a product. This changes the business, so it is proposed to the operator and only goes through once they approve it on screen. Explain your reasoning in the reason field — they read it before deciding.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"product_id":{"type":"string"},"quantity":{"type":"number","description":"Units to order, 1-10000"},"reason":{"type":"string","description":"Why this restock is needed"}},"required":["product_id","quantity","reason"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"},{"name":"set_product_price","kind":"answer","impl":"imperative","description":"Change a product's price. Proposed to the operator and applied only once they approve. Say why in the reason field.","annotations":{"readOnlyHint":false},"inputSchema":{"type":"object","properties":{"product_id":{"type":"string"},"price":{"type":"number"},"reason":{"type":"string"}},"required":["product_id","price","reason"],"additionalProperties":false},"hasHandler":true,"hasExecute":true,"__source":"spec","executable":true,"handlerField":"execute","page":"/app"}],"category":"Productivity & Business","favicon":"/favicons/enclave-bay.vercel.app.svg","apiSurface":"spec","toolCount":22}}