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 +3 -3
- package/dist/http.js +1 -1
- package/dist/index.js +30 -10
- package/dist/tools.js +4 -4
- package/package.json +1 -1
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.
|
|
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
|
|
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(`/
|
|
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
|
-
|
|
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: "
|
|
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: "
|
|
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
|
|
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: "
|
|
353
|
-
description: "
|
|
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 "
|
|
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.
|
|
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.
|
|
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
|
|
99
|
-
const { data } = await (0, api_js_1.
|
|
100
|
-
return checkResponseSize("
|
|
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);
|