@chaprola/mcp-server 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +11 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -582,23 +582,26 @@ server.tool("chaprola_download", "Get a presigned S3 URL to download any file yo
582
582
  return textResult(res);
583
583
  }));
584
584
  // --- Query ---
585
- server.tool("chaprola_query", "SQL-free data query with WHERE, SELECT, aggregation, ORDER BY, JOIN, pivot, and Mercury scoring", {
585
+ server.tool("chaprola_query", "SQL-free data query with WHERE, SELECT, aggregation, ORDER BY, JOIN, pivot, DISTINCT, transforms, and Mercury scoring", {
586
586
  project: z.string().describe("Project name"),
587
587
  file: z.string().describe("Data file to query"),
588
- where: z.string().optional().describe("JSON object of filter conditions, e.g. {\"field\": \"status\", \"op\": \"eq\", \"value\": \"active\"}. Ops: eq, ne, gt, ge, lt, le, between, contains, starts_with, in, not_in. For in/not_in, value must be a JSON array of strings, e.g. {\"field\": \"status\", \"op\": \"in\", \"value\": [\"active\", \"pending\"]}"),
588
+ where: z.string().optional().describe("JSON array of filter conditions, e.g. [{\"field\": \"status\", \"op\": \"eq\", \"value\": \"active\"}]. Ops: eq, ne, gt, ge, lt, le, between, contains, starts_with, in, not_in, date_within, date_before, date_after. For in/not_in, value is a JSON array. For date_within, value is relative like \"30d\", \"6h\", \"15m\"."),
589
589
  select: z.array(z.string()).optional().describe("Fields to include in output"),
590
590
  aggregate: z.string().optional().describe("JSON array of aggregation specs, e.g. [{\"field\": \"amount\", \"func\": \"sum\"}]. Funcs: count, sum, avg, min, max, stddev"),
591
- order_by: z.string().optional().describe("JSON array of sort specs, e.g. [{\"field\": \"name\", \"dir\": \"asc\"}]"),
591
+ order_by: z.string().optional().describe("JSON sort spec — single object or array for multi-column sort, e.g. [{\"field\": \"dept\", \"dir\": \"asc\"}, {\"field\": \"salary\", \"dir\": \"desc\"}]"),
592
+ distinct: z.boolean().optional().describe("Return only unique rows based on selected fields. Cannot combine with aggregate or pivot."),
593
+ transform: z.string().optional().describe("JSON array of transforms applied before WHERE, e.g. [{\"field\": \"email\", \"func\": \"lower\"}]. Funcs: upper, lower, trim, substring (start, length), replace (old, new), length, date_trunc (unit: year/month/day/hour), date_extract (part: year/month/day/hour/minute/weekday)"),
592
594
  limit: z.number().optional().describe("Max results to return"),
593
595
  offset: z.number().optional().describe("Skip this many results"),
594
596
  join: z.string().optional().describe("JSON object of join config, e.g. {\"file\": \"other\", \"on\": \"id\", \"type\": \"inner\"}"),
595
597
  pivot: z.string().optional().describe("JSON object of pivot config, e.g. {\"row\": \"category\", \"column\": \"month\", \"values\": \"sales\"}"),
596
598
  mercury: z.string().optional().describe("JSON object of mercury scoring config, e.g. {\"fields\": [{\"field\": \"score\", \"target\": 100, \"weight\": 1.0}]}"),
597
599
  userid: z.string().optional().describe("Project owner's username. Required when accessing a shared project where you are a writer. Defaults to the authenticated user."),
598
- }, async ({ project, file, where: whereStr, select, aggregate: aggregateStr, order_by: orderByStr, limit, offset, join: joinStr, pivot: pivotStr, mercury: mercuryStr, userid }) => withBaaCheck(async () => {
600
+ }, async ({ project, file, where: whereStr, select, aggregate: aggregateStr, order_by: orderByStr, distinct, transform: transformStr, limit, offset, join: joinStr, pivot: pivotStr, mercury: mercuryStr, userid }) => withBaaCheck(async () => {
599
601
  const where = typeof whereStr === 'string' ? JSON.parse(whereStr) : whereStr;
600
602
  const aggregate = typeof aggregateStr === 'string' ? JSON.parse(aggregateStr) : aggregateStr;
601
603
  const order_by = typeof orderByStr === 'string' ? JSON.parse(orderByStr) : orderByStr;
604
+ const transform = transformStr ? (typeof transformStr === 'string' ? JSON.parse(transformStr) : transformStr) : undefined;
602
605
  const join = typeof joinStr === 'string' ? JSON.parse(joinStr) : joinStr;
603
606
  const pivot = typeof pivotStr === 'string' ? JSON.parse(pivotStr) : pivotStr;
604
607
  const mercury = typeof mercuryStr === 'string' ? JSON.parse(mercuryStr) : mercuryStr;
@@ -612,6 +615,10 @@ server.tool("chaprola_query", "SQL-free data query with WHERE, SELECT, aggregati
612
615
  body.aggregate = aggregate;
613
616
  if (order_by)
614
617
  body.order_by = order_by;
618
+ if (distinct)
619
+ body.distinct = distinct;
620
+ if (transform)
621
+ body.transform = transform;
615
622
  if (limit !== undefined)
616
623
  body.limit = limit;
617
624
  if (offset !== undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chaprola/mcp-server",
3
- "version": "1.10.0",
3
+ "version": "1.11.0",
4
4
  "description": "MCP server for Chaprola — agent-first data platform. Gives AI agents tools for structured data storage, record CRUD, querying, schema inspection, documentation lookup, web search, URL fetching, scheduled jobs, scoped site keys, and execution via plain HTTP.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",