distil-ai-rms-reporting 1.0.21 → 1.0.23

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.
package/dist/api.js CHANGED
@@ -13,7 +13,7 @@ exports.apiGetSummaryStats = apiGetSummaryStats;
13
13
  exports.apiGetRevenueStats = apiGetRevenueStats;
14
14
  exports.apiGetTimePatternStats = apiGetTimePatternStats;
15
15
  exports.apiGetDemandAnalytics = apiGetDemandAnalytics;
16
- exports.apiGetOpenTableChangeLog = apiGetOpenTableChangeLog;
16
+ exports.apiGetChangeLog = apiGetChangeLog;
17
17
  exports.apiGetAvailabilityAnalytics = apiGetAvailabilityAnalytics;
18
18
  exports.apiGetDemandOutlook = apiGetDemandOutlook;
19
19
  exports.apiGetReviewStats = apiGetReviewStats;
@@ -164,7 +164,7 @@ async function apiGetDemandAnalytics(dimension, flagType, restaurantName, theDat
164
164
  params.set("tenant_code", tenantCode);
165
165
  return request(`/demand-analytics?${params}`);
166
166
  }
167
- async function apiGetOpenTableChangeLog(dimension, eventType, username, restaurantName, rid, dateFrom, dateTo, period, limit, tenantCode) {
167
+ async function apiGetChangeLog(dimension, eventType, username, restaurantName, rid, dateFrom, dateTo, period, limit, tenantCode) {
168
168
  const params = new URLSearchParams({ dimension });
169
169
  if (eventType)
170
170
  params.set("event_type", eventType);
@@ -184,7 +184,7 @@ async function apiGetOpenTableChangeLog(dimension, eventType, username, restaura
184
184
  params.set("limit", limit);
185
185
  if (tenantCode)
186
186
  params.set("tenant_code", tenantCode);
187
- return request(`/opentable-change-log?${params}`);
187
+ return request(`/change-log?${params}`);
188
188
  }
189
189
  async function apiGetAvailabilityAnalytics(dimension, flagType, restaurantName, serviceDate, tenantCode) {
190
190
  const params = new URLSearchParams({ dimension });
package/dist/http.js CHANGED
@@ -72,7 +72,7 @@ async function createSession(apiKey) {
72
72
  availableDatasetTypes = new Set(Object.values(index_js_2.TOOL_DATASET_MAP));
73
73
  }
74
74
  // Create MCP server and transport for this session
75
- const server = new index_js_1.Server({ name: "distil-ai-rms-reporting", version: "1.0.0" }, { capabilities: { tools: {} } });
75
+ const server = new index_js_1.Server({ name: "distil-ai-rms-reporting", version: "1.0.0" }, { capabilities: { tools: {} }, instructions: index_js_2.SERVER_INSTRUCTIONS });
76
76
  (0, index_js_2.registerHandlers)(server, availableDatasetTypes, ctx);
77
77
  const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
78
78
  sessionIdGenerator: () => crypto_1.default.randomUUID(),
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.ALL_TOOLS = exports.TOOL_DATASET_MAP = void 0;
7
+ exports.ALL_TOOLS = exports.TOOL_DATASET_MAP = exports.SERVER_INSTRUCTIONS = void 0;
8
8
  exports.registerHandlers = registerHandlers;
9
9
  const crypto_1 = __importDefault(require("crypto"));
10
10
  const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
@@ -25,6 +25,26 @@ const PROMPT_PARAM = {
25
25
  description: "Optional. Pass the user's original natural language question that triggered this tool call. Used for usage analytics and improving data quality.",
26
26
  },
27
27
  };
28
+ // Top-level routing guidance for Claude. Sent on initialize, applies before
29
+ // any tool selection. Use this for cross-tool decision rules that don't fit
30
+ // neatly inside a single tool description.
31
+ exports.SERVER_INSTRUCTIONS = `Distil RMS Reporting MCP — restaurant analytics across reservations, demand, availability, POS, marketing, loyalty, change-log, and more.
32
+
33
+ Tool-selection priorities:
34
+
35
+ 1. Reservation pacing ("on the book at T-N", "this week vs last week", "how is Saturday building", "covers booked by yesterday"): use get_pacing_stats. Default for any pace question on actual reservations.
36
+
37
+ 2. Forward-looking demand-search signal ("baseline", "days-out booking curve", "demand vs historical median at the same days_out"): use get_demand_outlook. Only when the user explicitly mentions demand or baselines.
38
+
39
+ 3. Aggregate counts/covers/revenue by visit date: get_date_stats / get_revenue_stats. Do NOT pull rows from query_reservations to count — use the aggregate endpoints.
40
+
41
+ 4. Audit / change-log questions ("who changed what", "recent admin activity", "configuration drift"): use get_change_log.
42
+
43
+ 5. POS check-level data (sales, comps, item mix): use the get_aloha_* family.
44
+
45
+ 6. Use query_reservations only when the user needs raw rows (specific bookings, guest details, notes). It caps at 1000 rows; aggregates belong in stats endpoints.
46
+
47
+ If a tool is missing for the question, say so plainly rather than approximating with raw row pulls.`;
28
48
  // Maps each tool to the dataset_type it requires
29
49
  exports.TOOL_DATASET_MAP = {
30
50
  get_schema: "reservations",
@@ -37,7 +57,7 @@ exports.TOOL_DATASET_MAP = {
37
57
  get_demand_outlook: "demand",
38
58
  get_demand_analytics: "demand_analytics",
39
59
  get_availability_analytics: "availability_analytics",
40
- get_opentable_change_log: "opentable_group_change_log",
60
+ get_change_log: "opentable_group_change_log",
41
61
  get_review_stats: "reviews",
42
62
  get_forecast_stats: "cover_forecast",
43
63
  get_aloha_schema: "aloha_opentable_pos",
@@ -220,7 +240,7 @@ exports.ALL_TOOLS = [
220
240
  },
221
241
  {
222
242
  name: "get_pacing_stats",
223
- description: "Returns booking-pace ('T-N' / 'as-of') aggregates: for a given visit date (or range), how many reservations and covers were on the book by end of as_of_date, plus the current non-cancelled total and pace percentages. Use this for any 'where were we at T-1 / T-7 / last week vs this week' question. One call replaces multi-call pagination over /reservations/query with created_date / cancellation_date filters.",
243
+ description: "DEFAULT TOOL for any 'pace', 'pacing', 'on the book', 'T-N', 'T-1 / T-7', 'where were we at this time last week', or 'how is the book building' question about ACTUAL RESERVATIONS. Returns, for a given visit date (or range), how many reservations and covers were on the book by end of as_of_date, the current non-cancelled total, and pace percentages. One call replaces multi-call pagination over /reservations/query with created_date / cancellation_date filters. NOT for forward-looking demand-search signal — for that use get_demand_outlook.",
224
244
  inputSchema: {
225
245
  type: "object",
226
246
  properties: {
@@ -253,14 +273,14 @@ exports.ALL_TOOLS = [
253
273
  },
254
274
  {
255
275
  name: "get_demand_outlook",
256
- description: "Queries the data_restaurant_demand_master table to analyse forward-looking demand. Use this for questions about upcoming reservation demand, booking pace (how far in advance guests book), party size distribution in the outlook period, or which restaurants have the highest expected demand. Always uses the latest snapshot by default.",
276
+ description: "Forward-looking DEMAND-SEARCH signal from the data_restaurant_demand_master snapshot what guests are searching for and how that's tracking vs the same-day-of-week historical baseline at the same days-out. Use ONLY when the user explicitly asks about 'demand', 'demand search', 'demand outlook', 'baseline', or 'days-out booking curve'. NOT for reservation pacing — for 'how many covers were on the book at T-1 / vs last week' on actual reservations, use get_pacing_stats instead. The booking_pace and pace_by_date dimensions here describe how demand-search builds over days_out (a curve), NOT the as-of count of reservations on the book.",
257
277
  inputSchema: {
258
278
  type: "object",
259
279
  properties: {
260
280
  dimension: {
261
281
  type: "string",
262
282
  enum: ["by_date", "by_restaurant", "by_party_size", "booking_pace", "pace_by_date", "by_date_restaurant", "pace_snapshot"],
263
- description: "pace_snapshot: USE THIS FIRST for any demand outlook or booking pace question. Returns one row per restaurant × future date with: days_out_today, cum_demand_today, baseline_median (same-DOW historical median at the same days_out), pct_vs_baseline, flag (Well ahead/Ahead/On track/Behind/Well behind), party mix % by band (mix_small_pct/mix_standard_pct/mix_medium_pct/mix_large_pct/mix_event_pct), and mix_shift_flag highlighting the biggest mix shift vs baseline if >10pp. One call replaces 36+ multi-call pace patterns. by_date: total demand per upcoming date (all restaurants combined). by_restaurant: demand ranked by restaurant for the outlook period. by_party_size: demand distribution across party sizes. booking_pace: booking curve aggregated across all dates. pace_by_date: booking curve per restaurant × date × days_out — all restaurants included unless restaurant_name filter applied. by_date_restaurant: per-date per-restaurant demand from the latest snapshot.",
283
+ description: "pace_snapshot: USE THIS FIRST for any demand-search outlook or days-out booking-curve question. Returns one row per restaurant × future date with: days_out_today, cum_demand_today, baseline_median (median of same-DOW past dates at the same days_out horizon, pulled from historical snapshots), sample_count (how many past dates fed the baseline — treat baselines below ~4 samples as low-confidence), pct_vs_baseline, flag (Well ahead/Ahead/On track/Behind/Well behind/No baseline), party mix % by band (mix_small_pct/mix_standard_pct/mix_medium_pct/mix_large_pct/mix_event_pct), and mix_shift_flag highlighting the biggest mix shift vs baseline if >10pp. One call replaces 36+ multi-call pace patterns. by_date: total demand per upcoming date (all restaurants combined). by_restaurant: demand ranked by restaurant for the outlook period. by_party_size: demand distribution across party sizes. booking_pace: booking curve aggregated across all dates. pace_by_date: booking curve per restaurant × date × days_out — all restaurants included unless restaurant_name filter applied. by_date_restaurant: per-date per-restaurant demand from the latest snapshot.",
264
284
  },
265
285
  snapshot_date: {
266
286
  type: "string",
@@ -349,8 +369,8 @@ exports.ALL_TOOLS = [
349
369
  },
350
370
  },
351
371
  {
352
- name: "get_opentable_change_log",
353
- description: "Queries data_opentable_change_log_master OpenTable audit events for the tenant's restaurants (floor plan changes, shift edits, permission changes, section configuration updates, etc). Use this to investigate who changed what and when, audit configuration drift, or summarise recent admin activity across a group. Requires the tenant to have the opentable_group_change_log dataset configured.",
372
+ name: "get_change_log",
373
+ description: "Audit / change-log events for the tenant's restaurants floor plan changes, shift edits, permission changes, section configuration updates, etc. Use this for any 'change log', 'audit', 'who changed what', 'recent admin activity', or 'configuration drift' question. Returns counts and timelines of change events; use the recent dimension for raw events and the by_* dimensions for summaries.",
354
374
  inputSchema: {
355
375
  type: "object",
356
376
  properties: {
@@ -1196,11 +1216,11 @@ function registerHandlers(server, availableDatasetTypes, tenantContext) {
1196
1216
  const data = await (0, tools_js_1.getAvailabilityAnalytics)(a.dimension, a.flag_type, a.restaurant_name, a.service_date, a.tenant_code);
1197
1217
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
1198
1218
  }
1199
- case "get_opentable_change_log": {
1219
+ case "get_change_log": {
1200
1220
  if (!a.dimension) {
1201
1221
  return { content: [{ type: "text", text: "Error: dimension is required." }], isError: true };
1202
1222
  }
1203
- const data = await (0, tools_js_1.getOpenTableChangeLog)(a.dimension, a.event_type, a.username, a.restaurant_name, a.rid, a.date_from, a.date_to, a.period, a.limit, a.tenant_code);
1223
+ const data = await (0, tools_js_1.getChangeLog)(a.dimension, a.event_type, a.username, a.restaurant_name, a.rid, a.date_from, a.date_to, a.period, a.limit, a.tenant_code);
1204
1224
  return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
1205
1225
  }
1206
1226
  case "get_review_stats": {
@@ -1442,7 +1462,7 @@ async function main() {
1442
1462
  console.error(`Dataset discovery failed, exposing all tools: ${err instanceof Error ? err.message : String(err)}`);
1443
1463
  availableDatasetTypes = new Set(Object.values(exports.TOOL_DATASET_MAP));
1444
1464
  }
1445
- const server = new index_js_1.Server({ name: "distil-ai-rms-reporting", version: "1.0.0" }, { capabilities: { tools: {} } });
1465
+ const server = new index_js_1.Server({ name: "distil-ai-rms-reporting", version: "1.0.0" }, { capabilities: { tools: {} }, instructions: exports.SERVER_INSTRUCTIONS });
1446
1466
  registerHandlers(server, availableDatasetTypes, ctx);
1447
1467
  const transport = new stdio_js_1.StdioServerTransport();
1448
1468
  await server.connect(transport);
package/dist/tools.js CHANGED
@@ -7,7 +7,7 @@ exports.getRevenueStats = getRevenueStats;
7
7
  exports.getTimePatternStats = getTimePatternStats;
8
8
  exports.getDemandAnalytics = getDemandAnalytics;
9
9
  exports.getAvailabilityAnalytics = getAvailabilityAnalytics;
10
- exports.getOpenTableChangeLog = getOpenTableChangeLog;
10
+ exports.getChangeLog = getChangeLog;
11
11
  exports.getDemandOutlook = getDemandOutlook;
12
12
  exports.getReviewStats = getReviewStats;
13
13
  exports.getForecastStats = getForecastStats;
@@ -95,9 +95,9 @@ async function getAvailabilityAnalytics(dimension, flagType, restaurantName, ser
95
95
  const { data } = await (0, api_js_1.apiGetAvailabilityAnalytics)(dimension, flagType, restaurantName, serviceDate, tenantCode);
96
96
  return checkResponseSize("get_availability_analytics", data);
97
97
  }
98
- async function getOpenTableChangeLog(dimension, eventType, username, restaurantName, rid, dateFrom, dateTo, period, limit, tenantCode) {
99
- const { data } = await (0, api_js_1.apiGetOpenTableChangeLog)(dimension, eventType, username, restaurantName, rid, dateFrom, dateTo, period, limit, tenantCode);
100
- return checkResponseSize("get_opentable_change_log", data);
98
+ async function getChangeLog(dimension, eventType, username, restaurantName, rid, dateFrom, dateTo, period, limit, tenantCode) {
99
+ const { data } = await (0, api_js_1.apiGetChangeLog)(dimension, eventType, username, restaurantName, rid, dateFrom, dateTo, period, limit, tenantCode);
100
+ return checkResponseSize("get_change_log", data);
101
101
  }
102
102
  async function getDemandOutlook(dimension, snapshotDate, restaurantName, dateFrom, dateTo, partySize, tenantCode) {
103
103
  const { data } = await (0, api_js_1.apiGetDemandOutlook)(dimension, snapshotDate, restaurantName, dateFrom, dateTo, partySize, tenantCode);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "distil-ai-rms-reporting",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "description": "MCP server for restaurant management system reporting and analytics",
5
5
  "main": "dist/index.js",
6
6
  "bin": {