Clean, filter and reshape JSON rows in one call: 26 transforms, 25 filters, sort, dedupe, limit.
One address for any MCP client. No sign-in needed on this server.
1 read1 other
Grouped by tool name. At most: creates or changes data: records, files, settings.
Odel charges nothing per call. The publisher may charge for its own service.
Clean, filter and reshape messy JSON rows in a single tool call. Hand it a list of rows from a scraper, an API or a spreadsheet, tell it how to reshape them and which rows to keep, and it hands back clean rows plus an exact account of what was removed and why.
Built for AI agents. No install, no API key, no signup. Connect by URL and call it.
https://dataset-filter-transform.nerolabs.workers.dev/mcp
Free to use while in early access.
One call runs a full pipeline, in this order:
Transforms run before filters, so you can create a field and filter on it in the same call.
It is honest about what it could not do. If a price like "not a price" cannot become a number, the row is not silently guessed at: the summary reports cast:price: 1.
| Tool | What it does |
|---|---|
list_capabilities | Lists every transform operation and filter operator, the pipeline order and the row limit. Processes no data. |
process_rows | Runs the pipeline on the rows you pass and returns the kept rows plus a summary. |
Claude Code
claude mcp add --transport http dataset-filter-transform https://dataset-filter-transform.nerolabs.workers.dev/mcp
Claude Desktop / claude.ai: Settings, Connectors, Add custom connector, paste the URL above.
Cursor, Windsurf, VS Code and other MCP clients
{
"mcpServers": {
"dataset-filter-transform": {
"url": "https://dataset-filter-transform.nerolabs.workers.dev/mcp"
}
}
}
Five messy lead rows go in:
{
"rows": [
{"company": " Acme Ltd ", "e_mail": "Sales@ACME.co.uk", "price": "$1,234.50", "qty": "3", "country": "uk"},
{"company": "Beta Systems", "e_mail": "hi@beta.io", "price": "49 USD", "qty": "1", "country": "UK"},
{"company": "Gamma GmbH", "e_mail": "info@gamma.de", "price": "€900", "qty": "2", "country": "DE"},
{"company": "Acme Ltd", "e_mail": "sales@acme.co.uk", "price": "$1,234.50", "qty": "3", "country": "UK"},
{"company": "Delta Co", "e_mail": "", "price": "not a price", "qty": "5", "country": "UK"}
],
"transforms": [
{"op": "trim", "field": "company"},
{"op": "rename", "from": "e_mail", "to": "email"},
{"op": "lowercase", "field": "email"},
{"op": "cast", "field": "price", "to": "number"},
{"op": "cast", "field": "qty", "to": "number"},
{"op": "compute", "field": "orderValue", "expression": "price * qty", "round": 2},
{"op": "extractDomain", "field": "email", "into": "domain"}
],
"filters": [
{"field": "country", "operator": "equals", "value": "UK"},
{"field": "orderValue", "operator": "greaterThan", "value": 100}
],
"sortBy": [{"field": "orderValue", "direction": "desc"}],
"distinctBy": ["domain"]
}
One clean row comes out, with a summary of exactly why the other four went:
{
"rows": [
{"company": "Acme Ltd", "price": 1234.5, "qty": 3, "country": "uk", "email": "sales@acme.co.uk", "orderValue": 3703.5, "domain": "acme.co.uk"}
],
"summary": {
"inputRowCount": 5,
"keptRowCount": 1,
"excludedByFilter": 3,
"duplicatesRemoved": 1,
"transformIssues": {"cast:price": 1, "compute:orderValue": 1, "extractDomain:email": 1}
}
}
Text matching is case-insensitive by default, and values like "$1,234.50", "49 USD" and "12%" are read as numbers unless you turn that off.
Up to 500 rows per call. For bigger lists, split them across several calls. Anything larger returns a clear message rather than failing silently.
Your rows are processed in memory and never stored. To see which tools get used, each call records the tool name, row counts, whether it succeeded, the client name your app reports, the country and a one-way hashed caller ID. Your data, your arguments and your IP address are never kept in that log.
The same engine runs on the Apify Store as Dataset Filter & Transform, which also reads Apify datasets, CSV and Excel files and Google Sheets, and exports CSV or Excel.
Built by Nero Labs.