cbrowser 18.78.0 → 18.80.0
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/analysis/accessibility-empathy.d.ts.map +1 -1
- package/dist/analysis/accessibility-empathy.js +395 -66
- package/dist/analysis/accessibility-empathy.js.map +1 -1
- package/dist/analysis/agent-ready-audit.d.ts.map +1 -1
- package/dist/analysis/agent-ready-audit.js +78 -0
- package/dist/analysis/agent-ready-audit.js.map +1 -1
- package/dist/analysis/page-understanding.d.ts +139 -1
- package/dist/analysis/page-understanding.d.ts.map +1 -1
- package/dist/analysis/page-understanding.js +179 -12
- package/dist/analysis/page-understanding.js.map +1 -1
- package/dist/artifact-store.d.ts +19 -5
- package/dist/artifact-store.d.ts.map +1 -1
- package/dist/artifact-store.js +41 -11
- package/dist/artifact-store.js.map +1 -1
- package/dist/browser.d.ts +9 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +81 -5
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +55 -10
- package/dist/cli.js.map +1 -1
- package/dist/cognitive/index.d.ts.map +1 -1
- package/dist/cognitive/index.js +3 -2
- package/dist/cognitive/index.js.map +1 -1
- package/dist/config.d.ts +57 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +234 -7
- package/dist/config.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server-remote.d.ts.map +1 -1
- package/dist/mcp-server-remote.js +108 -4
- package/dist/mcp-server-remote.js.map +1 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +62 -938
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-tools/account-personas.d.ts +41 -0
- package/dist/mcp-tools/account-personas.d.ts.map +1 -0
- package/dist/mcp-tools/account-personas.js +98 -0
- package/dist/mcp-tools/account-personas.js.map +1 -0
- package/dist/mcp-tools/base/analysis-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/analysis-tools.js +12 -2
- package/dist/mcp-tools/base/analysis-tools.js.map +1 -1
- package/dist/mcp-tools/base/artifact-tools.d.ts +3 -0
- package/dist/mcp-tools/base/artifact-tools.d.ts.map +1 -0
- package/dist/mcp-tools/base/artifact-tools.js +78 -0
- package/dist/mcp-tools/base/artifact-tools.js.map +1 -0
- package/dist/mcp-tools/base/audit-tools.d.ts +11 -0
- package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/audit-tools.js +595 -340
- package/dist/mcp-tools/base/audit-tools.js.map +1 -1
- package/dist/mcp-tools/base/browser-management-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/browser-management-tools.js +18 -0
- package/dist/mcp-tools/base/browser-management-tools.js.map +1 -1
- package/dist/mcp-tools/base/bug-analysis-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/bug-analysis-tools.js +59 -3
- package/dist/mcp-tools/base/bug-analysis-tools.js.map +1 -1
- package/dist/mcp-tools/base/capture-tools.d.ts +37 -0
- package/dist/mcp-tools/base/capture-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/capture-tools.js +267 -6
- package/dist/mcp-tools/base/capture-tools.js.map +1 -1
- package/dist/mcp-tools/base/cognitive-tools.d.ts +12 -0
- package/dist/mcp-tools/base/cognitive-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/cognitive-tools.js +63 -15
- package/dist/mcp-tools/base/cognitive-tools.js.map +1 -1
- package/dist/mcp-tools/base/extraction-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/extraction-tools.js +33 -2
- package/dist/mcp-tools/base/extraction-tools.js.map +1 -1
- package/dist/mcp-tools/base/index.d.ts +2 -0
- package/dist/mcp-tools/base/index.d.ts.map +1 -1
- package/dist/mcp-tools/base/index.js +9 -0
- package/dist/mcp-tools/base/index.js.map +1 -1
- package/dist/mcp-tools/base/marketing-tools.js +3 -3
- package/dist/mcp-tools/base/marketing-tools.js.map +1 -1
- package/dist/mcp-tools/base/persona-comparison-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/persona-comparison-tools.js +529 -40
- package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
- package/dist/mcp-tools/base/site-knowledge-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/site-knowledge-tools.js +36 -3
- package/dist/mcp-tools/base/site-knowledge-tools.js.map +1 -1
- package/dist/mcp-tools/base/values-tools.d.ts +113 -0
- package/dist/mcp-tools/base/values-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/values-tools.js +868 -78
- package/dist/mcp-tools/base/values-tools.js.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.js +130 -10
- package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
- package/dist/mcp-tools/index.d.ts +3 -1
- package/dist/mcp-tools/index.d.ts.map +1 -1
- package/dist/mcp-tools/index.js +3 -28
- package/dist/mcp-tools/index.js.map +1 -1
- package/dist/mcp-tools/persona-creation-tools.d.ts.map +1 -1
- package/dist/mcp-tools/persona-creation-tools.js +363 -20
- package/dist/mcp-tools/persona-creation-tools.js.map +1 -1
- package/dist/mcp-tools/persona-lifecycle-tools.d.ts +3 -0
- package/dist/mcp-tools/persona-lifecycle-tools.d.ts.map +1 -0
- package/dist/mcp-tools/persona-lifecycle-tools.js +406 -0
- package/dist/mcp-tools/persona-lifecycle-tools.js.map +1 -0
- package/dist/mcp-tools/screenshot-utils.d.ts.map +1 -1
- package/dist/mcp-tools/screenshot-utils.js +56 -10
- package/dist/mcp-tools/screenshot-utils.js.map +1 -1
- package/dist/mcp-tools/tier-gate.js +2 -2
- package/dist/mcp-tools/tier-gate.js.map +1 -1
- package/dist/mcp-tools/tool-categories.d.ts.map +1 -1
- package/dist/mcp-tools/tool-categories.js +4 -1
- package/dist/mcp-tools/tool-categories.js.map +1 -1
- package/dist/mcp-tools/ui-resources.d.ts +167 -0
- package/dist/mcp-tools/ui-resources.d.ts.map +1 -0
- package/dist/mcp-tools/ui-resources.js +707 -0
- package/dist/mcp-tools/ui-resources.js.map +1 -0
- package/dist/mcp-tools/widget-kit.d.ts +299 -0
- package/dist/mcp-tools/widget-kit.d.ts.map +1 -0
- package/dist/mcp-tools/widget-kit.js +2034 -0
- package/dist/mcp-tools/widget-kit.js.map +1 -0
- package/dist/mcp-ui-resources.d.ts.map +1 -1
- package/dist/mcp-ui-resources.js +14 -4
- package/dist/mcp-ui-resources.js.map +1 -1
- package/dist/persona-questionnaire.d.ts +69 -1
- package/dist/persona-questionnaire.d.ts.map +1 -1
- package/dist/persona-questionnaire.js +177 -76
- package/dist/persona-questionnaire.js.map +1 -1
- package/dist/persona-scope.d.ts +20 -0
- package/dist/persona-scope.d.ts.map +1 -0
- package/dist/persona-scope.js +59 -0
- package/dist/persona-scope.js.map +1 -0
- package/dist/personas.d.ts +51 -17
- package/dist/personas.d.ts.map +1 -1
- package/dist/personas.js +947 -286
- package/dist/personas.js.map +1 -1
- package/dist/recording/capture-player.d.ts +68 -0
- package/dist/recording/capture-player.d.ts.map +1 -0
- package/dist/recording/capture-player.js +298 -0
- package/dist/recording/capture-player.js.map +1 -0
- package/dist/recording/engine.d.ts +52 -0
- package/dist/recording/engine.d.ts.map +1 -1
- package/dist/recording/engine.js +241 -3
- package/dist/recording/engine.js.map +1 -1
- package/dist/recording/inline-player.d.ts +39 -0
- package/dist/recording/inline-player.d.ts.map +1 -0
- package/dist/recording/inline-player.js +272 -0
- package/dist/recording/inline-player.js.map +1 -0
- package/dist/recording/saliency-overlay.d.ts +133 -0
- package/dist/recording/saliency-overlay.d.ts.map +1 -0
- package/dist/recording/saliency-overlay.js +360 -0
- package/dist/recording/saliency-overlay.js.map +1 -0
- package/dist/recording/types.d.ts +32 -0
- package/dist/recording/types.d.ts.map +1 -1
- package/dist/recording/types.js +46 -0
- package/dist/recording/types.js.map +1 -1
- package/dist/site-model/manager.d.ts +20 -0
- package/dist/site-model/manager.d.ts.map +1 -1
- package/dist/site-model/manager.js +52 -0
- package/dist/site-model/manager.js.map +1 -1
- package/dist/trait-reference.d.ts +26 -2
- package/dist/trait-reference.d.ts.map +1 -1
- package/dist/trait-reference.js +129 -19
- package/dist/trait-reference.js.map +1 -1
- package/dist/types.d.ts +105 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/url-resolution.d.ts +58 -0
- package/dist/url-resolution.d.ts.map +1 -0
- package/dist/url-resolution.js +143 -0
- package/dist/url-resolution.js.map +1 -0
- package/dist/values/big-five-inference.d.ts +121 -0
- package/dist/values/big-five-inference.d.ts.map +1 -0
- package/dist/values/big-five-inference.js +241 -0
- package/dist/values/big-five-inference.js.map +1 -0
- package/dist/values/big-five-values.d.ts +76 -0
- package/dist/values/big-five-values.d.ts.map +1 -0
- package/dist/values/big-five-values.js +152 -0
- package/dist/values/big-five-values.js.map +1 -0
- package/dist/values/index.d.ts +1 -1
- package/dist/values/index.d.ts.map +1 -1
- package/dist/values/index.js +1 -1
- package/dist/values/index.js.map +1 -1
- package/dist/values/persona-completeness.d.ts +91 -0
- package/dist/values/persona-completeness.d.ts.map +1 -0
- package/dist/values/persona-completeness.js +114 -0
- package/dist/values/persona-completeness.js.map +1 -0
- package/dist/values/persona-diff.d.ts +50 -0
- package/dist/values/persona-diff.d.ts.map +1 -0
- package/dist/values/persona-diff.js +126 -0
- package/dist/values/persona-diff.js.map +1 -0
- package/dist/values/persona-values.d.ts +16 -0
- package/dist/values/persona-values.d.ts.map +1 -1
- package/dist/values/persona-values.js +33 -0
- package/dist/values/persona-values.js.map +1 -1
- package/dist/values/schwartz-values.d.ts +9 -1
- package/dist/values/schwartz-values.d.ts.map +1 -1
- package/dist/values/schwartz-values.js +10 -2
- package/dist/values/schwartz-values.js.map +1 -1
- package/dist/values/value-mappings.d.ts +41 -2
- package/dist/values/value-mappings.d.ts.map +1 -1
- package/dist/values/value-mappings.js +65 -8
- package/dist/values/value-mappings.js.map +1 -1
- package/dist/visual/attention-quality.d.ts +27 -0
- package/dist/visual/attention-quality.d.ts.map +1 -1
- package/dist/visual/attention-quality.js +164 -2
- package/dist/visual/attention-quality.js.map +1 -1
- package/dist/visual/attention-transport.d.ts +41 -2
- package/dist/visual/attention-transport.d.ts.map +1 -1
- package/dist/visual/attention-transport.js +98 -26
- package/dist/visual/attention-transport.js.map +1 -1
- package/dist/visual/barrier-overlay-html.d.ts +10 -0
- package/dist/visual/barrier-overlay-html.d.ts.map +1 -1
- package/dist/visual/barrier-overlay-html.js.map +1 -1
- package/dist/visual/cognitive-models.d.ts +109 -13
- package/dist/visual/cognitive-models.d.ts.map +1 -1
- package/dist/visual/cognitive-models.js +166 -3
- package/dist/visual/cognitive-models.js.map +1 -1
- package/dist/visual/cognitive-transport-chain.d.ts +149 -5
- package/dist/visual/cognitive-transport-chain.d.ts.map +1 -1
- package/dist/visual/cognitive-transport-chain.js +558 -30
- package/dist/visual/cognitive-transport-chain.js.map +1 -1
- package/dist/visual/cognitive-transport.d.ts +45 -3
- package/dist/visual/cognitive-transport.d.ts.map +1 -1
- package/dist/visual/cognitive-transport.js +126 -12
- package/dist/visual/cognitive-transport.js.map +1 -1
- package/dist/visual/fixation-corpus.d.ts +52 -0
- package/dist/visual/fixation-corpus.d.ts.map +1 -1
- package/dist/visual/fixation-corpus.js +95 -0
- package/dist/visual/fixation-corpus.js.map +1 -1
- package/dist/visual/llm-relevance.d.ts +193 -0
- package/dist/visual/llm-relevance.d.ts.map +1 -0
- package/dist/visual/llm-relevance.js +480 -0
- package/dist/visual/llm-relevance.js.map +1 -0
- package/dist/visual/perceptual-transport.d.ts +60 -0
- package/dist/visual/perceptual-transport.d.ts.map +1 -1
- package/dist/visual/perceptual-transport.js +228 -19
- package/dist/visual/perceptual-transport.js.map +1 -1
- package/dist/visual/persona-context.d.ts +23 -0
- package/dist/visual/persona-context.d.ts.map +1 -0
- package/dist/visual/persona-context.js +44 -0
- package/dist/visual/persona-context.js.map +1 -0
- package/package.json +2 -1
package/dist/mcp-server.js
CHANGED
|
@@ -12,33 +12,36 @@
|
|
|
12
12
|
* Or: npx cbrowser mcp-server
|
|
13
13
|
*/
|
|
14
14
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
15
|
-
import { PERSONA_CATEGORIES } from "./persona-questionnaire.js";
|
|
16
15
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
17
16
|
import { z } from "zod";
|
|
18
17
|
import { CBrowser } from "./browser.js";
|
|
19
18
|
import { ensureDirectories, getStatusInfo } from "./config.js";
|
|
20
19
|
// Screen capture tools — implementation shared with the remote MCP server
|
|
21
20
|
import { startCapture, stopCapture, captureStatus, CAPTURE_START_DESCRIPTION, CAPTURE_STOP_DESCRIPTION, CAPTURE_STATUS_DESCRIPTION, } from "./mcp-tools/base/capture-tools.js";
|
|
21
|
+
import { registerEmpathyAuditTool } from "./mcp-tools/base/audit-tools.js";
|
|
22
|
+
import { registerValuesTools } from "./mcp-tools/base/values-tools.js";
|
|
23
|
+
import { registerPersonaComparisonTools } from "./mcp-tools/base/persona-comparison-tools.js";
|
|
24
|
+
import { registerPersonaCreationTools } from "./mcp-tools/persona-creation-tools.js";
|
|
25
|
+
import { registerPersonaLifecycleTools } from "./mcp-tools/persona-lifecycle-tools.js";
|
|
26
|
+
import { registerUiResources } from "./mcp-tools/ui-resources.js";
|
|
22
27
|
import { applySecurityLayer } from "./mcp-tools/security-layer.js";
|
|
23
28
|
// Visual module imports
|
|
24
29
|
import { runVisualRegression, runCrossBrowserTest, runResponsiveTest, runABComparison, crossBrowserDiff, captureVisualBaseline, listVisualBaselines, } from "./visual/index.js";
|
|
25
30
|
// Testing module imports
|
|
26
31
|
import { runNLTestSuite, parseNLTestSuite, dryRunNLTestSuite, repairTest, detectFlakyTests, generateCoverageMap, } from "./testing/index.js";
|
|
27
32
|
// Analysis module imports
|
|
28
|
-
import { huntBugs, runChaosTest,
|
|
33
|
+
import { huntBugs, runChaosTest, findElementByIntent, runAgentReadyAudit, runCompetitiveBenchmark, } from "./analysis/index.js";
|
|
29
34
|
import { listAccessibilityPersonas, getAccessibilityPersona } from "./personas.js";
|
|
30
35
|
// Persona imports for cognitive journey
|
|
31
|
-
import { getPersona, getAnyPersona, listPersonas, getCognitiveProfile, createCognitivePersona,
|
|
36
|
+
import { getPersona, getAnyPersona, listPersonas, getCognitiveProfile, createCognitivePersona, listEmotionalPersonas, getEmotionalPersona, isAgentPersonaObject, } from "./personas.js";
|
|
32
37
|
// Emotional state functions (v13.1.0)
|
|
33
38
|
import { createInitialEmotionalState, createEmotionalConfig, applyEmotionalTrigger, describeEmotionalState, shouldConsiderAbandonment, calculateAbandonmentModifier, calculateExplorationTendency, calculateDecisionSpeedModifier, } from "./cognitive/emotions.js";
|
|
34
39
|
// Performance module imports
|
|
35
40
|
import { capturePerformanceBaseline, detectPerformanceRegression, listPerformanceBaselines, } from "./performance/index.js";
|
|
36
41
|
// Values system (Schwartz's 10 Universal Values)
|
|
37
|
-
import {
|
|
42
|
+
import { resolveValuesForPersona, rankInfluencePatternsForProfile, } from "./values/index.js";
|
|
38
43
|
// Version from package.json - single source of truth
|
|
39
44
|
import { VERSION } from "./version.js";
|
|
40
|
-
// Persona questionnaire imports
|
|
41
|
-
import { generatePersonaQuestionnaire, buildTraitsFromAnswers, TRAIT_REFERENCE_MATRIX, deriveValuesFromTraits, } from "./persona-questionnaire.js";
|
|
42
45
|
// Security tools (mcp-guardian)
|
|
43
46
|
import { securityAuditHandler, } from "mcp-guardian";
|
|
44
47
|
// Shared browser instance
|
|
@@ -277,7 +280,7 @@ function getTraitHeader(trait) {
|
|
|
277
280
|
timeHorizon: "Time Focus", attributionStyle: "Attribution", metacognitivePlanning: "Planning",
|
|
278
281
|
proceduralFluency: "Procedures", transferLearning: "Transfer", authoritySensitivity: "Authority",
|
|
279
282
|
emotionalContagion: "Emotional", fearOfMissingOut: "FOMO", socialProofSensitivity: "Social Proof",
|
|
280
|
-
|
|
283
|
+
mentalModelFlexibility: "Flexibility",
|
|
281
284
|
};
|
|
282
285
|
return headers[trait] || trait;
|
|
283
286
|
}
|
|
@@ -1415,57 +1418,6 @@ async function registerCBrowserTools() {
|
|
|
1415
1418
|
};
|
|
1416
1419
|
}
|
|
1417
1420
|
});
|
|
1418
|
-
server.tool("compare_personas", "Compare how different user personas experience a journey. REQUIRES API KEY for internal simulation. For API-free usage over remote MCP, use compare_personas_init + browser tools + compare_personas_record_result + compare_personas_summarize instead.", {
|
|
1419
|
-
url: z.string().url().describe("Starting URL"),
|
|
1420
|
-
goal: z.string().describe("Goal to accomplish"),
|
|
1421
|
-
personas: z.array(z.string()).describe("Persona names to compare"),
|
|
1422
|
-
}, async ({ url, goal, personas }) => {
|
|
1423
|
-
try {
|
|
1424
|
-
const result = await comparePersonas({
|
|
1425
|
-
startUrl: url,
|
|
1426
|
-
goal,
|
|
1427
|
-
personas,
|
|
1428
|
-
});
|
|
1429
|
-
return {
|
|
1430
|
-
content: [
|
|
1431
|
-
{
|
|
1432
|
-
type: "text",
|
|
1433
|
-
text: JSON.stringify({
|
|
1434
|
-
url: result.url,
|
|
1435
|
-
goal: result.goal,
|
|
1436
|
-
personasCompared: result.personas.length,
|
|
1437
|
-
summary: result.summary,
|
|
1438
|
-
}, null, 2),
|
|
1439
|
-
},
|
|
1440
|
-
],
|
|
1441
|
-
};
|
|
1442
|
-
}
|
|
1443
|
-
catch (error) {
|
|
1444
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1445
|
-
if (errorMessage.includes("API key")) {
|
|
1446
|
-
return {
|
|
1447
|
-
content: [
|
|
1448
|
-
{
|
|
1449
|
-
type: "text",
|
|
1450
|
-
text: JSON.stringify({
|
|
1451
|
-
error: "API key required for all-in-one compare_personas",
|
|
1452
|
-
solution: "Use the API-free session bridge pattern instead:",
|
|
1453
|
-
steps: [
|
|
1454
|
-
"1. Call compare_personas_init with url, goal, personas",
|
|
1455
|
-
"2. For each persona, use browser tools (navigate, click, fill) to attempt the goal",
|
|
1456
|
-
"3. Call cognitive_journey_update_state after each action to track cognitive state",
|
|
1457
|
-
"4. Call compare_personas_record_result when each persona completes (success or abandon)",
|
|
1458
|
-
"5. Call compare_personas_summarize to get the comparison report",
|
|
1459
|
-
],
|
|
1460
|
-
note: "Claude orchestrates the simulation - no API key needed when YOU are the brain!",
|
|
1461
|
-
}, null, 2),
|
|
1462
|
-
},
|
|
1463
|
-
],
|
|
1464
|
-
};
|
|
1465
|
-
}
|
|
1466
|
-
throw error;
|
|
1467
|
-
}
|
|
1468
|
-
});
|
|
1469
1421
|
server.tool("find_element_by_intent", "AI-powered semantic element finding with ARIA-first selector strategy. Prioritizes aria-label > role > semantic HTML > ID > name > class. Returns selectorType, accessibilityScore (0-1), and alternatives. Use verbose=true for enriched failure responses.", {
|
|
1470
1422
|
intent: z.string().describe("Natural language description like 'the cheapest product' or 'login form'"),
|
|
1471
1423
|
verbose: z.boolean().optional().describe("Include alternative matches with confidence scores and AI suggestions"),
|
|
@@ -1516,7 +1468,15 @@ async function registerCBrowserTools() {
|
|
|
1516
1468
|
emotionalContagion: z.number().min(0).max(1).optional().describe("Affected by page emotional tone (0=immune, 1=absorbs mood)"),
|
|
1517
1469
|
fearOfMissingOut: z.number().min(0).max(1).optional().describe("Responds to scarcity/urgency (0=immune, 1=strongly affected)"),
|
|
1518
1470
|
socialProofSensitivity: z.number().min(0).max(1).optional().describe("Influenced by reviews/testimonials (0=ignores, 1=strongly influenced)"),
|
|
1519
|
-
|
|
1471
|
+
// POLARITY CORRECTED 2026-08-01. This read "0=flexible, 1=rigid",
|
|
1472
|
+
// which is backwards from every other authority on the field: the
|
|
1473
|
+
// questionnaire runs 0 "Rigid Mental Models" to 1 "Extremely Flexible",
|
|
1474
|
+
// the glossary's high end is "Highly adaptive", and its typicalScores
|
|
1475
|
+
// put power-user high and elderly-user low. A caller trusting this
|
|
1476
|
+
// description would send 1.0 meaning rigid and get the most flexible
|
|
1477
|
+
// persona the scale can express, with nothing in the output looking
|
|
1478
|
+
// wrong -- exactly the failure the field's rename note warns about.
|
|
1479
|
+
mentalModelFlexibility: z.number().min(0).max(1).optional().describe("Mental-model adaptability. 0 = rigid, cannot adapt when conventions change; 1 = instantly adapts. Named 'Rigidity' for backwards compatibility; the SCALE runs toward flexibility."),
|
|
1520
1480
|
}).optional().describe("Override specific cognitive traits (25 available)"),
|
|
1521
1481
|
}, async ({ persona: personaName, goal, startUrl, customTraits }) => {
|
|
1522
1482
|
// Get or create persona
|
|
@@ -1541,7 +1501,8 @@ async function registerCBrowserTools() {
|
|
|
1541
1501
|
personaObj = createCognitivePersona(personaName, personaName, customTraits || {});
|
|
1542
1502
|
}
|
|
1543
1503
|
else if (customTraits) {
|
|
1544
|
-
// v16.11.0:
|
|
1504
|
+
// v16.11.0: full default trait set (was only 7, causing trait dropout).
|
|
1505
|
+
// Said 25 until 2026-08-01; the model has 26 and has for some time.
|
|
1545
1506
|
const defaultTraits = {
|
|
1546
1507
|
// Core 7 traits
|
|
1547
1508
|
patience: 0.5,
|
|
@@ -1570,7 +1531,7 @@ async function registerCBrowserTools() {
|
|
|
1570
1531
|
emotionalContagion: 0.5,
|
|
1571
1532
|
fearOfMissingOut: 0.5,
|
|
1572
1533
|
socialProofSensitivity: 0.5,
|
|
1573
|
-
|
|
1534
|
+
mentalModelFlexibility: 0.5,
|
|
1574
1535
|
};
|
|
1575
1536
|
personaObj = {
|
|
1576
1537
|
...existingPersona,
|
|
@@ -1617,7 +1578,7 @@ async function registerCBrowserTools() {
|
|
|
1617
1578
|
const b = await getBrowser();
|
|
1618
1579
|
await b.navigate(startUrl);
|
|
1619
1580
|
// v16.12.0: Include persona values for influence pattern analysis
|
|
1620
|
-
const personaValues =
|
|
1581
|
+
const personaValues = resolveValuesForPersona(personaObj.name);
|
|
1621
1582
|
const influencePatterns = personaValues
|
|
1622
1583
|
? rankInfluencePatternsForProfile(personaValues).slice(0, 5) // Top 5 most effective patterns
|
|
1623
1584
|
: undefined;
|
|
@@ -1833,7 +1794,7 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1833
1794
|
return null;
|
|
1834
1795
|
const profile = getCognitiveProfile(p);
|
|
1835
1796
|
// v16.12.0: Include Schwartz values for each persona
|
|
1836
|
-
const values =
|
|
1797
|
+
const values = resolveValuesForPersona(p.name);
|
|
1837
1798
|
return {
|
|
1838
1799
|
name: p.name,
|
|
1839
1800
|
description: p.description,
|
|
@@ -1913,7 +1874,7 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1913
1874
|
disabilityType = "Cognitive";
|
|
1914
1875
|
}
|
|
1915
1876
|
// v16.12.0: Include Schwartz values for accessibility personas
|
|
1916
|
-
const values =
|
|
1877
|
+
const values = resolveValuesForPersona(p.name);
|
|
1917
1878
|
return {
|
|
1918
1879
|
name: p.name,
|
|
1919
1880
|
description: p.description,
|
|
@@ -1971,489 +1932,20 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1971
1932
|
// Persona Questionnaire Tools (v16.5.0)
|
|
1972
1933
|
// Research-based persona generation via questionnaire
|
|
1973
1934
|
// =========================================================================
|
|
1974
|
-
server.tool("persona_questionnaire_get", "Get the persona questionnaire for building a custom persona. Returns research-backed questions that map to cognitive traits. Use comprehensive=true for all 25 traits, or leave false for 8 core traits. v16.12.0: Now includes category question for value safeguards.", {
|
|
1975
|
-
comprehensive: z.boolean().optional().default(false).describe("Include all 25 traits (true) or just 8 core traits (false)"),
|
|
1976
|
-
traits: z.array(z.string()).optional().describe("Specific trait names to include (overrides comprehensive)"),
|
|
1977
|
-
includeCategory: z.boolean().optional().default(true).describe("Include category selection question for value safeguards"),
|
|
1978
|
-
}, async ({ comprehensive, traits, includeCategory }) => {
|
|
1979
|
-
const { generatePersonaQuestionnaire, formatForAskUserQuestion, CATEGORY_QUESTION, CATEGORY_VALUE_PRESETS, } = await import("./persona-questionnaire.js");
|
|
1980
|
-
const questions = generatePersonaQuestionnaire({
|
|
1981
|
-
comprehensive,
|
|
1982
|
-
traits: traits,
|
|
1983
|
-
});
|
|
1984
|
-
const formatted = formatForAskUserQuestion(questions);
|
|
1985
|
-
// v16.12.0: Include category question and value presets
|
|
1986
|
-
const categoryInfo = includeCategory ? {
|
|
1987
|
-
categoryQuestion: CATEGORY_QUESTION,
|
|
1988
|
-
categoryPresets: CATEGORY_VALUE_PRESETS.map(p => ({
|
|
1989
|
-
category: p.category,
|
|
1990
|
-
description: p.description,
|
|
1991
|
-
valueStrategy: p.valueStrategy,
|
|
1992
|
-
guidance: p.guidance,
|
|
1993
|
-
})),
|
|
1994
|
-
} : undefined;
|
|
1995
|
-
return {
|
|
1996
|
-
content: [
|
|
1997
|
-
{
|
|
1998
|
-
type: "text",
|
|
1999
|
-
text: JSON.stringify({
|
|
2000
|
-
instructions: `
|
|
2001
|
-
PERSONA CREATION WORKFLOW (v16.12.0):
|
|
2002
|
-
|
|
2003
|
-
1. FIRST: Ask the category question to determine value assignment strategy:
|
|
2004
|
-
- Cognitive disabilities (ADHD, autism) → specific values from neuroscience
|
|
2005
|
-
- Physical disabilities (motor, mobility) → security/autonomy shifts only
|
|
2006
|
-
- Sensory differences (color-blind, deaf) → neutral values (perception ≠ motivation)
|
|
2007
|
-
- Emotional traits (anxious, confident) → trait-based psychology values
|
|
2008
|
-
- General → population baseline
|
|
2009
|
-
|
|
2010
|
-
2. THEN: Ask the trait questions to build cognitive profile
|
|
2011
|
-
|
|
2012
|
-
3. FINALLY: Call persona_questionnaire_build with:
|
|
2013
|
-
- name, description, answers (from trait questions)
|
|
2014
|
-
- category (from category question)
|
|
2015
|
-
- The tool will apply appropriate value safeguards based on category
|
|
2016
|
-
|
|
2017
|
-
This ensures personas are grounded in research, not stereotypes.
|
|
2018
|
-
`.trim(),
|
|
2019
|
-
categoryInfo,
|
|
2020
|
-
questionCount: questions.length,
|
|
2021
|
-
// `questions` (formatted) and `rawQuestions` (unformatted) were
|
|
2022
|
-
// both returned, so every question shipped twice and roughly
|
|
2023
|
-
// doubled the payload. The formatted set is what a caller asks
|
|
2024
|
-
// these with; the raw set carried no field the formatted one
|
|
2025
|
-
// lacks. (2026-07-29)
|
|
2026
|
-
questions: formatted,
|
|
2027
|
-
}, null, 2),
|
|
2028
|
-
},
|
|
2029
|
-
],
|
|
2030
|
-
};
|
|
2031
|
-
});
|
|
2032
|
-
server.tool("persona_category_guidance", "Get research-based guidance for a specific persona category. Explains what values are appropriate and why, with citations. Use before building a persona to understand category constraints.", {
|
|
2033
|
-
category: z.enum(PERSONA_CATEGORIES).describe("Persona category to get guidance for"),
|
|
2034
|
-
}, async ({ category }) => {
|
|
2035
|
-
const { getCategoryValuePreset, COGNITIVE_SUBTYPES, } = await import("./persona-questionnaire.js");
|
|
2036
|
-
const preset = getCategoryValuePreset(category);
|
|
2037
|
-
// Get subtypes if cognitive
|
|
2038
|
-
const subtypes = category === "cognitive"
|
|
2039
|
-
? Object.entries(COGNITIVE_SUBTYPES).map(([name, info]) => ({
|
|
2040
|
-
name,
|
|
2041
|
-
values: info.values,
|
|
2042
|
-
researchBasis: info.researchBasis,
|
|
2043
|
-
}))
|
|
2044
|
-
: undefined;
|
|
2045
|
-
return {
|
|
2046
|
-
content: [
|
|
2047
|
-
{
|
|
2048
|
-
type: "text",
|
|
2049
|
-
text: JSON.stringify({
|
|
2050
|
-
category,
|
|
2051
|
-
description: preset.description,
|
|
2052
|
-
valueStrategy: preset.valueStrategy,
|
|
2053
|
-
guidance: preset.guidance,
|
|
2054
|
-
defaultValues: preset.defaultValues,
|
|
2055
|
-
researchBasis: preset.researchBasis,
|
|
2056
|
-
subtypes,
|
|
2057
|
-
safeguards: {
|
|
2058
|
-
cognitive: "Use specific values based on the neurobiological profile (e.g., ADHD = high stimulation). NOT stereotyping - grounded in dopamine/reward research.",
|
|
2059
|
-
physical: "Apply security ↑ and autonomyNeed ↑ shifts for predictable interfaces. Don't change core personality values.",
|
|
2060
|
-
sensory: "Use neutral (0.5) values. Sensory perception ≠ motivational psychology. Color-blindness doesn't make someone more/less achievement-oriented.",
|
|
2061
|
-
emotional: "Apply trait-based values from personality psychology (e.g., anxiety = high security-seeking).",
|
|
2062
|
-
general: "Use population baselines. Specific characteristics come from cognitive traits, not disability-based value shifts.",
|
|
2063
|
-
// Added 2026-07-29: this table covered five of the six
|
|
2064
|
-
// categories, and TypeScript flagged it the moment the enum
|
|
2065
|
-
// stopped silently excluding "agent". An unlisted key would have
|
|
2066
|
-
// yielded `undefined` guidance beside a populated preset.
|
|
2067
|
-
agent: "Agent personas are not human — motivational values do not apply. Use trait-based capability values (parsing, retrieval, tool use) and do NOT project human needs like security or belonging onto them.",
|
|
2068
|
-
}[category],
|
|
2069
|
-
}, null, 2),
|
|
2070
|
-
},
|
|
2071
|
-
],
|
|
2072
|
-
};
|
|
2073
|
-
});
|
|
2074
|
-
server.tool("persona_questionnaire_build", "Build a custom persona from questionnaire answers with category-aware value safeguards. Answers map trait names to values (0-1). Category determines value assignment strategy: cognitive disabilities get specific values, physical get security/autonomy shifts, sensory-only get neutral values.", {
|
|
2075
|
-
name: z.string().describe("Name for the new persona"),
|
|
2076
|
-
description: z.string().describe("Description of the persona"),
|
|
2077
|
-
answers: z.record(z.string(), z.number()).describe("Map of trait names to values (0-1), e.g. {patience: 0.25, riskTolerance: 0.75}"),
|
|
2078
|
-
category: z.enum(PERSONA_CATEGORIES).optional().describe("Persona category for value safeguards. Auto-detected from name/description if not provided."),
|
|
2079
|
-
valueOverrides: z.record(z.string(), z.number()).optional().describe("Override specific Schwartz values (0-1), e.g. {security: 0.8, stimulation: 0.3}"),
|
|
2080
|
-
save: z.boolean().optional().default(true).describe("Save the persona to disk for future use"),
|
|
2081
|
-
}, async ({ name, description, answers, category, valueOverrides, save }) => {
|
|
2082
|
-
const { buildTraitsFromAnswers, getTraitLabel, getTraitBehaviors, detectPersonaCategory, buildValuesFromCategory, validateCategoryValues, getCognitiveSubtypeValues, } = await import("./persona-questionnaire.js");
|
|
2083
|
-
// v16.12.0: Detect category if not provided
|
|
2084
|
-
const detectedCategory = category || detectPersonaCategory(name, description);
|
|
2085
|
-
// Build traits from answers with research-based correlations
|
|
2086
|
-
const traits = buildTraitsFromAnswers(answers);
|
|
2087
|
-
// v16.12.0: Build values based on category with safeguards
|
|
2088
|
-
// v16.14.0: Pass traits for trait_based categories (general, emotional)
|
|
2089
|
-
// Check for cognitive subtype (e.g., adhd-combined, autism-spectrum)
|
|
2090
|
-
const subtypeValues = getCognitiveSubtypeValues(name);
|
|
2091
|
-
const categoryResult = buildValuesFromCategory(detectedCategory, subtypeValues?.values || valueOverrides, traits // v16.14.0: Pass traits for trait-based value derivation
|
|
2092
|
-
);
|
|
2093
|
-
// Validate that values match category guidelines
|
|
2094
|
-
const warnings = validateCategoryValues(detectedCategory, categoryResult.values);
|
|
2095
|
-
// Create the persona
|
|
2096
|
-
const persona = createCognitivePersona(name, description, traits, {});
|
|
2097
|
-
// Save if requested
|
|
2098
|
-
let savedPath;
|
|
2099
|
-
if (save) {
|
|
2100
|
-
savedPath = saveCustomPersona(persona);
|
|
2101
|
-
}
|
|
2102
|
-
// Generate behavioral summary for key traits
|
|
2103
|
-
const traitSummary = {};
|
|
2104
|
-
for (const [trait, value] of Object.entries(traits)) {
|
|
2105
|
-
if (value !== 0.5) { // Only include non-default traits
|
|
2106
|
-
traitSummary[trait] = {
|
|
2107
|
-
value: value,
|
|
2108
|
-
label: getTraitLabel(trait, value),
|
|
2109
|
-
behaviors: getTraitBehaviors(trait, value),
|
|
2110
|
-
};
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
return {
|
|
2114
|
-
content: [
|
|
2115
|
-
{
|
|
2116
|
-
type: "text",
|
|
2117
|
-
text: JSON.stringify({
|
|
2118
|
-
success: true,
|
|
2119
|
-
persona: {
|
|
2120
|
-
name: persona.name,
|
|
2121
|
-
description: persona.description,
|
|
2122
|
-
demographics: persona.demographics,
|
|
2123
|
-
},
|
|
2124
|
-
cognitiveTraits: traits,
|
|
2125
|
-
traitSummary,
|
|
2126
|
-
// v16.12.0: Category-aware values
|
|
2127
|
-
category: {
|
|
2128
|
-
detected: detectedCategory,
|
|
2129
|
-
strategy: categoryResult.valueStrategy,
|
|
2130
|
-
guidance: categoryResult.guidance,
|
|
2131
|
-
},
|
|
2132
|
-
// Flat shape retained for callers that already read it; the nested
|
|
2133
|
-
// grouping is what every other values-returning path emits.
|
|
2134
|
-
values: categoryResult.values,
|
|
2135
|
-
valuesNested: nestPersonaValues(categoryResult.values),
|
|
2136
|
-
researchBasis: subtypeValues
|
|
2137
|
-
? [...categoryResult.researchBasis, subtypeValues.researchBasis]
|
|
2138
|
-
: categoryResult.researchBasis,
|
|
2139
|
-
// v16.14.0: Show how traits influenced values for trait_based categories
|
|
2140
|
-
valueDerivations: categoryResult.derivations && categoryResult.derivations.length > 0
|
|
2141
|
-
? categoryResult.derivations
|
|
2142
|
-
: undefined,
|
|
2143
|
-
warnings: warnings.length > 0 ? warnings : undefined,
|
|
2144
|
-
savedPath,
|
|
2145
|
-
usage: `Use persona "${name}" with cognitive-journey or other commands`,
|
|
2146
|
-
}, null, 2),
|
|
2147
|
-
},
|
|
2148
|
-
],
|
|
2149
|
-
};
|
|
2150
|
-
});
|
|
2151
|
-
server.tool("persona_trait_lookup", "Look up behavioral descriptions for specific trait values. Useful for understanding what a trait value means in practice.", {
|
|
2152
|
-
trait: z.string().describe("Trait name (e.g., 'patience', 'riskTolerance')"),
|
|
2153
|
-
value: z.number().min(0).max(1).describe("Trait value (0-1)"),
|
|
2154
|
-
}, async ({ trait, value }) => {
|
|
2155
|
-
const { getTraitReference, getTraitLabel, getTraitBehaviors } = await import("./persona-questionnaire.js");
|
|
2156
|
-
const reference = getTraitReference(trait);
|
|
2157
|
-
if (!reference) {
|
|
2158
|
-
return {
|
|
2159
|
-
content: [
|
|
2160
|
-
{
|
|
2161
|
-
type: "text",
|
|
2162
|
-
text: JSON.stringify({
|
|
2163
|
-
error: `Unknown trait: ${trait}`,
|
|
2164
|
-
availableTraits: [
|
|
2165
|
-
"patience", "riskTolerance", "comprehension", "persistence", "curiosity",
|
|
2166
|
-
"workingMemory", "readingTendency", "resilience", "selfEfficacy", "satisficing",
|
|
2167
|
-
"trustCalibration", "interruptRecovery", "informationForaging", "changeBlindness",
|
|
2168
|
-
"anchoringBias", "timeHorizon", "attributionStyle", "metacognitivePlanning",
|
|
2169
|
-
"proceduralFluency", "transferLearning", "authoritySensitivity", "emotionalContagion",
|
|
2170
|
-
"fearOfMissingOut", "socialProofSensitivity", "mentalModelRigidity"
|
|
2171
|
-
],
|
|
2172
|
-
}, null, 2),
|
|
2173
|
-
},
|
|
2174
|
-
],
|
|
2175
|
-
};
|
|
2176
|
-
}
|
|
2177
|
-
return {
|
|
2178
|
-
content: [
|
|
2179
|
-
{
|
|
2180
|
-
type: "text",
|
|
2181
|
-
text: JSON.stringify({
|
|
2182
|
-
trait: reference.name,
|
|
2183
|
-
description: reference.description,
|
|
2184
|
-
researchBasis: reference.researchBasis,
|
|
2185
|
-
value,
|
|
2186
|
-
label: getTraitLabel(trait, value),
|
|
2187
|
-
behaviors: getTraitBehaviors(trait, value),
|
|
2188
|
-
allLevels: reference.levels,
|
|
2189
|
-
}, null, 2),
|
|
2190
|
-
},
|
|
2191
|
-
],
|
|
2192
|
-
};
|
|
2193
|
-
});
|
|
2194
1935
|
// =========================================================================
|
|
2195
1936
|
// Values System Tools (v16.12.0)
|
|
2196
1937
|
// Schwartz's 10 Universal Values, Self-Determination Theory, Maslow
|
|
2197
1938
|
// =========================================================================
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
selfDirection: { range: "0-1", meaning: "Independent thought, creativity, freedom. High: values autonomy and exploration. Low: prefers guidance and structure." },
|
|
2206
|
-
stimulation: { range: "0-1", meaning: "Excitement, novelty, challenge. High: seeks variety and new experiences. Low: prefers routine and predictability." },
|
|
2207
|
-
hedonism: { range: "0-1", meaning: "Pleasure, sensuous gratification. High: prioritizes enjoyment and comfort. Low: prioritizes duty over pleasure." },
|
|
2208
|
-
achievement: { range: "0-1", meaning: "Personal success through competence. High: driven to excel and demonstrate capability. Low: content without external validation." },
|
|
2209
|
-
power: { range: "0-1", meaning: "Social status, prestige, control. High: seeks influence over others/resources. Low: indifferent to status hierarchies." },
|
|
2210
|
-
security: { range: "0-1", meaning: "Safety, harmony, stability. High: risk-averse, needs predictability. Low: comfortable with uncertainty." },
|
|
2211
|
-
conformity: { range: "0-1", meaning: "Restraint of actions that harm others. High: follows social rules carefully. Low: independent of social expectations." },
|
|
2212
|
-
tradition: { range: "0-1", meaning: "Respect for customs, heritage. High: values cultural/religious practices. Low: questions or ignores tradition." },
|
|
2213
|
-
benevolence: { range: "0-1", meaning: "Welfare of close others. High: prioritizes helping friends/family. Low: more self-focused." },
|
|
2214
|
-
universalism: { range: "0-1", meaning: "Tolerance, social justice, environment. High: cares about all people and nature. Low: focused on in-group." },
|
|
2215
|
-
},
|
|
2216
|
-
higherOrderValues: {
|
|
2217
|
-
openness: { formula: "(selfDirection + stimulation) / 2", meaning: "Openness to change - receptivity to new ideas and experiences" },
|
|
2218
|
-
selfEnhancement: { formula: "(achievement + power) / 2", meaning: "Focus on personal success and dominance" },
|
|
2219
|
-
conservation: { formula: "(security + conformity + tradition) / 3", meaning: "Preservation of stability and traditional practices" },
|
|
2220
|
-
selfTranscendence: { formula: "(benevolence + universalism) / 2", meaning: "Concern for welfare of others and nature" },
|
|
2221
|
-
},
|
|
2222
|
-
selfDeterminationTheory: {
|
|
2223
|
-
autonomyNeed: { range: "0-1", meaning: "Need for choice and self-direction (Deci & Ryan, 1985)" },
|
|
2224
|
-
competenceNeed: { range: "0-1", meaning: "Need to feel capable and effective" },
|
|
2225
|
-
relatednessNeed: { range: "0-1", meaning: "Need for connection and belonging" },
|
|
2226
|
-
},
|
|
2227
|
-
maslowLevels: [
|
|
2228
|
-
{ level: "physiological", meaning: "Basic survival needs (food, water, shelter)" },
|
|
2229
|
-
{ level: "safety", meaning: "Security, stability, freedom from fear" },
|
|
2230
|
-
{ level: "belonging", meaning: "Social connection, love, acceptance" },
|
|
2231
|
-
{ level: "esteem", meaning: "Achievement, recognition, respect" },
|
|
2232
|
-
{ level: "self-actualization", meaning: "Self-fulfillment, reaching potential" },
|
|
2233
|
-
],
|
|
2234
|
-
researchBasis: {
|
|
2235
|
-
schwartz: "Schwartz, S. H. (1992, 2012). Theory of Basic Human Values. DOI: 10.1016/S0065-2601(08)60281-6",
|
|
2236
|
-
sdt: "Deci, E. L., & Ryan, R. M. (1985, 2000). Self-Determination Theory. DOI: 10.1037/0003-066X.55.1.68",
|
|
2237
|
-
maslow: "Maslow, A. H. (1943). A Theory of Human Motivation. DOI: 10.1037/h0054346",
|
|
2238
|
-
},
|
|
2239
|
-
usage: "Use persona_values_lookup with a persona name to see these values for a specific persona, and list_influence_patterns to see which persuasion patterns work on which values.",
|
|
2240
|
-
}, null, 2),
|
|
2241
|
-
},
|
|
2242
|
-
],
|
|
2243
|
-
};
|
|
2244
|
-
});
|
|
2245
|
-
server.tool("persona_values_lookup", "Look up the values profile for a persona (Schwartz's 10 Universal Values, SDT needs, Maslow level). Values describe WHO the persona is at a deeper motivational level, informing influence susceptibility.", {
|
|
2246
|
-
persona: z.string().describe("Persona name (e.g., 'first-timer', 'power-user', 'anxious-user')"),
|
|
2247
|
-
includeInfluencePatterns: z.boolean().optional().default(true).describe("Include ranked influence patterns this persona is susceptible to"),
|
|
2248
|
-
}, async ({ persona, includeInfluencePatterns }) => {
|
|
2249
|
-
const values = getPersonaValues(persona);
|
|
2250
|
-
if (!values) {
|
|
2251
|
-
// List available personas with values
|
|
2252
|
-
const availablePersonas = PERSONA_VALUE_PROFILES.map(p => p.personaName);
|
|
2253
|
-
return {
|
|
2254
|
-
content: [
|
|
2255
|
-
{
|
|
2256
|
-
type: "text",
|
|
2257
|
-
text: JSON.stringify({
|
|
2258
|
-
error: `No values profile found for persona: ${persona}`,
|
|
2259
|
-
availablePersonas,
|
|
2260
|
-
note: "Values are defined for all built-in personas. Custom personas can have values added via the questionnaire.",
|
|
2261
|
-
}, null, 2),
|
|
2262
|
-
},
|
|
2263
|
-
],
|
|
2264
|
-
};
|
|
2265
|
-
}
|
|
2266
|
-
// Find rationale for this persona
|
|
2267
|
-
const profile = PERSONA_VALUE_PROFILES.find(p => p.personaName.toLowerCase() === persona.toLowerCase());
|
|
2268
|
-
// Calculate influence susceptibility if requested
|
|
2269
|
-
let influencePatterns;
|
|
2270
|
-
if (includeInfluencePatterns) {
|
|
2271
|
-
const ranked = rankInfluencePatternsForProfile(values);
|
|
2272
|
-
influencePatterns = ranked.slice(0, 7).map(r => ({
|
|
2273
|
-
pattern: r.pattern.name,
|
|
2274
|
-
susceptibility: r.susceptibility,
|
|
2275
|
-
description: r.pattern.description,
|
|
2276
|
-
}));
|
|
2277
|
-
}
|
|
2278
|
-
return {
|
|
2279
|
-
content: [
|
|
2280
|
-
{
|
|
2281
|
-
type: "text",
|
|
2282
|
-
text: JSON.stringify({
|
|
2283
|
-
persona,
|
|
2284
|
-
rationale: profile?.rationale,
|
|
2285
|
-
schwartzValues: {
|
|
2286
|
-
selfDirection: { value: values.selfDirection, meaning: "Independent thought, creativity, freedom" },
|
|
2287
|
-
stimulation: { value: values.stimulation, meaning: "Excitement, novelty, challenge" },
|
|
2288
|
-
hedonism: { value: values.hedonism, meaning: "Pleasure, sensuous gratification" },
|
|
2289
|
-
achievement: { value: values.achievement, meaning: "Personal success through competence" },
|
|
2290
|
-
power: { value: values.power, meaning: "Social status, prestige, control" },
|
|
2291
|
-
security: { value: values.security, meaning: "Safety, harmony, stability" },
|
|
2292
|
-
conformity: { value: values.conformity, meaning: "Restraint of actions that harm others" },
|
|
2293
|
-
tradition: { value: values.tradition, meaning: "Respect for customs, heritage" },
|
|
2294
|
-
benevolence: { value: values.benevolence, meaning: "Welfare of close others" },
|
|
2295
|
-
universalism: { value: values.universalism, meaning: "Tolerance, social justice, environment" },
|
|
2296
|
-
},
|
|
2297
|
-
higherOrderValues: {
|
|
2298
|
-
openness: { value: values.openness, meaning: "(selfDirection + stimulation) / 2" },
|
|
2299
|
-
selfEnhancement: { value: values.selfEnhancement, meaning: "(achievement + power) / 2" },
|
|
2300
|
-
conservation: { value: values.conservation, meaning: "(security + conformity + tradition) / 3" },
|
|
2301
|
-
selfTranscendence: { value: values.selfTranscendence, meaning: "(benevolence + universalism) / 2" },
|
|
2302
|
-
},
|
|
2303
|
-
selfDeterminationTheory: {
|
|
2304
|
-
autonomyNeed: { value: values.autonomyNeed, meaning: "Need for choice and control" },
|
|
2305
|
-
competenceNeed: { value: values.competenceNeed, meaning: "Need to feel capable" },
|
|
2306
|
-
relatednessNeed: { value: values.relatednessNeed, meaning: "Need for connection" },
|
|
2307
|
-
},
|
|
2308
|
-
maslowLevel: {
|
|
2309
|
-
level: values.maslowLevel,
|
|
2310
|
-
meaning: values.maslowLevel === "physiological" ? "Basic survival needs"
|
|
2311
|
-
: values.maslowLevel === "safety" ? "Security and stability"
|
|
2312
|
-
: values.maslowLevel === "belonging" ? "Social connection and love"
|
|
2313
|
-
: values.maslowLevel === "esteem" ? "Achievement and recognition"
|
|
2314
|
-
: "Self-fulfillment and growth",
|
|
2315
|
-
},
|
|
2316
|
-
influencePatterns,
|
|
2317
|
-
researchBasis: {
|
|
2318
|
-
schwartz: "Schwartz, S. H. (1992, 2012). Theory of Basic Human Values. DOI: 10.1016/S0065-2601(08)60281-6",
|
|
2319
|
-
sdt: "Deci, E. L., & Ryan, R. M. (1985, 2000). Self-Determination Theory. DOI: 10.1037/0003-066X.55.1.68",
|
|
2320
|
-
maslow: "Maslow, A. H. (1943). A Theory of Human Motivation. DOI: 10.1037/h0054346",
|
|
2321
|
-
},
|
|
2322
|
-
}, null, 2),
|
|
2323
|
-
},
|
|
2324
|
-
],
|
|
2325
|
-
};
|
|
2326
|
-
});
|
|
2327
|
-
server.tool("list_influence_patterns", "List all research-backed influence/persuasion patterns and which persona values make someone susceptible to each pattern. Based on Cialdini, Kahneman, and behavioral economics research.", {}, async () => {
|
|
2328
|
-
// INFLUENCE_PATTERNS is an array of InfluencePattern objects
|
|
2329
|
-
const patterns = INFLUENCE_PATTERNS.map(pattern => ({
|
|
2330
|
-
name: pattern.name,
|
|
2331
|
-
description: pattern.description,
|
|
2332
|
-
researchBasis: pattern.researchBasis,
|
|
2333
|
-
targetValues: pattern.targetValues,
|
|
2334
|
-
mechanism: pattern.mechanism,
|
|
2335
|
-
examples: pattern.examples,
|
|
2336
|
-
}));
|
|
2337
|
-
return {
|
|
2338
|
-
content: [
|
|
2339
|
-
{
|
|
2340
|
-
type: "text",
|
|
2341
|
-
text: JSON.stringify({
|
|
2342
|
-
count: patterns.length,
|
|
2343
|
-
patterns,
|
|
2344
|
-
usage: "Use persona_values_lookup to see which patterns a specific persona is susceptible to",
|
|
2345
|
-
note: "These patterns describe psychological influence mechanisms. Use ethically for UX optimization, not manipulation.",
|
|
2346
|
-
}, null, 2),
|
|
2347
|
-
},
|
|
2348
|
-
],
|
|
2349
|
-
};
|
|
2350
|
-
});
|
|
1939
|
+
// persona_values_lookup lives in mcp-tools/base/values-tools.ts and is
|
|
1940
|
+
// registered below via registerValuesTools. A second copy lived here and
|
|
1941
|
+
// answered the stdio server while the remote server answered from the
|
|
1942
|
+
// shared one: same tool name, two different payloads, and the newer fields
|
|
1943
|
+
// (netNudge, valuesSource, the maslow basis) existed in only one of them.
|
|
1944
|
+
// The divergence was invisible because each server was self-consistent.
|
|
1945
|
+
// Same removal as the legacy empathy_audit above. (2026-08-01)
|
|
2351
1946
|
// =========================================================================
|
|
2352
1947
|
// Persona Comparison Session Bridge (API-free via Claude orchestration)
|
|
2353
1948
|
// =========================================================================
|
|
2354
|
-
server.tool("compare_personas_init", "Initialize a multi-persona comparison session. Returns all persona profiles and initial states. Claude orchestrates the journeys using browser tools + cognitive_journey_update_state, then records results. NO API KEY NEEDED - Claude is the brain.", {
|
|
2355
|
-
url: z.string().url().describe("Starting URL for all journeys"),
|
|
2356
|
-
goal: z.string().describe("Goal to accomplish"),
|
|
2357
|
-
personas: z.array(z.string()).describe("Persona names to compare (e.g., ['first-timer', 'elderly-user', 'power-user'])"),
|
|
2358
|
-
}, async ({ url, goal, personas: personaNames }) => {
|
|
2359
|
-
// Cleanup old sessions
|
|
2360
|
-
cleanupOldSessions();
|
|
2361
|
-
// Generate session ID
|
|
2362
|
-
const sessionId = `cmp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
2363
|
-
// Build persona profiles
|
|
2364
|
-
// v16.14.1: Use getAnyPersona to find personas in ALL registries
|
|
2365
|
-
// (builtin, accessibility, emotional, custom) - fixes name mismatch bug
|
|
2366
|
-
// v17.0.0: Filter out agent personas - cognitive journeys don't support them
|
|
2367
|
-
const personas = personaNames
|
|
2368
|
-
.filter(name => {
|
|
2369
|
-
const persona = getAnyPersona(name);
|
|
2370
|
-
if (persona && isAgentPersonaObject(persona)) {
|
|
2371
|
-
console.warn(`[CBrowser] Skipping agent persona "${name}" - not supported for persona comparison`);
|
|
2372
|
-
return false;
|
|
2373
|
-
}
|
|
2374
|
-
return true;
|
|
2375
|
-
})
|
|
2376
|
-
.map(name => {
|
|
2377
|
-
const existingPersona = getAnyPersona(name);
|
|
2378
|
-
let personaObj;
|
|
2379
|
-
if (!existingPersona) {
|
|
2380
|
-
// Only create generic stub if persona truly doesn't exist
|
|
2381
|
-
personaObj = createCognitivePersona(name, name, {});
|
|
2382
|
-
}
|
|
2383
|
-
else {
|
|
2384
|
-
// Safe cast - we filtered out agent personas above
|
|
2385
|
-
personaObj = existingPersona;
|
|
2386
|
-
}
|
|
2387
|
-
const profile = getCognitiveProfile(personaObj);
|
|
2388
|
-
// Initial cognitive state
|
|
2389
|
-
const initialState = {
|
|
2390
|
-
patienceRemaining: 1.0,
|
|
2391
|
-
confusionLevel: 0.0,
|
|
2392
|
-
frustrationLevel: 0.0,
|
|
2393
|
-
goalProgress: 0.0,
|
|
2394
|
-
confidenceLevel: 0.5,
|
|
2395
|
-
currentMood: "neutral",
|
|
2396
|
-
memory: {
|
|
2397
|
-
pagesVisited: [url],
|
|
2398
|
-
actionsAttempted: [],
|
|
2399
|
-
errorsEncountered: [],
|
|
2400
|
-
backtrackCount: 0,
|
|
2401
|
-
},
|
|
2402
|
-
timeElapsed: 0,
|
|
2403
|
-
stepCount: 0,
|
|
2404
|
-
};
|
|
2405
|
-
// Abandonment thresholds
|
|
2406
|
-
const traits = profile.traits;
|
|
2407
|
-
const thresholds = {
|
|
2408
|
-
patienceMin: 0.1,
|
|
2409
|
-
confusionMax: traits.comprehension < 0.4 ? 0.6 : 0.8,
|
|
2410
|
-
frustrationMax: traits.patience < 0.3 ? 0.7 : 0.85,
|
|
2411
|
-
maxStepsWithoutProgress: traits.persistence > 0.7 ? 15 : 10,
|
|
2412
|
-
loopDetectionThreshold: 3,
|
|
2413
|
-
timeLimit: traits.patience > 0.7 ? 180 : (traits.patience < 0.3 ? 60 : 120),
|
|
2414
|
-
};
|
|
2415
|
-
return {
|
|
2416
|
-
name,
|
|
2417
|
-
description: personaObj.description || name,
|
|
2418
|
-
profile,
|
|
2419
|
-
initialState,
|
|
2420
|
-
thresholds,
|
|
2421
|
-
};
|
|
2422
|
-
});
|
|
2423
|
-
// Store session
|
|
2424
|
-
const session = {
|
|
2425
|
-
id: sessionId,
|
|
2426
|
-
url,
|
|
2427
|
-
goal,
|
|
2428
|
-
personas,
|
|
2429
|
-
results: [],
|
|
2430
|
-
createdAt: Date.now(),
|
|
2431
|
-
};
|
|
2432
|
-
comparisonSessions.set(sessionId, session);
|
|
2433
|
-
return {
|
|
2434
|
-
content: [
|
|
2435
|
-
{
|
|
2436
|
-
type: "text",
|
|
2437
|
-
text: JSON.stringify({
|
|
2438
|
-
sessionId,
|
|
2439
|
-
url,
|
|
2440
|
-
goal,
|
|
2441
|
-
personaCount: personas.length,
|
|
2442
|
-
personas: personas.map(p => ({
|
|
2443
|
-
name: p.name,
|
|
2444
|
-
description: p.description,
|
|
2445
|
-
cognitiveTraits: p.profile.traits,
|
|
2446
|
-
attentionPattern: p.profile.attentionPattern,
|
|
2447
|
-
decisionStyle: p.profile.decisionStyle,
|
|
2448
|
-
initialState: p.initialState,
|
|
2449
|
-
thresholds: p.thresholds,
|
|
2450
|
-
})),
|
|
2451
|
-
instructions: "For each persona: 1) Use browser tools (navigate, click, fill) to attempt the goal. 2) Call cognitive_journey_update_state after each action. 3) Call compare_personas_record_result when done (success or abandon). 4) After all personas, call compare_personas_summarize.",
|
|
2452
|
-
}, null, 2),
|
|
2453
|
-
},
|
|
2454
|
-
],
|
|
2455
|
-
};
|
|
2456
|
-
});
|
|
2457
1949
|
server.tool("compare_personas_record_result", "Record the journey result for a persona in the comparison session. Call this when a persona's journey is complete (success or abandonment).", {
|
|
2458
1950
|
sessionId: z.string().describe("Session ID from compare_personas_init"),
|
|
2459
1951
|
persona: z.string().describe("Persona name"),
|
|
@@ -3036,83 +2528,36 @@ This ensures personas are grounded in research, not stereotypes.
|
|
|
3036
2528
|
],
|
|
3037
2529
|
};
|
|
3038
2530
|
});
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
return {
|
|
3070
|
-
persona: r.persona,
|
|
3071
|
-
disabilityType: r.disabilityType,
|
|
3072
|
-
goalAchieved: r.goalAchieved,
|
|
3073
|
-
empathyScore: r.empathyScore,
|
|
3074
|
-
barrierCount: uniqueTypes.size, // v14.2.5: Changed to unique types
|
|
3075
|
-
barrierTypes: Array.from(uniqueTypes),
|
|
3076
|
-
totalBarrierElements: r.barriers.length, // v14.2.5: Raw element count
|
|
3077
|
-
wcagViolationCount: r.wcagViolations.length,
|
|
3078
|
-
};
|
|
3079
|
-
}),
|
|
3080
|
-
allWcagViolations: result.allWcagViolations,
|
|
3081
|
-
topBarriers: result.topBarriers.slice(0, 5), // v11.11.0: Deduplicated by type
|
|
3082
|
-
topRemediation: result.combinedRemediation.slice(0, 5),
|
|
3083
|
-
duration: result.duration,
|
|
3084
|
-
}, null, 2),
|
|
3085
|
-
},
|
|
3086
|
-
],
|
|
3087
|
-
};
|
|
3088
|
-
}
|
|
3089
|
-
catch (error) {
|
|
3090
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3091
|
-
if (errorMessage.includes("API key")) {
|
|
3092
|
-
return {
|
|
3093
|
-
content: [
|
|
3094
|
-
{
|
|
3095
|
-
type: "text",
|
|
3096
|
-
text: JSON.stringify({
|
|
3097
|
-
error: "API key required for all-in-one empathy_audit",
|
|
3098
|
-
solution: "Use the API-free session bridge pattern instead:",
|
|
3099
|
-
steps: [
|
|
3100
|
-
"1. Call empathy_audit_init with url, goal, disabilities, wcagLevel",
|
|
3101
|
-
"2. For each disability persona, use browser tools to attempt the goal",
|
|
3102
|
-
"3. Call empathy_audit_record_barrier when you observe accessibility barriers",
|
|
3103
|
-
"4. Call empathy_audit_complete_persona when each persona finishes",
|
|
3104
|
-
"5. Call empathy_audit_summarize to get the final audit report",
|
|
3105
|
-
],
|
|
3106
|
-
note: "Claude orchestrates the audit - no API key needed when YOU are the brain!",
|
|
3107
|
-
availablePersonas: listAccessibilityPersonas(),
|
|
3108
|
-
}, null, 2),
|
|
3109
|
-
},
|
|
3110
|
-
],
|
|
3111
|
-
};
|
|
3112
|
-
}
|
|
3113
|
-
throw error;
|
|
3114
|
-
}
|
|
3115
|
-
});
|
|
2531
|
+
// The ui:// resources the canonical tools advertise via _meta.ui. Without
|
|
2532
|
+
// these the stdio server answered "Method not found" to resources/list while
|
|
2533
|
+
// its own tool pointed at ui://cbrowser/empathy, so a UI-capable host was
|
|
2534
|
+
// told a widget existed and could not fetch it.
|
|
2535
|
+
registerUiResources(server);
|
|
2536
|
+
// empathy_audit is registered from the canonical implementation in
|
|
2537
|
+
// mcp-tools/base/audit-tools.ts. This file used to carry its own older copy
|
|
2538
|
+
// of the same tool name -- thin summary, no barrier rects, no persona
|
|
2539
|
+
// weighting, no UI resource -- so the local server answered differently to
|
|
2540
|
+
// the remote one for the same call. Removed 2026-07-31.
|
|
2541
|
+
registerEmpathyAuditTool(server);
|
|
2542
|
+
registerValuesTools(server);
|
|
2543
|
+
// The eight cognitive/comparison tools were registered only on the PUBLIC
|
|
2544
|
+
// path, so the hosted server had them and `npx cbrowser mcp-server` did not:
|
|
2545
|
+
// compare_personas, compare_personas_init, compare_personas_complete,
|
|
2546
|
+
// cognitive_distance, cognitive_coverage, cognitive_interpolate,
|
|
2547
|
+
// cognitive_load_estimate and cognitive_effort. Two of them existed here as
|
|
2548
|
+
// separate older copies, which is how the gap stayed invisible -- the two
|
|
2549
|
+
// most-used names were present locally, so the absence of the other six read
|
|
2550
|
+
// as "those are enterprise features" rather than as a registration gap.
|
|
2551
|
+
// Same split, same fix as the values family earlier today. (2026-08-01)
|
|
2552
|
+
registerPersonaComparisonTools(server, { getBrowser });
|
|
2553
|
+
// The persona-creation family was duplicated here too -- five older copies
|
|
2554
|
+
// against the shared registrar's six. That is why Big Five inference from a
|
|
2555
|
+
// description reached the hosted server and not `npx cbrowser mcp-server`:
|
|
2556
|
+
// the stdio build was answering from tools that predate it. Eighth pair found
|
|
2557
|
+
// this way; the pattern is that anything registered only on the public path
|
|
2558
|
+
// silently diverges from anything hand-written here. (2026-08-01)
|
|
2559
|
+
registerPersonaCreationTools(server);
|
|
2560
|
+
registerPersonaLifecycleTools(server);
|
|
3116
2561
|
// =========================================================================
|
|
3117
2562
|
// Diagnostics Tools
|
|
3118
2563
|
// =========================================================================
|
|
@@ -3274,327 +2719,6 @@ This ensures personas are grounded in research, not stereotypes.
|
|
|
3274
2719
|
// =========================================================================
|
|
3275
2720
|
// Persona Creation Tools (v17.3.0)
|
|
3276
2721
|
// =========================================================================
|
|
3277
|
-
server.tool("persona_create_start", "Start creating a custom persona. YOU MUST USE YOUR AskUserQuestion TOOL to present the choice to the user.", {
|
|
3278
|
-
persona_name: z.string().describe("Name for the new persona"),
|
|
3279
|
-
comprehensive: z.boolean().optional().describe("Include all 25 traits (true) or just core 8 traits (false)"),
|
|
3280
|
-
}, async ({ persona_name, comprehensive = false }) => {
|
|
3281
|
-
const sessionId = "local-session";
|
|
3282
|
-
const existingSession = getQuestionnaireSession(sessionId);
|
|
3283
|
-
if (existingSession) {
|
|
3284
|
-
return {
|
|
3285
|
-
content: [{
|
|
3286
|
-
type: "text",
|
|
3287
|
-
text: JSON.stringify({
|
|
3288
|
-
warning: "A questionnaire session is already in progress",
|
|
3289
|
-
existing_persona: existingSession.personaName,
|
|
3290
|
-
progress: `${existingSession.currentIndex}/${existingSession.questions.length} questions answered`,
|
|
3291
|
-
options: ["Use persona_create_questionnaire_answer to continue", "Use persona_create_cancel to discard"],
|
|
3292
|
-
}, null, 2),
|
|
3293
|
-
}],
|
|
3294
|
-
};
|
|
3295
|
-
}
|
|
3296
|
-
const traitCount = comprehensive ? 25 : 8;
|
|
3297
|
-
const totalQuestions = traitCount + VALUES_QUESTIONS.length;
|
|
3298
|
-
return {
|
|
3299
|
-
content: [{
|
|
3300
|
-
type: "text",
|
|
3301
|
-
text: `ACTION REQUIRED: Use your AskUserQuestion tool to ask the user:
|
|
3302
|
-
|
|
3303
|
-
Question: "How would you like to create the '${persona_name}' persona?"
|
|
3304
|
-
Header: "Create Mode"
|
|
3305
|
-
|
|
3306
|
-
Options:
|
|
3307
|
-
1. "Fill out questionnaire (Recommended)" - Answer ${totalQuestions} questions about this persona's cognitive traits and values.
|
|
3308
|
-
2. "Describe the persona" - Provide a text description and I'll infer appropriate trait and value settings.
|
|
3309
|
-
|
|
3310
|
-
After the user chooses:
|
|
3311
|
-
- If "questionnaire": Call persona_create_questionnaire_start with persona_name="${persona_name}" and comprehensive=${comprehensive}
|
|
3312
|
-
- If "describe": Ask the user to describe the persona, then call persona_create_from_description
|
|
3313
|
-
|
|
3314
|
-
IMPORTANT: Do NOT show this text to the user. USE AskUserQuestion to present the choice interactively.`,
|
|
3315
|
-
}],
|
|
3316
|
-
};
|
|
3317
|
-
});
|
|
3318
|
-
server.tool("persona_create_questionnaire_start", "Start the questionnaire mode for persona creation. YOU MUST USE AskUserQuestion to present each question interactively.", {
|
|
3319
|
-
persona_name: z.string().describe("Name for the new persona"),
|
|
3320
|
-
comprehensive: z.boolean().optional().describe("Include all 25 traits (default: false)"),
|
|
3321
|
-
}, async ({ persona_name, comprehensive = false }) => {
|
|
3322
|
-
const sessionId = "local-session";
|
|
3323
|
-
const rawQuestions = generatePersonaQuestionnaire({ comprehensive });
|
|
3324
|
-
const session = {
|
|
3325
|
-
personaName: persona_name,
|
|
3326
|
-
questions: rawQuestions,
|
|
3327
|
-
valueQuestions: VALUES_QUESTIONS,
|
|
3328
|
-
answers: {},
|
|
3329
|
-
valueAnswers: {},
|
|
3330
|
-
currentIndex: 0,
|
|
3331
|
-
phase: "traits",
|
|
3332
|
-
comprehensive,
|
|
3333
|
-
startedAt: Date.now(),
|
|
3334
|
-
lastQuestionAskedAt: Date.now(),
|
|
3335
|
-
};
|
|
3336
|
-
setQuestionnaireSession(sessionId, session);
|
|
3337
|
-
const firstQuestion = rawQuestions[0];
|
|
3338
|
-
const thirdPersonQuestion = convertToThirdPerson(firstQuestion.question);
|
|
3339
|
-
const totalQuestions = rawQuestions.length + VALUES_QUESTIONS.length;
|
|
3340
|
-
return {
|
|
3341
|
-
content: [{
|
|
3342
|
-
type: "text",
|
|
3343
|
-
text: `ACTION REQUIRED: Use your AskUserQuestion tool to ask about the "${persona_name}" persona.
|
|
3344
|
-
|
|
3345
|
-
Question 1 of ${totalQuestions} (Trait: ${firstQuestion.trait})
|
|
3346
|
-
"${thirdPersonQuestion}"
|
|
3347
|
-
|
|
3348
|
-
Header: "${getTraitHeader(firstQuestion.trait)}"
|
|
3349
|
-
|
|
3350
|
-
Options:
|
|
3351
|
-
${firstQuestion.options.map((o, i) => `${i + 1}. "${o.label}" - ${o.description}`).join("\n")}
|
|
3352
|
-
|
|
3353
|
-
After the user selects an option, call persona_create_questionnaire_answer with answer_value.
|
|
3354
|
-
|
|
3355
|
-
IMPORTANT: Use AskUserQuestion - do NOT just display this text.`,
|
|
3356
|
-
}],
|
|
3357
|
-
};
|
|
3358
|
-
});
|
|
3359
|
-
server.tool("persona_create_questionnaire_answer", "Submit an answer for the current questionnaire question.", {
|
|
3360
|
-
answer_value: z.number().min(0).max(1).describe("The value selected (0.0, 0.25, 0.33, 0.67, 0.75, or 1.0)"),
|
|
3361
|
-
}, async ({ answer_value }) => {
|
|
3362
|
-
const sessionId = "local-session";
|
|
3363
|
-
const session = getQuestionnaireSession(sessionId);
|
|
3364
|
-
if (!session) {
|
|
3365
|
-
return {
|
|
3366
|
-
content: [{
|
|
3367
|
-
type: "text",
|
|
3368
|
-
text: JSON.stringify({
|
|
3369
|
-
error: "No questionnaire session in progress",
|
|
3370
|
-
instruction: "Start a new questionnaire with persona_create_questionnaire_start",
|
|
3371
|
-
}, null, 2),
|
|
3372
|
-
}],
|
|
3373
|
-
};
|
|
3374
|
-
}
|
|
3375
|
-
const totalQuestions = session.questions.length + session.valueQuestions.length;
|
|
3376
|
-
const now = Date.now();
|
|
3377
|
-
if (session.phase === "traits") {
|
|
3378
|
-
const currentQuestion = session.questions[session.currentIndex];
|
|
3379
|
-
session.answers[currentQuestion.trait] = answer_value;
|
|
3380
|
-
session.currentIndex++;
|
|
3381
|
-
if (session.currentIndex >= session.questions.length) {
|
|
3382
|
-
session.phase = "values";
|
|
3383
|
-
session.currentIndex = 0;
|
|
3384
|
-
}
|
|
3385
|
-
}
|
|
3386
|
-
else {
|
|
3387
|
-
const currentValueQ = session.valueQuestions[session.currentIndex];
|
|
3388
|
-
session.valueAnswers[currentValueQ.value] = answer_value;
|
|
3389
|
-
session.currentIndex++;
|
|
3390
|
-
}
|
|
3391
|
-
session.lastQuestionAskedAt = now;
|
|
3392
|
-
if (session.phase === "values" && session.currentIndex >= session.valueQuestions.length) {
|
|
3393
|
-
const traits = buildTraitsFromAnswers(session.answers);
|
|
3394
|
-
const derivedResult = deriveValuesFromTraits(traits);
|
|
3395
|
-
const derivedValues = derivedResult.values;
|
|
3396
|
-
const values = {
|
|
3397
|
-
selfDirection: session.valueAnswers.selfDirection ?? derivedValues.selfDirection ?? 0.5,
|
|
3398
|
-
stimulation: session.valueAnswers.stimulation ?? derivedValues.stimulation ?? 0.5,
|
|
3399
|
-
hedonism: session.valueAnswers.hedonism ?? derivedValues.hedonism ?? 0.5,
|
|
3400
|
-
achievement: session.valueAnswers.achievement ?? derivedValues.achievement ?? 0.5,
|
|
3401
|
-
power: session.valueAnswers.power ?? derivedValues.power ?? 0.5,
|
|
3402
|
-
security: session.valueAnswers.security ?? derivedValues.security ?? 0.5,
|
|
3403
|
-
conformity: session.valueAnswers.conformity ?? derivedValues.conformity ?? 0.5,
|
|
3404
|
-
tradition: session.valueAnswers.tradition ?? derivedValues.tradition ?? 0.5,
|
|
3405
|
-
benevolence: session.valueAnswers.benevolence ?? derivedValues.benevolence ?? 0.5,
|
|
3406
|
-
universalism: session.valueAnswers.universalism ?? derivedValues.universalism ?? 0.5,
|
|
3407
|
-
};
|
|
3408
|
-
const personaName = session.personaName;
|
|
3409
|
-
const duration = Date.now() - session.startedAt;
|
|
3410
|
-
clearQuestionnaireSession(sessionId);
|
|
3411
|
-
return {
|
|
3412
|
-
content: [{
|
|
3413
|
-
type: "text",
|
|
3414
|
-
text: JSON.stringify({
|
|
3415
|
-
questionnaire_complete: true,
|
|
3416
|
-
persona_name: personaName,
|
|
3417
|
-
duration_seconds: Math.round(duration / 1000),
|
|
3418
|
-
traits,
|
|
3419
|
-
values,
|
|
3420
|
-
instruction: "Persona has been created with traits AND values. Use with cognitive_journey_init.",
|
|
3421
|
-
}, null, 2),
|
|
3422
|
-
}],
|
|
3423
|
-
};
|
|
3424
|
-
}
|
|
3425
|
-
const answeredCount = session.phase === "traits"
|
|
3426
|
-
? session.currentIndex
|
|
3427
|
-
: session.questions.length + session.currentIndex;
|
|
3428
|
-
if (session.phase === "traits") {
|
|
3429
|
-
const nextQuestion = session.questions[session.currentIndex];
|
|
3430
|
-
const thirdPersonQuestion = convertToThirdPerson(nextQuestion.question);
|
|
3431
|
-
setQuestionnaireSession(sessionId, session);
|
|
3432
|
-
return {
|
|
3433
|
-
content: [{
|
|
3434
|
-
type: "text",
|
|
3435
|
-
text: `ACTION REQUIRED: Use your AskUserQuestion tool.
|
|
3436
|
-
|
|
3437
|
-
Question ${answeredCount + 1} of ${totalQuestions} (Trait: ${nextQuestion.trait})
|
|
3438
|
-
"${thirdPersonQuestion}"
|
|
3439
|
-
|
|
3440
|
-
Header: "${getTraitHeader(nextQuestion.trait)}"
|
|
3441
|
-
|
|
3442
|
-
Options:
|
|
3443
|
-
${nextQuestion.options.map((o, i) => `${i + 1}. "${o.label}" - ${o.description}`).join("\n")}
|
|
3444
|
-
|
|
3445
|
-
Progress: ${Math.round((answeredCount / totalQuestions) * 100)}% complete`,
|
|
3446
|
-
}],
|
|
3447
|
-
};
|
|
3448
|
-
}
|
|
3449
|
-
else {
|
|
3450
|
-
const nextValueQ = session.valueQuestions[session.currentIndex];
|
|
3451
|
-
setQuestionnaireSession(sessionId, session);
|
|
3452
|
-
return {
|
|
3453
|
-
content: [{
|
|
3454
|
-
type: "text",
|
|
3455
|
-
text: `ACTION REQUIRED: Use your AskUserQuestion tool.
|
|
3456
|
-
|
|
3457
|
-
Question ${answeredCount + 1} of ${totalQuestions} (Value: ${nextValueQ.value})
|
|
3458
|
-
"${nextValueQ.question}"
|
|
3459
|
-
|
|
3460
|
-
Header: "${nextValueQ.value.charAt(0).toUpperCase() + nextValueQ.value.slice(1)}"
|
|
3461
|
-
|
|
3462
|
-
Options:
|
|
3463
|
-
${nextValueQ.options.map((o, i) => `${i + 1}. "${o.label}" - ${o.description}`).join("\n")}
|
|
3464
|
-
|
|
3465
|
-
Progress: ${Math.round((answeredCount / totalQuestions) * 100)}% complete`,
|
|
3466
|
-
}],
|
|
3467
|
-
};
|
|
3468
|
-
}
|
|
3469
|
-
});
|
|
3470
|
-
server.tool("persona_create_from_description", "Create a persona from a text description. Returns trait reference for manual inference.", {
|
|
3471
|
-
persona_name: z.string().describe("Name for the new persona"),
|
|
3472
|
-
description: z.string().describe("Text description of the persona"),
|
|
3473
|
-
}, async ({ persona_name, description }) => {
|
|
3474
|
-
const traitInfo = TRAIT_REFERENCE_MATRIX.map(trait => ({
|
|
3475
|
-
name: trait.name,
|
|
3476
|
-
description: trait.description,
|
|
3477
|
-
levels: trait.levels.map(l => ({ value: l.value, label: l.label, behaviors: l.behaviors.slice(0, 2) })),
|
|
3478
|
-
}));
|
|
3479
|
-
return {
|
|
3480
|
-
content: [{
|
|
3481
|
-
type: "text",
|
|
3482
|
-
text: JSON.stringify({
|
|
3483
|
-
mode: "manual_inference",
|
|
3484
|
-
persona_name,
|
|
3485
|
-
user_description: description,
|
|
3486
|
-
instruction: "Based on the description, infer trait values (0.0-1.0) and return via persona_create_submit_traits.",
|
|
3487
|
-
trait_reference: traitInfo,
|
|
3488
|
-
follow_up_tool: "persona_create_submit_traits",
|
|
3489
|
-
}, null, 2),
|
|
3490
|
-
}],
|
|
3491
|
-
};
|
|
3492
|
-
});
|
|
3493
|
-
server.tool("persona_create_submit_traits", "Submit manually inferred traits for a persona.", {
|
|
3494
|
-
persona_name: z.string().describe("Name for the persona"),
|
|
3495
|
-
traits: z.record(z.string(), z.number().min(0).max(1)).describe("Object with trait names as keys and values 0.0-1.0"),
|
|
3496
|
-
values: z.record(z.string(), z.number().min(0).max(1)).optional().describe("Optional Schwartz values"),
|
|
3497
|
-
}, async ({ persona_name, traits, values }) => {
|
|
3498
|
-
const coreTraits = ["patience", "riskTolerance", "comprehension"];
|
|
3499
|
-
const missingCore = coreTraits.filter(t => !(t in traits));
|
|
3500
|
-
if (missingCore.length > 0) {
|
|
3501
|
-
return {
|
|
3502
|
-
content: [{
|
|
3503
|
-
type: "text",
|
|
3504
|
-
text: JSON.stringify({
|
|
3505
|
-
error: `Missing core traits: ${missingCore.join(", ")}`,
|
|
3506
|
-
instruction: "Include at least patience, riskTolerance, and comprehension",
|
|
3507
|
-
}, null, 2),
|
|
3508
|
-
}],
|
|
3509
|
-
};
|
|
3510
|
-
}
|
|
3511
|
-
const fullTraits = buildTraitsFromAnswers(traits);
|
|
3512
|
-
const derivedResult = deriveValuesFromTraits(fullTraits);
|
|
3513
|
-
const derivedValues = derivedResult.values;
|
|
3514
|
-
const fullValues = {
|
|
3515
|
-
selfDirection: values?.selfDirection ?? derivedValues.selfDirection ?? 0.5,
|
|
3516
|
-
stimulation: values?.stimulation ?? derivedValues.stimulation ?? 0.5,
|
|
3517
|
-
hedonism: derivedValues.hedonism ?? 0.5,
|
|
3518
|
-
achievement: values?.achievement ?? derivedValues.achievement ?? 0.5,
|
|
3519
|
-
power: derivedValues.power ?? 0.5,
|
|
3520
|
-
security: values?.security ?? derivedValues.security ?? 0.5,
|
|
3521
|
-
conformity: values?.conformity ?? derivedValues.conformity ?? 0.5,
|
|
3522
|
-
tradition: derivedValues.tradition ?? 0.5,
|
|
3523
|
-
benevolence: derivedValues.benevolence ?? 0.5,
|
|
3524
|
-
universalism: derivedValues.universalism ?? 0.5,
|
|
3525
|
-
};
|
|
3526
|
-
return {
|
|
3527
|
-
content: [{
|
|
3528
|
-
type: "text",
|
|
3529
|
-
text: JSON.stringify({
|
|
3530
|
-
persona_name,
|
|
3531
|
-
traits: fullTraits,
|
|
3532
|
-
values: fullValues,
|
|
3533
|
-
provided_traits: Object.keys(traits).length,
|
|
3534
|
-
defaulted_traits: Object.keys(fullTraits).length - Object.keys(traits).length,
|
|
3535
|
-
instruction: "Persona traits AND values are ready. Use with cognitive_journey_init.",
|
|
3536
|
-
}, null, 2),
|
|
3537
|
-
}],
|
|
3538
|
-
};
|
|
3539
|
-
});
|
|
3540
|
-
server.tool("persona_create_cancel", "Cancel the current questionnaire session.", {}, async () => {
|
|
3541
|
-
const sessionId = "local-session";
|
|
3542
|
-
const session = getQuestionnaireSession(sessionId);
|
|
3543
|
-
if (!session) {
|
|
3544
|
-
return {
|
|
3545
|
-
content: [{
|
|
3546
|
-
type: "text",
|
|
3547
|
-
text: JSON.stringify({ message: "No questionnaire session to cancel" }, null, 2),
|
|
3548
|
-
}],
|
|
3549
|
-
};
|
|
3550
|
-
}
|
|
3551
|
-
const personaName = session.personaName;
|
|
3552
|
-
const progress = session.currentIndex;
|
|
3553
|
-
clearQuestionnaireSession(sessionId);
|
|
3554
|
-
return {
|
|
3555
|
-
content: [{
|
|
3556
|
-
type: "text",
|
|
3557
|
-
text: JSON.stringify({
|
|
3558
|
-
cancelled: true,
|
|
3559
|
-
persona_name: personaName,
|
|
3560
|
-
progress_lost: `${progress} answers discarded`,
|
|
3561
|
-
instruction: "Questionnaire cancelled. Use persona_create_start to begin a new persona.",
|
|
3562
|
-
}, null, 2),
|
|
3563
|
-
}],
|
|
3564
|
-
};
|
|
3565
|
-
});
|
|
3566
|
-
server.tool("persona_traits_list", "List all available cognitive traits with their descriptions and value levels.", {
|
|
3567
|
-
format: z.enum(["summary", "detailed"]).optional().describe("Summary (names only) or detailed (with levels)"),
|
|
3568
|
-
}, async ({ format = "summary" }) => {
|
|
3569
|
-
if (format === "summary") {
|
|
3570
|
-
const traits = TRAIT_REFERENCE_MATRIX.map(t => ({
|
|
3571
|
-
name: t.name,
|
|
3572
|
-
description: t.description,
|
|
3573
|
-
}));
|
|
3574
|
-
return {
|
|
3575
|
-
content: [{
|
|
3576
|
-
type: "text",
|
|
3577
|
-
text: JSON.stringify({ count: traits.length, traits }, null, 2),
|
|
3578
|
-
}],
|
|
3579
|
-
};
|
|
3580
|
-
}
|
|
3581
|
-
const traits = TRAIT_REFERENCE_MATRIX.map(t => ({
|
|
3582
|
-
name: t.name,
|
|
3583
|
-
description: t.description,
|
|
3584
|
-
researchBasis: t.researchBasis,
|
|
3585
|
-
levels: t.levels.map(l => ({
|
|
3586
|
-
value: l.value,
|
|
3587
|
-
label: l.label,
|
|
3588
|
-
behaviors: l.behaviors,
|
|
3589
|
-
})),
|
|
3590
|
-
}));
|
|
3591
|
-
return {
|
|
3592
|
-
content: [{
|
|
3593
|
-
type: "text",
|
|
3594
|
-
text: JSON.stringify({ count: traits.length, traits }, null, 2),
|
|
3595
|
-
}],
|
|
3596
|
-
};
|
|
3597
|
-
});
|
|
3598
2722
|
// =========================================================================
|
|
3599
2723
|
// Security Tools (mcp-guardian integration)
|
|
3600
2724
|
// =========================================================================
|