MCP App Store
Productivity
DataAssist-IO icon

DataAssist-IO

by Absolute TechTeam

Overview

DataAssist lets organizations expose uploaded CSVs and connected databases as MCP tools so users can discover tables, inspect metadata, preview rows, and run validated SQL SELECT queries from ChatGPT. Tool calls are scoped to the authenticated organization and user, use only tables the organization has exposed, and support self-serve analysis across CSV, SFTP, MySQL, PostgreSQL, and S3-backed data sources.

Tools

describe_table

ChatGPT
Return the schema of one table — columns, types, sample values, row count. Use this when you have a known table name but don't know its columns yet. For business-level descriptions (what each column means) prefer get_table_metadata; this tool returns the raw schema view. Errors (returned as {"error": "..."}): - Unknown table → call list_tables first to discover valid names. - Disabled / errored data source → tell the user; admin must re-enable the source in DataAssist-IO Data Sources. Example: describe_table("orders") → {"name": "orders", "row_count": 1234, "columns": [{"name": "id", "type": "bigint", ...}, ...]}

describe_table

ChatGPT
Return the schema of one table — columns, types, sample values, row count. Use this when you have a known table name but don't know its columns yet. For business-level descriptions (what each column means) prefer get_table_metadata; this tool returns the raw schema view. Errors (returned as {"error": "..."}): - Unknown table → call list_tables first to discover valid names. - Disabled / errored data source → tell the user; admin must re-enable the source in DataAssist-IO Data Sources. Example: describe_table("orders") → {"name": "orders", "row_count": 1234, "columns": [{"name": "id", "type": "bigint", ...}, ...]}

get_sample_data

ChatGPT
Return the first N rows of a table as JSON (clamped: 1 ≤ N ≤ 100). Useful for sanity-checking what real data looks like — what's an amount column actually denominated in, what date format does the org use, are there nulls, etc. Cheaper than query_data for "show me a few rows" because you don't have to write a SELECT. Errors (returned as {"error": "..."}): - Unknown / disabled table → call list_tables first. - Pending-column references / forbidden keywords → these can't happen here (we run SELECT *), but the same envelope shape is used so callers can handle errors uniformly. Example: get_sample_data("orders", limit=5) → [{"id": 1, "amount": 49.99, "ordered_at": "2026-05-20", ...}, ...]

get_sample_data

ChatGPT
Return the first N rows of a table as JSON (clamped: 1 ≤ N ≤ 100). Useful for sanity-checking what real data looks like — what's an amount column actually denominated in, what date format does the org use, are there nulls, etc. Cheaper than query_data for "show me a few rows" because you don't have to write a SELECT. Errors (returned as {"error": "..."}): - Unknown / disabled table → call list_tables first. - Pending-column references / forbidden keywords → these can't happen here (we run SELECT *), but the same envelope shape is used so callers can handle errors uniformly. Example: get_sample_data("orders", limit=5) → [{"id": 1, "amount": 49.99, "ordered_at": "2026-05-20", ...}, ...]

get_table_metadata

ChatGPT
Return the BUSINESS-LEVEL description of a table's columns. Each column carries human-curated metadata: label (display name), description (what it means), category (grouping), plus the inferred type and a few sample values. Use this before writing queries so you map the user's natural-language question to the right columns. Prefer this over describe_table for any user-facing answer — the metadata is what the org's admin chose to expose. describe_table is the raw schema fallback when this returns sparse info. Errors (returned as {"error": "..."}): - Unknown table → call list_tables to discover valid names. - Disabled / errored source → tell the user the admin needs to fix it. Example: get_table_metadata("orders") → {"name": "orders", "description": "All customer purchase events", "columns": [ {"name": "amount", "label": "Order total (USD)", "description": "Pre-tax order amount in USD", "category": "money", "inferred_type": "decimal"}, ...]}

get_table_metadata

ChatGPT
Return the BUSINESS-LEVEL description of a table's columns. Each column carries human-curated metadata: label (display name), description (what it means), category (grouping), plus the inferred type and a few sample values. Use this before writing queries so you map the user's natural-language question to the right columns. Prefer this over describe_table for any user-facing answer — the metadata is what the org's admin chose to expose. describe_table is the raw schema fallback when this returns sparse info. Errors (returned as {"error": "..."}): - Unknown table → call list_tables to discover valid names. - Disabled / errored source → tell the user the admin needs to fix it. Example: get_table_metadata("orders") → {"name": "orders", "description": "All customer purchase events", "columns": [ {"name": "amount", "label": "Order total (USD)", "description": "Pre-tax order amount in USD", "category": "money", "inferred_type": "decimal"}, ...]}

list_tables

