apphud-mcp 0.2.2 → 0.2.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.
@@ -1,28 +1,7 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
- import { z } from "zod";
4
3
  import { toToolError } from "../errors/toolError.js";
5
- import { resolveAuth } from "../security/authResolver.js";
6
- const authSchema = z
7
- .object({
8
- tenant_id: z.string().min(1),
9
- role: z.enum(["analyst", "support", "admin"]),
10
- actor_id: z.string().min(1).optional(),
11
- })
12
- .optional();
13
- const analyticsPlatformSchema = z.enum(["ios", "android", "web"]);
14
- const analyticsFiltersSchema = z
15
- .record(z.union([z.string(), z.number(), z.boolean(), z.null()]))
16
- .optional();
17
- const analyticsEventsFiltersSchema = z
18
- .object({
19
- user_id: z.string().min(1).optional(),
20
- product_id: z.string().min(1).optional(),
21
- event_type: z.string().min(1).optional(),
22
- country: z.string().min(1).optional(),
23
- platform: analyticsPlatformSchema.optional(),
24
- })
25
- .optional();
4
+ import { executeRemoteTool, getRemoteToolEntries } from "../tools/remoteTools.js";
26
5
  function jsonResult(payload, isError = false) {
27
6
  return {
28
7
  content: [{ type: "text", text: JSON.stringify(payload) }],
@@ -32,819 +11,19 @@ function jsonResult(payload, isError = false) {
32
11
  export function createMcpServer(container) {
33
12
  const server = new McpServer({
34
13
  name: "apphud-mcp",
35
- version: "0.2.0",
36
- });
37
- server.tool("apphud_etl_local_status", "Get local ETL worker status and TODO alerts", {
38
- tenant_id: z.string().optional(),
39
- auth: authSchema,
40
- }, async (input) => {
41
- const auth = resolveAuth(input, container.config);
42
- try {
43
- const result = await container.toolGuard.run(auth, "apphud_etl_local_status", async () => container.etlService.localStatus());
44
- return jsonResult(result);
45
- }
46
- catch (error) {
47
- return jsonResult(toToolError(error), true);
48
- }
49
- });
50
- server.tool("apphud_apps_list_local", "List apps available in local ETL SQLite storage", {
51
- tenant_id: z.string().optional(),
52
- auth: authSchema,
53
- include_raw: z.boolean().optional(),
54
- }, async (input) => {
55
- const auth = resolveAuth(input, container.config);
56
- try {
57
- const result = await container.toolGuard.run(auth, "apphud_apps_list_local", async () => container.etlService.localAppsList({ include_raw: input.include_raw }));
58
- return jsonResult(result);
59
- }
60
- catch (error) {
61
- return jsonResult(toToolError(error), true);
62
- }
63
- });
64
- server.tool("apphud_dashboard_local", "Local dashboard summary (Money, Subscriptions, selected range, events, users)", {
65
- tenant_id: z.string().optional(),
66
- auth: authSchema,
67
- app_id: z.string().min(1).optional(),
68
- apphud_app_id: z.string().min(1).optional(),
69
- from: z.string().datetime().optional(),
70
- to: z.string().datetime().optional(),
71
- filters: analyticsFiltersSchema,
72
- include_raw: z.boolean().optional(),
73
- }, async (input) => {
74
- const auth = resolveAuth(input, container.config);
75
- try {
76
- const result = await container.toolGuard.run(auth, "apphud_dashboard_local", async () => container.etlService.localDashboard({
77
- app_id: input.app_id,
78
- apphud_app_id: input.apphud_app_id,
79
- from: input.from,
80
- to: input.to,
81
- filters: input.filters,
82
- include_raw: input.include_raw,
83
- }), { appId: input.app_id ?? input.apphud_app_id });
84
- return jsonResult(result);
85
- }
86
- catch (error) {
87
- return jsonResult(toToolError(error), true);
88
- }
89
- });
90
- server.tool("apphud_analytics_events_list_local", "List raw subscription events from local ETL SQLite storage", {
91
- tenant_id: z.string().optional(),
92
- auth: authSchema,
93
- app_id: z.string().min(1).optional(),
94
- apphud_app_id: z.string().min(1).optional(),
95
- from: z.string().datetime(),
96
- to: z.string().datetime(),
97
- limit: z.number().int().min(1).max(500).optional(),
98
- cursor: z.string().min(1).optional(),
99
- filters: analyticsEventsFiltersSchema,
100
- include_raw: z.boolean().optional(),
101
- }, async (input) => {
102
- const auth = resolveAuth(input, container.config);
103
- try {
104
- const result = await container.toolGuard.run(auth, "apphud_analytics_events_list_local", async () => container.etlService.localEventsList({
105
- app_id: input.app_id,
106
- apphud_app_id: input.apphud_app_id,
107
- from: input.from,
108
- to: input.to,
109
- limit: input.limit,
110
- filters: input.filters,
111
- include_raw: input.include_raw,
112
- }), { appId: input.app_id ?? input.apphud_app_id });
113
- return jsonResult(result);
114
- }
115
- catch (error) {
116
- return jsonResult(toToolError(error), true);
117
- }
118
- });
119
- server.tool("apphud_analytics_active_subscriptions_local", "Fetch active paid subscriptions from local ETL SQLite storage", {
120
- tenant_id: z.string().optional(),
121
- auth: authSchema,
122
- app_id: z.string().min(1).optional(),
123
- apphud_app_id: z.string().min(1).optional(),
124
- platform: analyticsPlatformSchema.optional(),
125
- include_raw: z.boolean().optional(),
126
- }, async (input) => {
127
- const auth = resolveAuth(input, container.config);
128
- try {
129
- const result = await container.toolGuard.run(auth, "apphud_analytics_active_subscriptions_local", async () => container.etlService.localMetricValue({
130
- app_id: input.app_id,
131
- apphud_app_id: input.apphud_app_id,
132
- metric_key: "active_subs",
133
- include_raw: input.include_raw,
134
- filters: input.platform ? { platform: input.platform } : undefined,
135
- }), { appId: input.app_id ?? input.apphud_app_id });
136
- return jsonResult(result);
137
- }
138
- catch (error) {
139
- return jsonResult(toToolError(error), true);
140
- }
141
- });
142
- server.tool("apphud_analytics_capabilities_get_local", "Get local analytics capabilities and available metrics", {
143
- tenant_id: z.string().optional(),
144
- auth: authSchema,
145
- app_id: z.string().min(1).optional(),
146
- apphud_app_id: z.string().min(1).optional(),
147
- include_raw: z.boolean().optional(),
148
- }, async (input) => {
149
- const auth = resolveAuth(input, container.config);
150
- try {
151
- const result = await container.toolGuard.run(auth, "apphud_analytics_capabilities_get_local", async () => container.etlService.localCapabilities({
152
- app_id: input.app_id,
153
- apphud_app_id: input.apphud_app_id,
154
- include_raw: input.include_raw,
155
- }), { appId: input.app_id ?? input.apphud_app_id });
156
- return jsonResult(result);
157
- }
158
- catch (error) {
159
- return jsonResult(toToolError(error), true);
160
- }
161
- });
162
- server.tool("apphud_analytics_metrics_list_local", "List local analytics metric keys", {
163
- tenant_id: z.string().optional(),
164
- auth: authSchema,
165
- app_id: z.string().min(1).optional(),
166
- apphud_app_id: z.string().min(1).optional(),
167
- include_raw: z.boolean().optional(),
168
- }, async (input) => {
169
- const auth = resolveAuth(input, container.config);
170
- try {
171
- const result = await container.toolGuard.run(auth, "apphud_analytics_metrics_list_local", async () => container.etlService.localMetricsList({
172
- app_id: input.app_id,
173
- apphud_app_id: input.apphud_app_id,
174
- include_raw: input.include_raw,
175
- }), { appId: input.app_id ?? input.apphud_app_id });
176
- return jsonResult(result);
177
- }
178
- catch (error) {
179
- return jsonResult(toToolError(error), true);
180
- }
181
- });
182
- server.tool("apphud_analytics_metric_value_local", "Get single metric value from local ETL SQLite storage", {
183
- tenant_id: z.string().optional(),
184
- auth: authSchema,
185
- app_id: z.string().min(1).optional(),
186
- apphud_app_id: z.string().min(1).optional(),
187
- metric_key: z.string().min(1),
188
- from: z.string().datetime().optional(),
189
- to: z.string().datetime().optional(),
190
- platform: analyticsPlatformSchema.optional(),
191
- filters: analyticsFiltersSchema,
192
- include_raw: z.boolean().optional(),
193
- }, async (input) => {
194
- const auth = resolveAuth(input, container.config);
195
- try {
196
- const result = await container.toolGuard.run(auth, "apphud_analytics_metric_value_local", async () => container.etlService.localMetricValue({
197
- app_id: input.app_id,
198
- apphud_app_id: input.apphud_app_id,
199
- metric_key: input.metric_key,
200
- from: input.from,
201
- to: input.to,
202
- filters: input.filters,
203
- include_raw: input.include_raw,
204
- }), { appId: input.app_id ?? input.apphud_app_id });
205
- return jsonResult(result);
206
- }
207
- catch (error) {
208
- return jsonResult(toToolError(error), true);
209
- }
210
- });
211
- server.tool("apphud_analytics_metric_timeseries_local", "Get metric timeseries from local ETL SQLite storage", {
212
- tenant_id: z.string().optional(),
213
- auth: authSchema,
214
- app_id: z.string().min(1).optional(),
215
- apphud_app_id: z.string().min(1).optional(),
216
- metric_key: z.string().min(1),
217
- from: z.string().datetime(),
218
- to: z.string().datetime(),
219
- granularity: z.enum(["day", "week"]).optional(),
220
- platform: analyticsPlatformSchema.optional(),
221
- filters: analyticsFiltersSchema,
222
- include_raw: z.boolean().optional(),
223
- }, async (input) => {
224
- const auth = resolveAuth(input, container.config);
225
- try {
226
- const result = await container.toolGuard.run(auth, "apphud_analytics_metric_timeseries_local", async () => container.etlService.localMetricTimeseries({
227
- app_id: input.app_id,
228
- apphud_app_id: input.apphud_app_id,
229
- metric_key: input.metric_key,
230
- from: input.from,
231
- to: input.to,
232
- granularity: input.granularity,
233
- filters: input.filters,
234
- include_raw: input.include_raw,
235
- }), { appId: input.app_id ?? input.apphud_app_id });
236
- return jsonResult(result);
237
- }
238
- catch (error) {
239
- return jsonResult(toToolError(error), true);
240
- }
241
- });
242
- server.tool("apphud_analytics_metric_breakdown_local", "Get metric breakdown from local ETL SQLite storage", {
243
- tenant_id: z.string().optional(),
244
- auth: authSchema,
245
- app_id: z.string().min(1).optional(),
246
- apphud_app_id: z.string().min(1).optional(),
247
- metric_key: z.string().min(1),
248
- from: z.string().datetime(),
249
- to: z.string().datetime(),
250
- dimension: z.string().min(1),
251
- granularity: z.enum(["day", "week"]).optional(),
252
- platform: analyticsPlatformSchema.optional(),
253
- filters: analyticsFiltersSchema,
254
- limit: z.number().int().min(1).max(200).optional(),
255
- include_raw: z.boolean().optional(),
256
- }, async (input) => {
257
- const auth = resolveAuth(input, container.config);
258
- try {
259
- const result = await container.toolGuard.run(auth, "apphud_analytics_metric_breakdown_local", async () => container.etlService.localMetricBreakdown({
260
- app_id: input.app_id,
261
- apphud_app_id: input.apphud_app_id,
262
- metric_key: input.metric_key,
263
- from: input.from,
264
- to: input.to,
265
- dimension: input.dimension,
266
- granularity: input.granularity,
267
- limit: input.limit,
268
- filters: input.filters,
269
- include_raw: input.include_raw,
270
- }), { appId: input.app_id ?? input.apphud_app_id });
271
- return jsonResult(result);
272
- }
273
- catch (error) {
274
- return jsonResult(toToolError(error), true);
275
- }
276
- });
277
- server.tool("apphud_analytics_revenue_summary_local", "Get revenue summary from local ETL SQLite storage", {
278
- tenant_id: z.string().optional(),
279
- auth: authSchema,
280
- app_id: z.string().min(1).optional(),
281
- apphud_app_id: z.string().min(1).optional(),
282
- from: z.string().datetime(),
283
- to: z.string().datetime(),
284
- platform: analyticsPlatformSchema.optional(),
285
- filters: analyticsFiltersSchema,
286
- compare_prev_period: z.boolean().optional(),
287
- include_raw: z.boolean().optional(),
288
- }, async (input) => {
289
- const auth = resolveAuth(input, container.config);
290
- try {
291
- const result = await container.toolGuard.run(auth, "apphud_analytics_revenue_summary_local", async () => container.etlService.localRevenueSummary({
292
- app_id: input.app_id,
293
- apphud_app_id: input.apphud_app_id,
294
- from: input.from,
295
- to: input.to,
296
- filters: input.filters,
297
- compare_prev_period: input.compare_prev_period,
298
- include_raw: input.include_raw,
299
- }), { appId: input.app_id ?? input.apphud_app_id });
300
- return jsonResult(result);
301
- }
302
- catch (error) {
303
- return jsonResult(toToolError(error), true);
304
- }
305
- });
306
- server.tool("apphud_analytics_subscriptions_summary_local", "Get subscriptions KPI summary from local ETL SQLite storage", {
307
- tenant_id: z.string().optional(),
308
- auth: authSchema,
309
- app_id: z.string().min(1).optional(),
310
- apphud_app_id: z.string().min(1).optional(),
311
- from: z.string().datetime().optional(),
312
- to: z.string().datetime().optional(),
313
- platform: analyticsPlatformSchema.optional(),
314
- filters: analyticsFiltersSchema,
315
- include_raw: z.boolean().optional(),
316
- }, async (input) => {
317
- const auth = resolveAuth(input, container.config);
318
- try {
319
- const result = await container.toolGuard.run(auth, "apphud_analytics_subscriptions_summary_local", async () => container.etlService.localSubscriptionsSummary({
320
- app_id: input.app_id,
321
- apphud_app_id: input.apphud_app_id,
322
- from: input.from,
323
- to: input.to,
324
- filters: input.filters,
325
- include_raw: input.include_raw,
326
- }), { appId: input.app_id ?? input.apphud_app_id });
327
- return jsonResult(result);
328
- }
329
- catch (error) {
330
- return jsonResult(toToolError(error), true);
331
- }
332
- });
333
- server.tool("apphud_analytics_conversion_trial_to_paid_local", "Get trial to paid conversion summary from local ETL SQLite storage", {
334
- tenant_id: z.string().optional(),
335
- auth: authSchema,
336
- app_id: z.string().min(1).optional(),
337
- apphud_app_id: z.string().min(1).optional(),
338
- from: z.string().datetime(),
339
- to: z.string().datetime(),
340
- platform: analyticsPlatformSchema.optional(),
341
- filters: analyticsFiltersSchema,
342
- include_raw: z.boolean().optional(),
343
- }, async (input) => {
344
- const auth = resolveAuth(input, container.config);
345
- try {
346
- const result = await container.toolGuard.run(auth, "apphud_analytics_conversion_trial_to_paid_local", async () => container.etlService.localConversionTrialToPaid({
347
- app_id: input.app_id,
348
- apphud_app_id: input.apphud_app_id,
349
- from: input.from,
350
- to: input.to,
351
- filters: input.filters,
352
- include_raw: input.include_raw,
353
- }), { appId: input.app_id ?? input.apphud_app_id });
354
- return jsonResult(result);
355
- }
356
- catch (error) {
357
- return jsonResult(toToolError(error), true);
358
- }
359
- });
360
- server.tool("apphud_analytics_cohorts_retention_local", "Get cohorts retention from local ETL SQLite storage", {
361
- tenant_id: z.string().optional(),
362
- auth: authSchema,
363
- app_id: z.string().min(1).optional(),
364
- apphud_app_id: z.string().min(1).optional(),
365
- from: z.string().datetime(),
366
- to: z.string().datetime(),
367
- granularity: z.enum(["day", "week"]).optional(),
368
- max_periods: z.number().int().min(1).max(104).optional(),
369
- platform: analyticsPlatformSchema.optional(),
370
- filters: analyticsFiltersSchema,
371
- include_raw: z.boolean().optional(),
372
- }, async (input) => {
373
- const auth = resolveAuth(input, container.config);
374
- try {
375
- const result = await container.toolGuard.run(auth, "apphud_analytics_cohorts_retention_local", async () => container.etlService.localCohortsRetention({
376
- app_id: input.app_id,
377
- apphud_app_id: input.apphud_app_id,
378
- from: input.from,
379
- to: input.to,
380
- granularity: input.granularity,
381
- filters: input.filters,
382
- include_raw: input.include_raw,
383
- }), { appId: input.app_id ?? input.apphud_app_id });
384
- return jsonResult(result);
385
- }
386
- catch (error) {
387
- return jsonResult(toToolError(error), true);
388
- }
389
- });
390
- server.tool("apphud_analytics_cohorts_ltv_local", "Get cohorts cumulative LTV from local ETL SQLite storage", {
391
- tenant_id: z.string().optional(),
392
- auth: authSchema,
393
- app_id: z.string().min(1).optional(),
394
- apphud_app_id: z.string().min(1).optional(),
395
- from: z.string().datetime(),
396
- to: z.string().datetime(),
397
- granularity: z.enum(["day", "week"]).optional(),
398
- max_periods: z.number().int().min(1).max(104).optional(),
399
- platform: analyticsPlatformSchema.optional(),
400
- filters: analyticsFiltersSchema,
401
- include_raw: z.boolean().optional(),
402
- }, async (input) => {
403
- const auth = resolveAuth(input, container.config);
404
- try {
405
- const result = await container.toolGuard.run(auth, "apphud_analytics_cohorts_ltv_local", async () => container.etlService.localCohortsLtv({
406
- app_id: input.app_id,
407
- apphud_app_id: input.apphud_app_id,
408
- from: input.from,
409
- to: input.to,
410
- granularity: input.granularity,
411
- filters: input.filters,
412
- include_raw: input.include_raw,
413
- }), { appId: input.app_id ?? input.apphud_app_id });
414
- return jsonResult(result);
415
- }
416
- catch (error) {
417
- return jsonResult(toToolError(error), true);
418
- }
419
- });
420
- server.tool("apphud_analytics_query_raw_local", "Low-level local analytics query tool (value/timeseries/breakdown/raw)", {
421
- tenant_id: z.string().optional(),
422
- auth: authSchema,
423
- app_id: z.string().min(1).optional(),
424
- apphud_app_id: z.string().min(1).optional(),
425
- query: z.object({
426
- shape: z.enum(["value", "timeseries", "breakdown", "raw"]),
427
- metric_key: z.string().optional(),
428
- from: z.string().datetime().optional(),
429
- to: z.string().datetime().optional(),
430
- granularity: z.enum(["day", "week"]).optional(),
431
- dimension: z.string().optional(),
432
- endpoint_path: z.string().optional(),
433
- method: z.enum(["GET", "POST"]).optional(),
434
- query_params: z.record(z.string()).optional(),
435
- body: z.record(z.unknown()).optional(),
436
- filters: analyticsFiltersSchema,
437
- platform: analyticsPlatformSchema.optional(),
438
- limit: z.number().int().min(1).max(500).optional(),
439
- }),
440
- include_raw: z.boolean().optional(),
441
- }, async (input) => {
442
- const auth = resolveAuth(input, container.config);
443
- try {
444
- const result = await container.toolGuard.run(auth, "apphud_analytics_query_raw_local", async () => container.etlService.localQueryRaw({
445
- app_id: input.app_id,
446
- apphud_app_id: input.apphud_app_id,
447
- query: input.query,
448
- include_raw: input.include_raw,
449
- }), { appId: input.app_id ?? input.apphud_app_id });
450
- return jsonResult(result);
451
- }
452
- catch (error) {
453
- return jsonResult(toToolError(error), true);
454
- }
455
- });
456
- server.tool("apphud_apps_list", "List apps available in authenticated Apphud dashboard account", {
457
- tenant_id: z.string().optional(),
458
- auth: authSchema,
459
- include_raw: z.boolean().optional(),
460
- }, async (input) => {
461
- const auth = resolveAuth(input, container.config);
462
- try {
463
- const result = await container.toolGuard.run(auth, "apphud_apps_list", async () => container.analyticsService.appsList(auth, {
464
- include_raw: input.include_raw,
465
- }));
466
- return jsonResult(result);
467
- }
468
- catch (error) {
469
- return jsonResult(toToolError(error), true);
470
- }
471
- });
472
- server.tool("apphud_analytics_events_list", "List raw subscription events from Apphud dashboard event feed", {
473
- tenant_id: z.string().optional(),
474
- auth: authSchema,
475
- app_id: z.string().min(1).optional(),
476
- apphud_app_id: z.string().min(1).optional(),
477
- from: z.string().datetime(),
478
- to: z.string().datetime(),
479
- limit: z.number().int().min(1).max(500).optional(),
480
- cursor: z.string().min(1).optional(),
481
- filters: analyticsEventsFiltersSchema,
482
- include_raw: z.boolean().optional(),
483
- }, async (input) => {
484
- const auth = resolveAuth(input, container.config);
485
- try {
486
- const result = await container.toolGuard.run(auth, "apphud_analytics_events_list", async () => container.analyticsService.eventsList(auth, {
487
- app_id: input.app_id,
488
- apphud_app_id: input.apphud_app_id,
489
- from: input.from,
490
- to: input.to,
491
- limit: input.limit,
492
- cursor: input.cursor,
493
- filters: input.filters,
494
- include_raw: input.include_raw,
495
- }), { appId: input.app_id ?? input.apphud_app_id });
496
- return jsonResult(result);
497
- }
498
- catch (error) {
499
- return jsonResult(toToolError(error), true);
500
- }
501
- });
502
- server.tool("apphud_analytics_active_subscriptions", "Fetch active paid subscriptions directly from Apphud analytics endpoint", {
503
- tenant_id: z.string().optional(),
504
- auth: authSchema,
505
- app_id: z.string().min(1).optional(),
506
- apphud_app_id: z.string().min(1).optional(),
507
- platform: analyticsPlatformSchema.optional(),
508
- include_raw: z.boolean().optional(),
509
- }, async (input) => {
510
- const auth = resolveAuth(input, container.config);
511
- try {
512
- const result = await container.toolGuard.run(auth, "apphud_analytics_active_subscriptions", async () => container.analyticsService.activeSubscriptions(auth, {
513
- app_id: input.app_id,
514
- apphud_app_id: input.apphud_app_id,
515
- platform: input.platform,
516
- include_raw: input.include_raw,
517
- }), { appId: input.app_id ?? input.apphud_app_id });
518
- return jsonResult(result);
519
- }
520
- catch (error) {
521
- return jsonResult(toToolError(error), true);
522
- }
523
- });
524
- server.tool("apphud_analytics_capabilities_get", "Get analytics capabilities and available metrics", {
525
- tenant_id: z.string().optional(),
526
- auth: authSchema,
527
- app_id: z.string().min(1).optional(),
528
- apphud_app_id: z.string().min(1).optional(),
529
- include_raw: z.boolean().optional(),
530
- }, async (input) => {
531
- const auth = resolveAuth(input, container.config);
532
- try {
533
- const result = await container.toolGuard.run(auth, "apphud_analytics_capabilities_get", async () => container.analyticsService.capabilities(auth, {
534
- app_id: input.app_id,
535
- apphud_app_id: input.apphud_app_id,
536
- include_raw: input.include_raw,
537
- }), { appId: input.app_id ?? input.apphud_app_id });
538
- return jsonResult(result);
539
- }
540
- catch (error) {
541
- return jsonResult(toToolError(error), true);
542
- }
543
- });
544
- server.tool("apphud_analytics_metrics_list", "List analytics metric keys", {
545
- tenant_id: z.string().optional(),
546
- auth: authSchema,
547
- app_id: z.string().min(1).optional(),
548
- apphud_app_id: z.string().min(1).optional(),
549
- include_raw: z.boolean().optional(),
550
- }, async (input) => {
551
- const auth = resolveAuth(input, container.config);
552
- try {
553
- const result = await container.toolGuard.run(auth, "apphud_analytics_metrics_list", async () => container.analyticsService.metricsList(auth, {
554
- app_id: input.app_id,
555
- apphud_app_id: input.apphud_app_id,
556
- include_raw: input.include_raw,
557
- }), { appId: input.app_id ?? input.apphud_app_id });
558
- return jsonResult(result);
559
- }
560
- catch (error) {
561
- return jsonResult(toToolError(error), true);
562
- }
563
- });
564
- server.tool("apphud_analytics_metric_value", "Get single metric value for period/snapshot", {
565
- tenant_id: z.string().optional(),
566
- auth: authSchema,
567
- app_id: z.string().min(1).optional(),
568
- apphud_app_id: z.string().min(1).optional(),
569
- metric_key: z.string().min(1),
570
- from: z.string().datetime().optional(),
571
- to: z.string().datetime().optional(),
572
- platform: analyticsPlatformSchema.optional(),
573
- filters: analyticsFiltersSchema,
574
- include_raw: z.boolean().optional(),
575
- }, async (input) => {
576
- const auth = resolveAuth(input, container.config);
577
- try {
578
- const result = await container.toolGuard.run(auth, "apphud_analytics_metric_value", async () => container.analyticsService.metricValue(auth, {
579
- app_id: input.app_id,
580
- apphud_app_id: input.apphud_app_id,
581
- metric_key: input.metric_key,
582
- from: input.from,
583
- to: input.to,
584
- platform: input.platform,
585
- filters: input.filters,
586
- include_raw: input.include_raw,
587
- }), { appId: input.app_id ?? input.apphud_app_id });
588
- return jsonResult(result);
589
- }
590
- catch (error) {
591
- return jsonResult(toToolError(error), true);
592
- }
593
- });
594
- server.tool("apphud_analytics_metric_timeseries", "Get metric timeseries by date range", {
595
- tenant_id: z.string().optional(),
596
- auth: authSchema,
597
- app_id: z.string().min(1).optional(),
598
- apphud_app_id: z.string().min(1).optional(),
599
- metric_key: z.string().min(1),
600
- from: z.string().datetime(),
601
- to: z.string().datetime(),
602
- granularity: z.enum(["day", "week"]).optional(),
603
- platform: analyticsPlatformSchema.optional(),
604
- filters: analyticsFiltersSchema,
605
- include_raw: z.boolean().optional(),
606
- }, async (input) => {
607
- const auth = resolveAuth(input, container.config);
608
- try {
609
- const result = await container.toolGuard.run(auth, "apphud_analytics_metric_timeseries", async () => container.analyticsService.metricTimeseries(auth, {
610
- app_id: input.app_id,
611
- apphud_app_id: input.apphud_app_id,
612
- metric_key: input.metric_key,
613
- from: input.from,
614
- to: input.to,
615
- granularity: input.granularity,
616
- platform: input.platform,
617
- filters: input.filters,
618
- include_raw: input.include_raw,
619
- }), { appId: input.app_id ?? input.apphud_app_id });
620
- return jsonResult(result);
621
- }
622
- catch (error) {
623
- return jsonResult(toToolError(error), true);
624
- }
625
- });
626
- server.tool("apphud_analytics_metric_breakdown", "Get metric breakdown by dimension", {
627
- tenant_id: z.string().optional(),
628
- auth: authSchema,
629
- app_id: z.string().min(1).optional(),
630
- apphud_app_id: z.string().min(1).optional(),
631
- metric_key: z.string().min(1),
632
- from: z.string().datetime(),
633
- to: z.string().datetime(),
634
- dimension: z.string().min(1),
635
- granularity: z.enum(["day", "week"]).optional(),
636
- platform: analyticsPlatformSchema.optional(),
637
- filters: analyticsFiltersSchema,
638
- limit: z.number().int().min(1).max(200).optional(),
639
- include_raw: z.boolean().optional(),
640
- }, async (input) => {
641
- const auth = resolveAuth(input, container.config);
642
- try {
643
- const result = await container.toolGuard.run(auth, "apphud_analytics_metric_breakdown", async () => container.analyticsService.metricBreakdown(auth, {
644
- app_id: input.app_id,
645
- apphud_app_id: input.apphud_app_id,
646
- metric_key: input.metric_key,
647
- from: input.from,
648
- to: input.to,
649
- dimension: input.dimension,
650
- granularity: input.granularity,
651
- platform: input.platform,
652
- filters: input.filters,
653
- limit: input.limit,
654
- include_raw: input.include_raw,
655
- }), { appId: input.app_id ?? input.apphud_app_id });
656
- return jsonResult(result);
657
- }
658
- catch (error) {
659
- return jsonResult(toToolError(error), true);
660
- }
661
- });
662
- server.tool("apphud_analytics_revenue_summary", "Get revenue summary for date range", {
663
- tenant_id: z.string().optional(),
664
- auth: authSchema,
665
- app_id: z.string().min(1).optional(),
666
- apphud_app_id: z.string().min(1).optional(),
667
- from: z.string().datetime(),
668
- to: z.string().datetime(),
669
- platform: analyticsPlatformSchema.optional(),
670
- filters: analyticsFiltersSchema,
671
- compare_prev_period: z.boolean().optional(),
672
- include_raw: z.boolean().optional(),
673
- }, async (input) => {
674
- const auth = resolveAuth(input, container.config);
675
- try {
676
- const result = await container.toolGuard.run(auth, "apphud_analytics_revenue_summary", async () => container.analyticsService.revenueSummary(auth, {
677
- app_id: input.app_id,
678
- apphud_app_id: input.apphud_app_id,
679
- from: input.from,
680
- to: input.to,
681
- platform: input.platform,
682
- filters: input.filters,
683
- compare_prev_period: input.compare_prev_period,
684
- include_raw: input.include_raw,
685
- }), { appId: input.app_id ?? input.apphud_app_id });
686
- return jsonResult(result);
687
- }
688
- catch (error) {
689
- return jsonResult(toToolError(error), true);
690
- }
691
- });
692
- server.tool("apphud_analytics_subscriptions_summary", "Get subscriptions KPI summary", {
693
- tenant_id: z.string().optional(),
694
- auth: authSchema,
695
- app_id: z.string().min(1).optional(),
696
- apphud_app_id: z.string().min(1).optional(),
697
- from: z.string().datetime().optional(),
698
- to: z.string().datetime().optional(),
699
- platform: analyticsPlatformSchema.optional(),
700
- filters: analyticsFiltersSchema,
701
- include_raw: z.boolean().optional(),
702
- }, async (input) => {
703
- const auth = resolveAuth(input, container.config);
704
- try {
705
- const result = await container.toolGuard.run(auth, "apphud_analytics_subscriptions_summary", async () => container.analyticsService.subscriptionsSummary(auth, {
706
- app_id: input.app_id,
707
- apphud_app_id: input.apphud_app_id,
708
- from: input.from,
709
- to: input.to,
710
- platform: input.platform,
711
- filters: input.filters,
712
- include_raw: input.include_raw,
713
- }), { appId: input.app_id ?? input.apphud_app_id });
714
- return jsonResult(result);
715
- }
716
- catch (error) {
717
- return jsonResult(toToolError(error), true);
718
- }
719
- });
720
- server.tool("apphud_analytics_conversion_trial_to_paid", "Get trial to paid conversion summary", {
721
- tenant_id: z.string().optional(),
722
- auth: authSchema,
723
- app_id: z.string().min(1).optional(),
724
- apphud_app_id: z.string().min(1).optional(),
725
- from: z.string().datetime(),
726
- to: z.string().datetime(),
727
- platform: analyticsPlatformSchema.optional(),
728
- filters: analyticsFiltersSchema,
729
- include_raw: z.boolean().optional(),
730
- }, async (input) => {
731
- const auth = resolveAuth(input, container.config);
732
- try {
733
- const result = await container.toolGuard.run(auth, "apphud_analytics_conversion_trial_to_paid", async () => container.analyticsService.conversionTrialToPaid(auth, {
734
- app_id: input.app_id,
735
- apphud_app_id: input.apphud_app_id,
736
- from: input.from,
737
- to: input.to,
738
- platform: input.platform,
739
- filters: input.filters,
740
- include_raw: input.include_raw,
741
- }), { appId: input.app_id ?? input.apphud_app_id });
742
- return jsonResult(result);
743
- }
744
- catch (error) {
745
- return jsonResult(toToolError(error), true);
746
- }
747
- });
748
- server.tool("apphud_analytics_cohorts_retention", "Get cohorts retention from analytics", {
749
- tenant_id: z.string().optional(),
750
- auth: authSchema,
751
- app_id: z.string().min(1).optional(),
752
- apphud_app_id: z.string().min(1).optional(),
753
- from: z.string().datetime(),
754
- to: z.string().datetime(),
755
- granularity: z.enum(["day", "week"]).optional(),
756
- max_periods: z.number().int().min(1).max(104).optional(),
757
- platform: analyticsPlatformSchema.optional(),
758
- filters: analyticsFiltersSchema,
759
- include_raw: z.boolean().optional(),
760
- }, async (input) => {
761
- const auth = resolveAuth(input, container.config);
762
- try {
763
- const result = await container.toolGuard.run(auth, "apphud_analytics_cohorts_retention", async () => container.analyticsService.cohortsRetention(auth, {
764
- app_id: input.app_id,
765
- apphud_app_id: input.apphud_app_id,
766
- from: input.from,
767
- to: input.to,
768
- granularity: input.granularity,
769
- max_periods: input.max_periods,
770
- platform: input.platform,
771
- filters: input.filters,
772
- include_raw: input.include_raw,
773
- }), { appId: input.app_id ?? input.apphud_app_id });
774
- return jsonResult(result);
775
- }
776
- catch (error) {
777
- return jsonResult(toToolError(error), true);
778
- }
779
- });
780
- server.tool("apphud_analytics_cohorts_ltv", "Get cohorts cumulative LTV from analytics", {
781
- tenant_id: z.string().optional(),
782
- auth: authSchema,
783
- app_id: z.string().min(1).optional(),
784
- apphud_app_id: z.string().min(1).optional(),
785
- from: z.string().datetime(),
786
- to: z.string().datetime(),
787
- granularity: z.enum(["day", "week"]).optional(),
788
- max_periods: z.number().int().min(1).max(104).optional(),
789
- platform: analyticsPlatformSchema.optional(),
790
- filters: analyticsFiltersSchema,
791
- include_raw: z.boolean().optional(),
792
- }, async (input) => {
793
- const auth = resolveAuth(input, container.config);
794
- try {
795
- const result = await container.toolGuard.run(auth, "apphud_analytics_cohorts_ltv", async () => container.analyticsService.cohortsLtv(auth, {
796
- app_id: input.app_id,
797
- apphud_app_id: input.apphud_app_id,
798
- from: input.from,
799
- to: input.to,
800
- granularity: input.granularity,
801
- max_periods: input.max_periods,
802
- platform: input.platform,
803
- filters: input.filters,
804
- include_raw: input.include_raw,
805
- }), { appId: input.app_id ?? input.apphud_app_id });
806
- return jsonResult(result);
807
- }
808
- catch (error) {
809
- return jsonResult(toToolError(error), true);
810
- }
811
- });
812
- server.tool("apphud_analytics_query_raw", "Low-level analytics query tool (value/timeseries/breakdown/raw)", {
813
- tenant_id: z.string().optional(),
814
- auth: authSchema,
815
- app_id: z.string().min(1).optional(),
816
- apphud_app_id: z.string().min(1).optional(),
817
- query: z.object({
818
- shape: z.enum(["value", "timeseries", "breakdown", "raw"]),
819
- metric_key: z.string().optional(),
820
- from: z.string().datetime().optional(),
821
- to: z.string().datetime().optional(),
822
- granularity: z.enum(["day", "week"]).optional(),
823
- dimension: z.string().optional(),
824
- endpoint_path: z.string().optional(),
825
- method: z.enum(["GET", "POST"]).optional(),
826
- query_params: z.record(z.string()).optional(),
827
- body: z.record(z.unknown()).optional(),
828
- filters: analyticsFiltersSchema,
829
- platform: analyticsPlatformSchema.optional(),
830
- limit: z.number().int().min(1).max(500).optional(),
831
- }),
832
- include_raw: z.boolean().optional(),
833
- }, async (input) => {
834
- const auth = resolveAuth(input, container.config);
835
- try {
836
- const result = await container.toolGuard.run(auth, "apphud_analytics_query_raw", async () => container.analyticsService.queryRaw(auth, {
837
- app_id: input.app_id,
838
- apphud_app_id: input.apphud_app_id,
839
- query: input.query,
840
- include_raw: input.include_raw,
841
- }), { appId: input.app_id ?? input.apphud_app_id });
842
- return jsonResult(result);
843
- }
844
- catch (error) {
845
- return jsonResult(toToolError(error), true);
846
- }
847
- });
14
+ version: "0.2.4",
15
+ });
16
+ for (const [toolName, definition] of getRemoteToolEntries()) {
17
+ server.tool(toolName, definition.description, definition.inputShape, async (input) => {
18
+ try {
19
+ const result = await executeRemoteTool(container, toolName, input);
20
+ return jsonResult(result);
21
+ }
22
+ catch (error) {
23
+ return jsonResult(toToolError(error), true);
24
+ }
25
+ });
26
+ }
848
27
  return server;
849
28
  }
850
29
  export async function startMcpStdioServer(container) {