Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ See [Vault payments](docs/vault-payments.md) for both provider flows, safety rul
- `webmcp` - List native page tools across every tab and frame in a browser, then synchronously invoke an exact opaque `tool_ref` with structured input.
- `exec_command` - Run shell commands inside a browser VM. Returns decoded stdout/stderr.
- `search_docs` - Search Kernel platform documentation and guides.
- `submit_feedback` - send product, mcp, or documentation feedback directly to the KERNEL team without interrupting the current task.
- `submit_feedback` - send product, bot-detection, config-registry, mcp, or documentation feedback directly to the KERNEL team without interrupting the current task. Config-registry reports connect the observed site outcome to the recommendation metadata and exact browser and proxy settings applied unchanged; general bot-detection reports remain available for outcomes not tied to a registry recommendation.
- `open_auth_login` - Open a secure interactive Managed Auth MCP App after user consent. Registered only for clients that declare MCP Apps support; credentials and MFA never enter MCP/model traffic.

## Resources
Expand Down
5 changes: 5 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"react": "^19.2.1",
"react-dom": "^19.2.1",
"redis": "^5.6.0",
"tldts": "^7.4.13",
"typescript": "^5"
},
"devDependencies": {
Expand Down
179 changes: 168 additions & 11 deletions src/lib/mcp/analytics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -613,12 +613,13 @@ describe("captureMcpFeedback", () => {
expect(captured).toEqual([
{
event: MCP_FEEDBACK_SUBMITTED_EVENT,
properties: {
properties: expect.objectContaining({
$groups: { organization: "org_analytics" },
feedback_summary: "Browser timeout guidance was unclear",
feedback_type: "product",
feedback_sentiment: "mixed",
feedback_product_area: "browsers",
feedback_destination: undefined,
feedback_category: undefined,
feedback_task_completed: true,
feedback_tools_used: ["manage_browsers"],
Expand All @@ -627,8 +628,153 @@ describe("captureMcpFeedback", () => {
"Include a retry interval in the response.",
feedback_user_request: undefined,
feedback_details: "The error linked to [url] for [email]",
}),
},
]);
});

test("routes structured bot-detection feedback to config registry prioritization", async () => {
const captured: unknown[] = [];
const analytics = {
capture: async (event: unknown) => {
captured.push(event);
},
} as McpAnalytics;

await captureMcpFeedback(
{
summary: "Stealth sessions were consistently blocked",
feedback_type: "bot_detection",
sentiment: "negative",
task_completed: false,
tools_used: ["manage_browsers", "execute_playwright_code"],
bot_detection: {
registrable_domain: "example.com",
observed_outcome: "blocked",
suspected_vendor: "Akamai Bot Manager",
challenge_type: "access_denied",
stealth: "enabled",
proxy_type: "isp",
region: "us-east",
browser_version: "152.0.7977.42",
browser_image_version: "2026.09.14",
reproducibility: "consistent",
browser_session_id: "session_123",
},
},
{
authInfo: {
extra: {
connectionContext: {
scope: { organizationId: "org_analytics" },
},
},
},
},
analytics,
);

expect(captured).toEqual([
{
event: MCP_FEEDBACK_SUBMITTED_EVENT,
properties: expect.objectContaining({
$groups: { organization: "org_analytics" },
feedback_type: "bot_detection",
feedback_destination: "config_registry_prioritization",
feedback_bot_detection_registrable_domain: "example.com",
feedback_bot_detection_observed_outcome: "blocked",
feedback_bot_detection_suspected_vendor: "Akamai Bot Manager",
feedback_bot_detection_challenge_type: "access_denied",
feedback_bot_detection_stealth: "enabled",
feedback_bot_detection_proxy_type: "isp",
feedback_bot_detection_region: "us-east",
feedback_bot_detection_browser_version: "152.0.7977.42",
feedback_bot_detection_browser_image_version: "2026.09.14",
feedback_bot_detection_reproducibility: "consistent",
feedback_bot_detection_browser_session_id: "session_123",
}),
},
]);
});

test("attributes config-registry feedback to the applied configuration", async () => {
const captured: unknown[] = [];
const analytics = {
capture: async (event: unknown) => {
captured.push(event);
},
} as McpAnalytics;

await captureMcpFeedback(
{
summary: "The recommended configuration remained blocked",
feedback_type: "config_registry",
sentiment: "negative",
task_completed: false,
bot_detection: {
registrable_domain: "example.com",
observed_outcome: "blocked",
challenge_type: "access_denied",
reproducibility: "consistent",
browser_session_id: "session_456",
},
config_registry: {
request_method: "resolve",
analysis_id: "analysis_123",
recommendation_match_scope: "exact",
recommendation_verification: "verified",
applied_browser: {
stealth: true,
headless: false,
gpu: false,
viewport: { width: 1920, height: 1080, refresh_rate: 25 },
},
applied_proxy: {
mode: "managed",
type: "residential",
country: "US",
},
},
},
{
authInfo: {
extra: {
connectionContext: {
scope: { organizationId: "org_analytics" },
},
},
},
},
analytics,
);

expect(captured).toEqual([
{
event: MCP_FEEDBACK_SUBMITTED_EVENT,
properties: expect.objectContaining({
$groups: { organization: "org_analytics" },
feedback_type: "config_registry",
feedback_destination: "config_registry_quality",
feedback_bot_detection_registrable_domain: "example.com",
feedback_bot_detection_observed_outcome: "blocked",
feedback_config_registry_request_method: "resolve",
feedback_config_registry_analysis_id: "analysis_123",
feedback_config_registry_recommendation_match_scope: "exact",
feedback_config_registry_recommendation_verification: "verified",
feedback_config_registry_applied_config_key:
"stealth-true|headless-false|gpu-false|viewport-1920x1080@25|proxy-managed-residential-US",
feedback_config_registry_browser_stealth: true,
feedback_config_registry_browser_headless: false,
feedback_config_registry_browser_gpu: false,
feedback_config_registry_viewport_width: 1920,
feedback_config_registry_viewport_height: 1080,
feedback_config_registry_viewport_refresh_rate: 25,
feedback_config_registry_proxy_mode: "managed",
feedback_config_registry_proxy_type: "residential",
feedback_config_registry_proxy_country: "US",
feedback_task_completed: false,
}),
},
]);
});
});
Expand Down Expand Up @@ -815,11 +961,17 @@ describe("instrumentMcpAnalytics (SDK integration)", () => {
name: KERNEL_FEEDBACK_TOOL_NAME,
arguments: {
context:
"Reporting that browser timeout guidance did not explain when the caller should retry.",
summary: "Browser timeout guidance was unclear",
feedback_type: "product",
sentiment: "mixed",
product_area: "browsers",
"Reporting a repeatable site block so the affected domain can be prioritized for a working browser configuration.",
summary: "Stealth sessions were consistently blocked",
feedback_type: "bot_detection",
sentiment: "negative",
task_completed: false,
bot_detection: {
registrable_domain: "example.com",
observed_outcome: "blocked",
suspected_vendor: "Akamai Bot Manager",
reproducibility: "consistent",
},
},
});

Expand All @@ -843,13 +995,18 @@ describe("instrumentMcpAnalytics (SDK integration)", () => {
[PostHogMCPAnalyticsProperty.ProtocolVersion]: "2025-03-26",
[PostHogMCPAnalyticsProperty.ServerName]: "test",
[PostHogMCPAnalyticsProperty.ServerVersion]: "0.0.0",
feedback_summary: "Browser timeout guidance was unclear",
feedback_type: "product",
feedback_sentiment: "mixed",
feedback_product_area: "browsers",
feedback_summary: "Stealth sessions were consistently blocked",
feedback_type: "bot_detection",
feedback_sentiment: "negative",
feedback_task_completed: false,
feedback_destination: "config_registry_prioritization",
feedback_bot_detection_registrable_domain: "example.com",
feedback_bot_detection_observed_outcome: "blocked",
feedback_bot_detection_suspected_vendor: "Akamai Bot Manager",
feedback_bot_detection_reproducibility: "consistent",
});
expect(toolCall.properties[PostHogMCPAnalyticsProperty.Intent]).toBe(
"Reporting that browser timeout guidance did not explain when the caller should retry.",
"Reporting a repeatable site block so the affected domain can be prioritized for a working browser configuration.",
);
});