ChatGPT
List all data tables the connected organization has exposed for MCP. Returns a JSON array; each entry has at least table_name, row_count, description. Call this FIRST when you don't know what data exists — every subsequent tool needs a table name from this list. Empty-state: returns an object of the form {"tables": [], "message": "no tables exposed — direct the user to..."}. Don't invent table names; tell the user how to add data via the DataAssist-IO Data Sources page. Example follow-up: 1. discover list_tables() → [{"table_name": "orders", "row_count": 1234, ...}, ...] 2. understand get_table_metadata("orders") 3. answer query_data("SELECT product, SUM(amount) FROM orders GROUP BY product")

list_tables

ChatGPT
List all data tables the connected organization has exposed for MCP. Returns a JSON array; each entry has at least table_name, row_count, description. Call this FIRST when you don't know what data exists — every subsequent tool needs a table name from this list. Empty-state: returns an object of the form {"tables": [], "message": "no tables exposed — direct the user to..."}. Don't invent table names; tell the user how to add data via the DataAssist-IO Data Sources page. Example follow-up: 1. discover list_tables() → [{"table_name": "orders", "row_count": 1234, ...}, ...] 2. understand get_table_metadata("orders") 3. answer query_data("SELECT product, SUM(amount) FROM orders GROUP BY product")

query_data

ChatGPT
Run a validated read-only SELECT against the org's data. Strictly read-only: only a single SELECT is allowed. DDL, DML (INSERT/UPDATE/DELETE), GRANT/REVOKE, MySQL HANDLER, system schemas (information_schema, mysql, performance_schema), and DataAssist-IO's own internal tables (orgs, users, audit_logs, etc.) are all rejected by the validator. Best practice — answer with SQL, not row dumps: Prefer SELECT region, SUM(amount) AS total FROM orders GROUP BY region ORDER BY total DESC LIMIT 10 over SELECT * FROM orders followed by client-side aggregation. Aggregations push the work to the DB, keep results small, and produce answers a human can read directly. Limits: `limit` (default 1000, max 10000) is applied automatically — you do NOT need to add a trailing `LIMIT` yourself, though one inside the query is fine. Queries are killed after 30 seconds. Errors (returned as {"error": "..."}): "Table 'X' is not in the allowed tables list" → call `list_tables` to see what's actually exposed. "Column 'X' is not in the allowed columns ... It may be pending admin review" → that column was added to the source but the admin hasn't approved it. Use a column from get_table_metadata. "Forbidden keyword" → you tried DML/DDL or a banned construct; rewrite as a pure SELECT. "Query exceeded timeout of 30 seconds" → narrow the WHERE clause, add an index-friendly filter, or aggregate harder. Examples: Aggregate query_data("SELECT status, COUNT(*) FROM orders GROUP BY status") Filter + sort query_data("SELECT id, amount FROM orders " "WHERE amount > 100 ORDER BY amount DESC LIMIT 50") Join query_data("SELECT c.name, SUM(o.amount) AS spend " "FROM customers c JOIN orders o ON o.customer_id = c.id " "GROUP BY c.name ORDER BY spend DESC LIMIT 10")

query_data

ChatGPT
Run a validated read-only SELECT against the org's data. Strictly read-only: only a single SELECT is allowed. DDL, DML (INSERT/UPDATE/DELETE), GRANT/REVOKE, MySQL HANDLER, system schemas (information_schema, mysql, performance_schema), and DataAssist-IO's own internal tables (orgs, users, audit_logs, etc.) are all rejected by the validator. Best practice — answer with SQL, not row dumps: Prefer SELECT region, SUM(amount) AS total FROM orders GROUP BY region ORDER BY total DESC LIMIT 10 over SELECT * FROM orders followed by client-side aggregation. Aggregations push the work to the DB, keep results small, and produce answers a human can read directly. Limits: `limit` (default 1000, max 10000) is applied automatically — you do NOT need to add a trailing `LIMIT` yourself, though one inside the query is fine. Queries are killed after 30 seconds. Errors (returned as {"error": "..."}): "Table 'X' is not in the allowed tables list" → call `list_tables` to see what's actually exposed. "Column 'X' is not in the allowed columns ... It may be pending admin review" → that column was added to the source but the admin hasn't approved it. Use a column from get_table_metadata. "Forbidden keyword" → you tried DML/DDL or a banned construct; rewrite as a pure SELECT. "Query exceeded timeout of 30 seconds" → narrow the WHERE clause, add an index-friendly filter, or aggregate harder. Examples: Aggregate query_data("SELECT status, COUNT(*) FROM orders GROUP BY status") Filter + sort query_data("SELECT id, amount FROM orders " "WHERE amount > 100 ORDER BY amount DESC LIMIT 50") Join query_data("SELECT c.name, SUM(o.amount) AS spend " "FROM customers c JOIN orders o ON o.customer_id = c.id " "GROUP BY c.name ORDER BY spend DESC LIMIT 10")

Capabilities

Writes

App Stats

10

Tools

ChatGPT

Platforms

Works with

ChatGPT

Data refreshed daily