@recapt/mcp 0.0.2-beta

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 (63) hide show
  1. package/dist/api/client.d.ts +12 -0
  2. package/dist/api/client.js +67 -0
  3. package/dist/index.d.ts +8 -0
  4. package/dist/index.js +217 -0
  5. package/dist/tools/analyzeFlow.d.ts +7 -0
  6. package/dist/tools/analyzeFlow.js +68 -0
  7. package/dist/tools/analyzeFunnel.d.ts +7 -0
  8. package/dist/tools/analyzeFunnel.js +63 -0
  9. package/dist/tools/compareCohorts.d.ts +6 -0
  10. package/dist/tools/compareCohorts.js +84 -0
  11. package/dist/tools/comparePeriods.d.ts +6 -0
  12. package/dist/tools/comparePeriods.js +54 -0
  13. package/dist/tools/detectDrift.d.ts +6 -0
  14. package/dist/tools/detectDrift.js +55 -0
  15. package/dist/tools/detectRegressions.d.ts +6 -0
  16. package/dist/tools/detectRegressions.js +46 -0
  17. package/dist/tools/discoverPersonas.d.ts +6 -0
  18. package/dist/tools/discoverPersonas.js +50 -0
  19. package/dist/tools/getActionableIssues.d.ts +7 -0
  20. package/dist/tools/getActionableIssues.js +55 -0
  21. package/dist/tools/getAnomalies.d.ts +6 -0
  22. package/dist/tools/getAnomalies.js +53 -0
  23. package/dist/tools/getConsoleErrors.d.ts +6 -0
  24. package/dist/tools/getConsoleErrors.js +61 -0
  25. package/dist/tools/getDeadClicks.d.ts +6 -0
  26. package/dist/tools/getDeadClicks.js +42 -0
  27. package/dist/tools/getDomains.d.ts +6 -0
  28. package/dist/tools/getDomains.js +34 -0
  29. package/dist/tools/getElementFriction.d.ts +6 -0
  30. package/dist/tools/getElementFriction.js +45 -0
  31. package/dist/tools/getFlowFriction.d.ts +7 -0
  32. package/dist/tools/getFlowFriction.js +57 -0
  33. package/dist/tools/getFormFriction.d.ts +6 -0
  34. package/dist/tools/getFormFriction.js +42 -0
  35. package/dist/tools/getIssues.d.ts +6 -0
  36. package/dist/tools/getIssues.js +82 -0
  37. package/dist/tools/getJourneyPatterns.d.ts +7 -0
  38. package/dist/tools/getJourneyPatterns.js +50 -0
  39. package/dist/tools/getPageMetrics.d.ts +6 -0
  40. package/dist/tools/getPageMetrics.js +47 -0
  41. package/dist/tools/getPageTrends.d.ts +6 -0
  42. package/dist/tools/getPageTrends.js +46 -0
  43. package/dist/tools/getSessionDetails.d.ts +6 -0
  44. package/dist/tools/getSessionDetails.js +70 -0
  45. package/dist/tools/getUxHealthReport.d.ts +7 -0
  46. package/dist/tools/getUxHealthReport.js +50 -0
  47. package/dist/tools/listPages.d.ts +6 -0
  48. package/dist/tools/listPages.js +50 -0
  49. package/dist/tools/listSessions.d.ts +7 -0
  50. package/dist/tools/listSessions.js +67 -0
  51. package/dist/tools/memory.d.ts +7 -0
  52. package/dist/tools/memory.js +119 -0
  53. package/dist/tools/predictOutcomes.d.ts +6 -0
  54. package/dist/tools/predictOutcomes.js +66 -0
  55. package/dist/tools/scanSite.d.ts +6 -0
  56. package/dist/tools/scanSite.js +51 -0
  57. package/dist/tools/searchSessions.d.ts +6 -0
  58. package/dist/tools/searchSessions.js +51 -0
  59. package/dist/tools/triageSessions.d.ts +8 -0
  60. package/dist/tools/triageSessions.js +195 -0
  61. package/dist/utils/orgContext.d.ts +6 -0
  62. package/dist/utils/orgContext.js +22 -0
  63. package/package.json +37 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * get_journey_patterns tool