Expand Down
111 changes: 111 additions & 0 deletions src/lib/mcp/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,32 @@ const SENT_PROPERTIES = new Set<string>([
"feedback_type",
"feedback_sentiment",
"feedback_product_area",
"feedback_destination",
"feedback_bot_detection_registrable_domain",
"feedback_bot_detection_observed_outcome",
"feedback_bot_detection_suspected_vendor",
"feedback_bot_detection_challenge_type",
"feedback_bot_detection_stealth",
"feedback_bot_detection_proxy_type",
"feedback_bot_detection_region",
"feedback_bot_detection_browser_version",
"feedback_bot_detection_browser_image_version",
"feedback_bot_detection_reproducibility",
"feedback_bot_detection_browser_session_id",
"feedback_config_registry_request_method",
"feedback_config_registry_analysis_id",
"feedback_config_registry_recommendation_match_scope",
"feedback_config_registry_recommendation_verification",
"feedback_config_registry_applied_config_key",
"feedback_config_registry_browser_stealth",
"feedback_config_registry_browser_headless",
"feedback_config_registry_browser_gpu",
"feedback_config_registry_viewport_width",
"feedback_config_registry_viewport_height",
"feedback_config_registry_viewport_refresh_rate",
"feedback_config_registry_proxy_mode",
"feedback_config_registry_proxy_type",
"feedback_config_registry_proxy_country",
"feedback_category",
"feedback_task_completed",
"feedback_tools_used",
Expand Down Expand Up @@ -512,18 +538,103 @@ export function captureMcpConnectionScopeFailure(
}
}

function configRegistryAppliedConfigKey(
configRegistry: NonNullable<KernelFeedback["config_registry"]>,
) {
const browser = configRegistry.applied_browser;
const viewport = browser.viewport;
const proxy = configRegistry.applied_proxy;
const proxyKey =
proxy.mode === "direct"
? "direct"
: `managed-${proxy.type}-${proxy.country ?? "default"}`;
return [
`stealth-${browser.stealth}`,
`headless-${browser.headless}`,
`gpu-${browser.gpu}`,
`viewport-${viewport.width}x${viewport.height}@${viewport.refresh_rate ?? "default"}`,
`proxy-${proxyKey}`,
].join("|");
}

export function captureMcpFeedback(
feedback: KernelFeedback,
extra: unknown,
analytics: McpAnalytics,
) {
const isSiteOutcome =
feedback.feedback_type === "bot_detection" ||
feedback.feedback_type === "config_registry";
const botDetection = isSiteOutcome ? feedback.bot_detection : undefined;
const configRegistry =
feedback.feedback_type === "config_registry"
? feedback.config_registry
: undefined;
return captureMcpCustomEvent(analytics, extra, MCP_FEEDBACK_SUBMITTED_EVENT, {
feedback_summary: redactAnalyticsText(feedback.summary),
feedback_type: feedback.feedback_type,
feedback_sentiment: feedback.sentiment,
feedback_product_area: feedback.product_area
? redactAnalyticsText(feedback.product_area)
: undefined,
feedback_destination: configRegistry
? "config_registry_quality"
: botDetection
? "config_registry_prioritization"
: undefined,
feedback_bot_detection_registrable_domain: botDetection?.registrable_domain,
feedback_bot_detection_observed_outcome: botDetection?.observed_outcome,
feedback_bot_detection_suspected_vendor: botDetection?.suspected_vendor
? redactAnalyticsText(botDetection.suspected_vendor)
: undefined,
feedback_bot_detection_challenge_type: botDetection?.challenge_type,
feedback_bot_detection_stealth: botDetection?.stealth,
feedback_bot_detection_proxy_type: botDetection?.proxy_type,
feedback_bot_detection_region: botDetection?.region
? redactAnalyticsText(botDetection.region)
: undefined,
feedback_bot_detection_browser_version: botDetection?.browser_version
? redactAnalyticsText(botDetection.browser_version)
: undefined,
feedback_bot_detection_browser_image_version:
botDetection?.browser_image_version
? redactAnalyticsText(botDetection.browser_image_version)
: undefined,
feedback_bot_detection_reproducibility: botDetection?.reproducibility,
feedback_bot_detection_browser_session_id: botDetection?.browser_session_id
? redactAnalyticsText(botDetection.browser_session_id)
: undefined,
feedback_config_registry_request_method: configRegistry?.request_method,
feedback_config_registry_analysis_id: configRegistry?.analysis_id
? redactAnalyticsText(configRegistry.analysis_id)
: undefined,
feedback_config_registry_recommendation_match_scope:
configRegistry?.recommendation_match_scope,
feedback_config_registry_recommendation_verification:
configRegistry?.recommendation_verification,
feedback_config_registry_applied_config_key: configRegistry
? configRegistryAppliedConfigKey(configRegistry)
: undefined,
feedback_config_registry_browser_stealth:
configRegistry?.applied_browser.stealth,
feedback_config_registry_browser_headless:
configRegistry?.applied_browser.headless,
feedback_config_registry_browser_gpu: configRegistry?.applied_browser.gpu,
feedback_config_registry_viewport_width:
configRegistry?.applied_browser.viewport.width,
feedback_config_registry_viewport_height:
configRegistry?.applied_browser.viewport.height,
feedback_config_registry_viewport_refresh_rate:
configRegistry?.applied_browser.viewport.refresh_rate,
feedback_config_registry_proxy_mode: configRegistry?.applied_proxy.mode,
feedback_config_registry_proxy_type:
configRegistry?.applied_proxy.mode === "managed"
? configRegistry.applied_proxy.type
: undefined,
feedback_config_registry_proxy_country:
configRegistry?.applied_proxy.mode === "managed"
? configRegistry.applied_proxy.country
: undefined,
feedback_category: feedback.category,
feedback_task_completed: feedback.task_completed,
feedback_tools_used: feedback.tools_used?.map(redactAnalyticsText),
Comment thread
masnwilliams marked this conversation as resolved.
Expand Down
Loading
Loading