@baasix/mcp 0.1.4 → 0.1.5

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/baasix/index.js +92 -34
  2. package/package.json +1 -1
package/baasix/index.js CHANGED
@@ -505,6 +505,8 @@ EXAMPLE M2M with custom junction table:
505
505
  name: "baasix_list_items",
506
506
  description: `Query items from a collection with powerful filtering, sorting, pagination, relations, and aggregation.
507
507
 
508
+ NOTE: For analytics, summaries, totals, sums, averages, counts, min/max, grouped reports, or dashboards → use baasix_generate_report instead. Use this tool (list_items) for fetching actual row data.
509
+
508
510
  FILTER OPERATORS (50+):
509
511
  - Comparison: eq, neq, gt, gte, lt, lte
510
512
  - String: contains, icontains, startswith, endswith, like, ilike, regex
@@ -745,29 +747,50 @@ FILTER EXAMPLES:
745
747
  // Reports and Analytics Tools
746
748
  {
747
749
  name: "baasix_generate_report",
748
- description: "Generate reports with grouping and aggregation for a collection",
750
+ description: `Run an aggregate/analytics query on a database table. Use this for summaries, totals, averages, counts, grouping, and any analytics query. Prefer this over baasix_list_items when the user asks for sums, counts, averages, min/max, grouped data, dashboards, or reports.
751
+
752
+ EXAMPLES:
753
+ 1. Sum of quantity: aggregate: {"total": {"function": "sum", "field": "quantity"}}
754
+ 2. Count by status: groupBy: ["status"], aggregate: {"count": {"function": "count", "field": "*"}}
755
+ 3. Average price for active products: filter: {"status": {"eq": "active"}}, aggregate: {"avg": {"function": "avg", "field": "price"}}
756
+ 4. Min/max: aggregate: {"min": {"function": "min", "field": "price"}, "max": {"function": "max", "field": "price"}}`,
749
757
  inputSchema: {
750
758
  type: "object",
751
759
  properties: {
752
760
  collection: {
753
761
  type: "string",
754
- description: "Collection name",
762
+ description: "Table/collection name to report on",
755
763
  },
756
- groupBy: {
757
- type: "string",
758
- description: "Field to group by",
764
+ fields: {
765
+ type: "array",
766
+ items: { type: "string" },
767
+ description: 'Columns to return. Default ["*"]. Use dot notation for relations: ["category.name"].',
759
768
  },
760
769
  filter: {
761
770
  type: "object",
762
- description: "Filter criteria",
771
+ description: "Row filter applied before aggregation. Same operators as baasix_list_items.",
772
+ },
773
+ sort: {
774
+ type: "array",
775
+ items: { type: "string" },
776
+ description: 'Sort results. Format: ["field:direction"]. E.g. ["count:desc", "name:asc"].',
777
+ },
778
+ limit: {
779
+ type: "number",
780
+ description: "Max rows returned. Default -1 (all). Set to limit grouped results.",
763
781
  },
764
- dateRange: {
782
+ page: {
783
+ type: "number",
784
+ description: "Page number for pagination (works with limit).",
785
+ },
786
+ aggregate: {
765
787
  type: "object",
766
- properties: {
767
- start: { type: "string" },
768
- end: { type: "string" },
769
- },
770
- description: "Date range filter",
788
+ description: 'Aggregation definitions. Each key is the result alias. Value: {function: "count|sum|avg|min|max", field: "columnName"}. E.g. {"total": {"function": "sum", "field": "quantity"}}',
789
+ },
790
+ groupBy: {
791
+ type: "array",
792
+ items: { type: "string" },
793
+ description: "Columns to group by. Required when using aggregate with breakdowns.",
771
794
  },
772
795
  },
773
796
  required: ["collection"],
@@ -775,20 +798,43 @@ FILTER EXAMPLES:
775
798
  },
776
799
  {
777
800
  name: "baasix_collection_stats",
778
- description: "Get collection statistics and analytics",
801
+ description: `Run multiple aggregate queries across different tables in a single call. Each query uses the full report engine (filter, aggregate, groupBy, etc.).
802
+
803
+ Each stats entry requires:
804
+ - name: A unique label for this stat in the results (e.g. "total_orders", "active_users")
805
+ - collection: The table to query
806
+ - query: Full report query object with fields, filter, aggregate, groupBy, sort, limit, page
807
+
808
+ EXAMPLES:
809
+ 1. Get counts: stats: [{"name": "users", "collection": "users", "query": {"aggregate": {"total": {"function": "count", "field": "*"}}}}]
810
+ 2. Multi-table: stats: [{"name": "orders", "collection": "orders", "query": {"aggregate": {"count": {"function": "count", "field": "*"}}}}, {"name": "revenue", "collection": "orders", "query": {"aggregate": {"total": {"function": "sum", "field": "amount"}}}}]`,
779
811
  inputSchema: {
780
812
  type: "object",
781
813
  properties: {
782
- collections: {
814
+ stats: {
783
815
  type: "array",
784
- items: { type: "string" },
785
- description: "Specific collections to get stats for",
786
- },
787
- timeframe: {
788
- type: "string",
789
- description: 'Timeframe for stats (e.g., "24h", "7d", "30d")',
816
+ items: {
817
+ type: "object",
818
+ properties: {
819
+ name: {
820
+ type: "string",
821
+ description: "Unique label for this stat in the results",
822
+ },
823
+ collection: {
824
+ type: "string",
825
+ description: "Table/collection to query",
826
+ },
827
+ query: {
828
+ type: "object",
829
+ description: "Report query: {fields?, filter?, sort?, limit?, page?, aggregate?, groupBy?}",
830
+ },
831
+ },
832
+ required: ["name", "collection", "query"],
833
+ },
834
+ description: "Array of stat queries to run across tables",
790
835
  },
791
836
  },
837
+ required: ["stats"],
792
838
  },
793
839
  },
794
840
 
@@ -2101,13 +2147,26 @@ The realtime config is stored in the schema definition and can include specific
2101
2147
 
2102
2148
  // Reports and Analytics Methods
2103
2149
  async handleGenerateReport(args) {
2104
- const { collection, groupBy, filter, dateRange } = args;
2105
- const params = new URLSearchParams();
2106
- if (groupBy) params.append("groupBy", groupBy);
2107
- if (filter) params.append("filter", JSON.stringify(filter));
2108
- if (dateRange) params.append("dateRange", JSON.stringify(dateRange));
2109
-
2110
- const report = await baasixRequest(`/reports/${collection}?${params}`);
2150
+ const { collection, fields, filter, sort, limit, page, aggregate, groupBy } = args;
2151
+ const body = {};
2152
+ if (fields) body.fields = fields;
2153
+ if (filter) body.filter = filter;
2154
+ if (sort) {
2155
+ // Convert "field:desc" → "-field", "field:asc" → "field" for ItemsService
2156
+ body.sort = sort.map(s => {
2157
+ const [field, dir] = s.split(':');
2158
+ return dir?.toLowerCase() === 'desc' ? `-${field}` : field;
2159
+ });
2160
+ }
2161
+ if (limit !== undefined) body.limit = limit;
2162
+ if (page !== undefined) body.page = page;
2163
+ if (aggregate) body.aggregate = aggregate;
2164
+ if (groupBy) body.groupBy = groupBy;
2165
+
2166
+ const report = await baasixRequest(`/reports/${encodeURIComponent(collection)}`, {
2167
+ method: 'POST',
2168
+ data: body,
2169
+ });
2111
2170
  return {
2112
2171
  content: [
2113
2172
  {
@@ -2119,17 +2178,16 @@ The realtime config is stored in the schema definition and can include specific
2119
2178
  }
2120
2179
 
2121
2180
  async handleGetStats(args) {
2122
- const { collections, timeframe } = args;
2123
- const params = new URLSearchParams();
2124
- if (collections) params.append("collections", JSON.stringify(collections));
2125
- if (timeframe) params.append("timeframe", timeframe);
2126
-
2127
- const stats = await baasixRequest(`/reports/stats?${params}`);
2181
+ const { stats } = args;
2182
+ const result = await baasixRequest(`/reports/stats`, {
2183
+ method: 'POST',
2184
+ data: { stats },
2185
+ });
2128
2186
  return {
2129
2187
  content: [
2130
2188
  {
2131
2189
  type: "text",
2132
- text: JSON.stringify(stats, null, 2),
2190
+ text: JSON.stringify(result, null, 2),
2133
2191
  },
2134
2192
  ],
2135
2193
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baasix/mcp",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Model Context Protocol (MCP) server for Baasix Backend-as-a-Service - provides 40+ tools for schema management, CRUD operations with 50+ filter operators, relationships, permissions, files, workflows, and more",
5
5
  "type": "module",
6
6
  "main": "baasix/index.js",