3
+ *
4
+ * Discovers navigation patterns across sessions.
5
+ * Thin proxy to external-api /flows/patterns endpoint.
6
+ */
7
+ import { z } from "zod";
8
+ import { apiGet, isApiConfigured } from "../api/client.js";
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ export function registerGetJourneyPatterns(server) {
11
+ server.registerTool("get_journey_patterns", {
12
+ description: "Discover navigation patterns across sessions. Returns top page transitions, " +
13
+ "backtrack hotspots (pages users return to), and dropoff pages (where sessions end). " +
14
+ "Use this to understand organic user navigation.",
15
+ inputSchema: z.object({
16
+ page_path: z
17
+ .string()
18
+ .optional()
19
+ .describe("Filter to transitions involving this page (e.g., /pricing)"),
20
+ days: z
21
+ .number()
22
+ .optional()
23
+ .default(7)
24
+ .describe("Number of days to analyze (default: 7)"),
25
+ }),
26
+ }, async ({ page_path, days }) => {
27
+ if (!isApiConfigured()) {
28
+ return {
29
+ content: [
30
+ {
31
+ type: "text",
32
+ text: JSON.stringify({ error: "API not configured" }),
33
+ },
34
+ ],
35
+ isError: true,
36
+ };
37
+ }
38
+ const { data, error } = await apiGet("/flows/patterns", {
39
+ page_path,
40
+ days: days ?? 7,
41
+ });
42
+ if (error) {
43
+ return {
44
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
45
+ isError: true,
46
+ };
47
+ }
48
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
49
+ });
50
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * get_page_metrics tool
3
+ *
4
+ * Returns aggregated behavioral metrics for a specific page or all pages.
5
+ */
6
+ export declare function registerGetPageMetrics(server: any): void;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * get_page_metrics tool
3
+ *
4
+ * Returns aggregated behavioral metrics for a specific page or all pages.
5
+ */
6
+ import { z } from "zod";
7
+ import { apiGet, isApiConfigured } from "../api/client.js";
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ export function registerGetPageMetrics(server) {
10
+ server.registerTool("get_page_metrics", {
11
+ description: "Get aggregated behavioral metrics for a page. Returns frustration, confusion, confidence, energy scores, and health score. If page_path is omitted, returns metrics for all pages.",
12
+ inputSchema: z.object({
13
+ page_path: z
14
+ .string()
15
+ .optional()
16
+ .describe("Page path to get metrics for (e.g., /checkout). Omit to get all pages."),
17
+ days: z
18
+ .number()
19
+ .optional()
20
+ .default(7)
21
+ .describe("Number of days to look back (default: 7)"),
22
+ }),
23
+ }, async ({ page_path, days }) => {
24
+ if (!isApiConfigured()) {
25
+ return {
26
+ content: [
27
+ {
28
+ type: "text",
29
+ text: JSON.stringify({ error: "API not configured" }),
30
+ },
31
+ ],
32
+ isError: true,
33
+ };
34
+ }
35
+ const { data, error } = await apiGet("/pages", {
36
+ page_path,
37
+ days,
38
+ });
39
+ if (error) {
40
+ return {
41
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
42
+ isError: true,
43
+ };
44
+ }
45
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
46
+ });
47
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * get_page_trends tool
3
+ *
4
+ * Returns daily behavioral trends for a page.
5
+ */
6
+ export declare function registerGetPageTrends(server: any): void;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * get_page_trends tool
3
+ *
4
+ * Returns daily behavioral trends for a page.
5
+ */
6
+ import { z } from "zod";
7
+ import { apiGet, isApiConfigured } from "../api/client.js";
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ export function registerGetPageTrends(server) {
10
+ server.registerTool("get_page_trends", {
11
+ description: "Get daily behavioral trends for a page. Shows how frustration, confusion, and confidence change over time.",
12
+ inputSchema: z.object({
13
+ page_path: z
14
+ .string()
15
+ .describe("Page path to analyze (e.g., /checkout)"),
16
+ days: z
17
+ .number()
18
+ .optional()
19
+ .default(14)
20
+ .describe("Number of days to look back (default: 14)"),
21
+ }),
22
+ }, async ({ page_path, days }) => {
23
+ if (!isApiConfigured()) {
24
+ return {
25
+ content: [
26
+ {
27
+ type: "text",
28
+ text: JSON.stringify({ error: "API not configured" }),
29
+ },
30
+ ],
31
+ isError: true,
32
+ };
33
+ }
34
+ const { data, error } = await apiGet("/trends", {
35
+ page_path,
36
+ days: days ?? 14,
37
+ });
38
+ if (error) {
39
+ return {
40
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
41
+ isError: true,
42
+ };
43
+ }
44
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
45
+ });
46
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * get_session_details tool
3
+ *
4
+ * Returns behavioral timeline for one or more sessions.
5
+ */
6
+ export declare function registerGetSessionDetails(server: any): void;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * get_session_details tool
3
+ *
4
+ * Returns behavioral timeline for one or more sessions.
5
+ */
6
+ import { z } from "zod";
7
+ import { apiGet, apiPost, isApiConfigured } from "../api/client.js";
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ export function registerGetSessionDetails(server) {
10
+ server.registerTool("get_session_details", {
11
+ description: "Get behavioral timeline for one or more sessions. Shows how frustration, confusion, and confidence evolved over time. Accepts a single session_id or an array of session_ids (max 20).",
12
+ inputSchema: z.object({
13
+ session_id: z
14
+ .string()
15
+ .optional()
16
+ .describe("Single session ID to get details for"),
17
+ session_ids: z
18
+ .array(z.string())
19
+ .max(20)
20
+ .optional()
21
+ .describe("Array of session IDs to get details for (max 20)"),
22
+ }),
23
+ }, async ({ session_id, session_ids, }) => {
24
+ if (!isApiConfigured()) {
25
+ return {
26
+ content: [
27
+ {
28
+ type: "text",
29
+ text: JSON.stringify({ error: "API not configured" }),
30
+ },
31
+ ],
32
+ isError: true,
33
+ };
34
+ }
35
+ if (!session_id && (!session_ids || session_ids.length === 0)) {
36
+ return {
37
+ content: [
38
+ {
39
+ type: "text",
40
+ text: JSON.stringify({
41
+ error: "Either session_id or session_ids must be provided",
42
+ }),
43
+ },
44
+ ],
45
+ isError: true,
46
+ };
47
+ }
48
+ if (session_id && !session_ids) {
49
+ const { data, error } = await apiGet(`/sessions/${session_id}`);
50
+ if (error) {
51
+ return {
52
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
53
+ isError: true,
54
+ };
55
+ }
56
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
57
+ }
58
+ const ids = session_ids ?? [session_id];
59
+ const { data, error } = await apiPost("/sessions/details", {
60
+ session_ids: ids,
61
+ });
62
+ if (error) {
63
+ return {
64
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
65
+ isError: true,
66
+ };
67
+ }
68
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
69
+ });
70
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * get_ux_health_report tool
3
+ *
4
+ * Returns a comprehensive UX health report for the website or a specific page.
5
+ * Thin proxy to external-api /health-report endpoint.
6
+ */
7
+ export declare function registerGetUxHealthReport(server: any): void;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * get_ux_health_report tool
3
+ *
4
+ * Returns a comprehensive UX health report for the website or a specific page.
5
+ * Thin proxy to external-api /health-report endpoint.
6
+ */
7
+ import { z } from "zod";
8
+ import { apiGet, isApiConfigured } from "../api/client.js";
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ export function registerGetUxHealthReport(server) {
11
+ server.registerTool("get_ux_health_report", {
12
+ description: "Get a comprehensive UX health report combining page metrics, issues, and anomalies. " +
13
+ "Returns overall health score, per-page breakdown, active issues, and frustration spikes. " +
14
+ "Use this as a starting point to understand overall UX state before diving deeper.",
15
+ inputSchema: z.object({
16
+ page_path: z
17
+ .string()
18
+ .optional()
19
+ .describe("Focus on a specific page (omit for site-wide report)"),
20
+ days: z
21
+ .number()
22
+ .optional()
23
+ .default(7)
24
+ .describe("Number of days to analyze (default: 7)"),
25
+ }),
26
+ }, async ({ page_path, days }) => {
27
+ if (!isApiConfigured()) {
28
+ return {
29
+ content: [
30
+ {
31
+ type: "text",
32
+ text: JSON.stringify({ error: "API not configured" }),
33
+ },
34
+ ],
35
+ isError: true,
36
+ };
37
+ }
38
+ const { data, error } = await apiGet("/health-report", {
39
+ page_path,
40
+ days: days ?? 7,
41
+ });
42
+ if (error) {
43
+ return {
44
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
45
+ isError: true,
46
+ };
47
+ }
48
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
49
+ });
50
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * list_pages tool
3
+ *
4
+ * List all tracked pages with basic metrics.
5
+ */
6
+ export declare function registerListPages(server: any): void;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * list_pages tool
3
+ *
4
+ * List all tracked pages with basic metrics.
5
+ */
6
+ import { z } from "zod";
7
+ import { apiGet, isApiConfigured } from "../api/client.js";
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ export function registerListPages(server) {
10
+ server.registerTool("list_pages", {
11
+ description: "List all tracked pages with basic metrics. " +
12
+ "Returns page paths sorted by session count with frustration and health grade. " +
13
+ "Use this to discover what pages are being tracked before diving into specific pages.",
14
+ inputSchema: z.object({
15
+ days: z
16
+ .number()
17
+ .optional()
18
+ .default(7)
19
+ .describe("Number of days to look back (default 7)"),
20
+ limit: z
21
+ .number()
22
+ .optional()
23
+ .default(50)
24
+ .describe("Maximum number of pages to return (default 50)"),
25
+ }),
26
+ }, async ({ days, limit }) => {
27
+ if (!isApiConfigured()) {
28
+ return {
29
+ content: [
30
+ {
31
+ type: "text",
32
+ text: JSON.stringify({ error: "API not configured" }),
33
+ },
34
+ ],
35
+ isError: true,
36
+ };
37
+ }
38
+ const { data, error } = await apiGet("/pages/list", {
39
+ days: days ?? 7,
40
+ limit: limit ?? 50,
41
+ });
42
+ if (error) {
43
+ return {
44
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
45
+ isError: true,
46
+ };
47
+ }
48
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
49
+ });
50
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * list_sessions tool
3
+ *
4
+ * Lists and filters recorded sessions.
5
+ * Thin proxy to external-api /sessions endpoint.
6
+ */
7
+ export declare function registerListSessions(server: any): void;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * list_sessions tool
3
+ *
4
+ * Lists and filters recorded sessions.
5
+ * Thin proxy to external-api /sessions endpoint.
6
+ */
7
+ import { z } from "zod";
8
+ import { apiGet, isApiConfigured } from "../api/client.js";
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ export function registerListSessions(server) {
11
+ server.registerTool("list_sessions", {
12
+ description: "List and filter recorded sessions. Returns session metadata including status, " +
13
+ "duration, device, browser, and domains. Use to find sessions for a domain, " +
14
+ "check for active sessions, or browse by device type.",
15
+ inputSchema: z.object({
16
+ domain: z
17
+ .string()
18
+ .optional()
19
+ .describe("Filter by domain name (partial match supported)"),
20
+ status: z
21
+ .enum(["active", "terminated", "all"])
22
+ .optional()
23
+ .default("all")
24
+ .describe("Filter by session status"),
25
+ device: z
26
+ .enum(["desktop", "mobile", "tablet"])
27
+ .optional()
28
+ .describe("Filter by device type"),
29
+ days: z
30
+ .number()
31
+ .optional()
32
+ .default(7)
33
+ .describe("Number of days to look back (default: 7)"),
34
+ limit: z
35
+ .number()
36
+ .optional()
37
+ .default(20)
38
+ .describe("Maximum sessions to return (default: 20, max: 200)"),
39
+ }),
40
+ }, async ({ domain, status, device, days, limit, }) => {
41
+ if (!isApiConfigured()) {
42
+ return {
43
+ content: [
44
+ {
45
+ type: "text",
46
+ text: JSON.stringify({ error: "API not configured" }),
47
+ },
48
+ ],
49
+ isError: true,
50
+ };
51
+ }
52
+ const { data, error } = await apiGet("/sessions", {
53
+ domain,
54
+ status: status === "all" ? undefined : status,
55
+ device,
56
+ days: days ?? 7,
57
+ limit: limit ?? 20,
58
+ });
59
+ if (error) {
60
+ return {
61
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
62
+ isError: true,
63
+ };
64
+ }
65
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
66
+ });
67
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Memory management tools for MCP sessions.
3
+ *
4
+ * Provides working memory for AI agents to store intermediate results
5
+ * and query across stored data without re-fetching.
6
+ */
7
+ export declare function registerMemoryTools(server: any): void;
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Memory management tools for MCP sessions.
3
+ *
4
+ * Provides working memory for AI agents to store intermediate results
5
+ * and query across stored data without re-fetching.
6
+ */
7
+ import { z } from "zod";
8
+ const memoryStore = new Map();
9
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
10
+ export function registerMemoryTools(server) {
11
+ server.registerTool("memory_save", {
12
+ description: "Save a value to working memory for later retrieval. " +
13
+ "Use this to store intermediate results from tool calls that you want to reference later.",
14
+ inputSchema: z.object({
15
+ key: z.string().describe("Unique key to store the value under"),
16
+ value: z.string().describe("Value to store (will be stored as string)"),
17
+ annotation: z
18
+ .string()
19
+ .optional()
20
+ .describe("Optional note about what this data represents"),
21
+ }),
22
+ }, async ({ key, value, annotation, }) => {
23
+ memoryStore.set(key, {
24
+ key,
25
+ value,
26
+ timestamp: Date.now(),
27
+ annotation,
28
+ });
29
+ return {
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: JSON.stringify({ success: true, key, size: value.length }),
34
+ },
35
+ ],
36
+ };
37
+ });
38
+ server.registerTool("memory_recall", {
39
+ description: "Retrieve a value from working memory by key. " +
40
+ "Use this to access data you previously stored with memory_save.",
41
+ inputSchema: z.object({
42
+ key: z.string().describe("Key to retrieve"),
43
+ }),
44
+ }, async ({ key }) => {
45
+ const entry = memoryStore.get(key);
46
+ if (!entry) {
47
+ return {
48
+ content: [
49
+ {
50
+ type: "text",
51
+ text: JSON.stringify({
52
+ error: `Key "${key}" not found in memory`,
53
+ }),
54
+ },
55
+ ],
56
+ isError: true,
57
+ };
58
+ }
59
+ return {
60
+ content: [
61
+ {
62
+ type: "text",
63
+ text: entry.value,
64
+ },
65
+ ],
66
+ };
67
+ });
68
+ server.registerTool("memory_list", {
69
+ description: "List all keys currently stored in working memory. " +
70
+ "Returns key names, sizes, timestamps, and annotations.",
71
+ inputSchema: z.object({}),
72
+ }, async () => {
73
+ const entries = [...memoryStore.values()].map((entry) => ({
74
+ key: entry.key,
75
+ size: entry.value.length,
76
+ timestamp: new Date(entry.timestamp).toISOString(),
77
+ annotation: entry.annotation,
78
+ }));
79
+ return {
80
+ content: [
81
+ {
82
+ type: "text",
83
+ text: JSON.stringify({ count: entries.length, entries }),
84
+ },
85
+ ],
86
+ };
87
+ });
88
+ server.registerTool("memory_delete", {
89
+ description: "Delete a value from working memory by key.",
90
+ inputSchema: z.object({
91
+ key: z.string().describe("Key to delete"),
92
+ }),
93
+ }, async ({ key }) => {
94
+ const existed = memoryStore.delete(key);
95
+ return {
96
+ content: [
97
+ {
98
+ type: "text",
99
+ text: JSON.stringify({ success: true, deleted: existed }),
100
+ },
101
+ ],
102
+ };
103
+ });
104
+ server.registerTool("memory_clear", {
105
+ description: "Clear all values from working memory. Use with caution.",
106
+ inputSchema: z.object({}),
107
+ }, async () => {
108
+ const count = memoryStore.size;
109
+ memoryStore.clear();
110
+ return {
111
+ content: [
112
+ {
113
+ type: "text",
114
+ text: JSON.stringify({ success: true, cleared: count }),
115
+ },
116
+ ],
117
+ };
118
+ });
119
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * predict_outcomes tool
3
+ *
4
+ * Predict session outcomes based on behavioral features.
5
+ */
6
+ export declare function registerPredictOutcomes(server: any): void;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * predict_outcomes tool
3
+ *
4
+ * Predict session outcomes based on behavioral features.
5
+ */
6
+ import { z } from "zod";
7
+ import { apiPost, isApiConfigured } from "../api/client.js";
8
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
+ export function registerPredictOutcomes(server) {
10
+ server.registerTool("predict_outcomes", {
11
+ description: "Predict session outcomes based on early behavioral signals. " +
12
+ "Provide either a session_id to analyze an existing session, or behavioral_features " +
13
+ "to predict outcomes for hypothetical scenarios. " +
14
+ "Returns predicted outcome (COMPLETED, STRUGGLED, BLOCKED, DISENGAGED) with confidence.",
15
+ inputSchema: z.object({
16
+ session_id: z
17
+ .string()
18
+ .optional()
19
+ .describe("Session ID to analyze and predict outcome for"),
20
+ behavioral_features: z
21
+ .object({
22
+ frustration: z.number().describe("Frustration score (0-1)"),
23
+ confusion: z.number().describe("Confusion score (0-1)"),
24
+ confidence: z.number().describe("Confidence score (0-1)"),
25
+ })
26
+ .optional()
27
+ .describe("Behavioral features to use for prediction"),
28
+ }),
29
+ }, async ({ session_id, behavioral_features, }) => {
30
+ if (!isApiConfigured()) {
31
+ return {
32
+ content: [
33
+ {
34
+ type: "text",
35
+ text: JSON.stringify({ error: "API not configured" }),
36
+ },
37
+ ],
38
+ isError: true,
39
+ };
40
+ }
41
+ if (!session_id && !behavioral_features) {
42
+ return {
43
+ content: [
44
+ {
45
+ type: "text",
46
+ text: JSON.stringify({
47
+ error: "Either session_id or behavioral_features is required",
48
+ }),
49
+ },
50
+ ],
51
+ isError: true,
52
+ };
53
+ }
54
+ const { data, error } = await apiPost("/predict", {
55
+ session_id,
56
+ behavioral_features,
57
+ });
58
+ if (error) {
59
+ return {
60
+ content: [{ type: "text", text: JSON.stringify({ error }) }],
61
+ isError: true,
62
+ };
63
+ }
64
+ return { content: [{ type: "text", text: JSON.stringify(data) }] };
65
+ });
66
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * scan_site tool
3
+ *
4
+ * One-shot site health scan across all pages.
5
+ */
6
+ export declare function registerScanSite(server: any): void;