@unified-product-graph/mcp-server 0.7.1 → 0.7.4
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/CHANGELOG.md +2 -2
- package/README.md +11 -11
- package/TOOLS.md +11 -11
- package/dist/index.js +930 -911
- package/dist/index.js.map +1 -1
- package/dist/preflight.js +1 -1
- package/dist/preflight.js.map +1 -1
- package/dist/tools-manifest.json +34 -34
- package/package.json +1 -1
- package/scripts/claudemd-snippet.md +8 -8
- package/scripts/install-skills.sh +7 -7
- package/skills/upg/SKILL.md +30 -30
- package/skills/upg-analytics/SKILL.md +11 -11
- package/skills/upg-capture/SKILL.md +19 -19
- package/skills/upg-connect/SKILL.md +6 -6
- package/skills/upg-context/SKILL.md +51 -51
- package/skills/upg-context-intelligence/SKILL.md +43 -43
- package/skills/upg-design-system/SKILL.md +21 -21
- package/skills/upg-diff/SKILL.md +12 -12
- package/skills/upg-discover/SKILL.md +10 -10
- package/skills/upg-explore/SKILL-DETAIL.md +9 -9
- package/skills/upg-explore/SKILL.md +14 -14
- package/skills/upg-export/SKILL.md +34 -34
- package/skills/upg-feedback/SKILL.md +17 -17
- package/skills/upg-gaps/SKILL.md +31 -31
- package/skills/upg-hypothesis/SKILL.md +10 -10
- package/skills/upg-impact/SKILL.md +30 -30
- package/skills/upg-import/SKILL.md +14 -14
- package/skills/upg-init/SKILL.md +40 -40
- package/skills/upg-inspect/SKILL.md +9 -9
- package/skills/upg-journey/SKILL.md +21 -21
- package/skills/upg-launch/SKILL-DETAIL.md +71 -71
- package/skills/upg-launch/SKILL.md +16 -16
- package/skills/upg-migrate/SKILL.md +19 -19
- package/skills/upg-okr/SKILL-DETAIL.md +27 -27
- package/skills/upg-okr/SKILL.md +10 -10
- package/skills/upg-persona/SKILL.md +20 -20
- package/skills/upg-prioritise/SKILL.md +19 -19
- package/skills/upg-pull/SKILL-DETAIL.md +21 -21
- package/skills/upg-pull/SKILL.md +5 -5
- package/skills/upg-push/SKILL-DETAIL.md +23 -23
- package/skills/upg-push/SKILL.md +6 -6
- package/skills/upg-reflect/SKILL.md +20 -20
- package/skills/upg-research/SKILL.md +37 -37
- package/skills/upg-rollback/SKILL.md +19 -19
- package/skills/upg-run/SKILL.md +14 -14
- package/skills/upg-schema-changelog/SKILL.md +29 -29
- package/skills/upg-schema-consolidate/SKILL.md +18 -18
- package/skills/upg-schema-edges/SKILL.md +12 -12
- package/skills/upg-schema-evolve/SKILL.md +16 -16
- package/skills/upg-schema-health/SKILL.md +22 -22
- package/skills/upg-schema-update/SKILL.md +24 -24
- package/skills/upg-snapshot/SKILL.md +8 -8
- package/skills/upg-status/SKILL.md +31 -31
- package/skills/upg-strategy/SKILL.md +26 -26
- package/skills/upg-template/SKILL.md +21 -21
- package/skills/upg-trace/SKILL.md +22 -22
- package/skills/upg-tree/SKILL.md +18 -18
- package/skills/upg-verify/SKILL.md +42 -42
- package/skills/upg-workspace/SKILL.md +12 -12
package/dist/preflight.js
CHANGED
|
@@ -18,7 +18,7 @@ for (const [label, specifier] of REQUIRED_DEPS) {
|
|
|
18
18
|
if (missing.length > 0) {
|
|
19
19
|
process.stderr.write(
|
|
20
20
|
`
|
|
21
|
-
\u256D\u2500 UPG MCP Server
|
|
21
|
+
\u256D\u2500 UPG MCP Server: missing dependencies \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E
|
|
22
22
|
\u2502 \u2502
|
|
23
23
|
` + missing.map(
|
|
24
24
|
(d) => `\u2502 \u2717 ${d}${" ".repeat(Math.max(0, 52 - d.length))}\u2502
|
package/dist/preflight.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/preflight.ts"],"sourcesContent":["/**\n * Preflight dependency check for the UPG MCP Server.\n *\n * ES module imports are hoisted, so if a dependency is missing the process\n * crashes before any error-handling code runs, producing silent failure\n * in Claude Code. This script checks critical deps first, prints a\n * human-readable message on failure, then dynamically imports the real\n * entry point.\n */\n\nconst REQUIRED_DEPS: Array<[label: string, specifier: string]> = [\n ['@modelcontextprotocol/sdk', '@modelcontextprotocol/sdk/server'],\n ['@unified-product-graph/core', '@unified-product-graph/core'],\n ['chokidar', 'chokidar'],\n ['nanoid', 'nanoid'],\n]\n\nconst missing: string[] = []\n\nfor (const [label, specifier] of REQUIRED_DEPS) {\n try {\n await import(specifier)\n } catch {\n missing.push(label)\n }\n}\n\nif (missing.length > 0) {\n process.stderr.write(\n `\\n╭─ UPG MCP Server
|
|
1
|
+
{"version":3,"sources":["../src/preflight.ts"],"sourcesContent":["/**\n * Preflight dependency check for the UPG MCP Server.\n *\n * ES module imports are hoisted, so if a dependency is missing the process\n * crashes before any error-handling code runs, producing silent failure\n * in Claude Code. This script checks critical deps first, prints a\n * human-readable message on failure, then dynamically imports the real\n * entry point.\n */\n\nconst REQUIRED_DEPS: Array<[label: string, specifier: string]> = [\n ['@modelcontextprotocol/sdk', '@modelcontextprotocol/sdk/server'],\n ['@unified-product-graph/core', '@unified-product-graph/core'],\n ['chokidar', 'chokidar'],\n ['nanoid', 'nanoid'],\n]\n\nconst missing: string[] = []\n\nfor (const [label, specifier] of REQUIRED_DEPS) {\n try {\n await import(specifier)\n } catch {\n missing.push(label)\n }\n}\n\nif (missing.length > 0) {\n process.stderr.write(\n `\\n╭─ UPG MCP Server: missing dependencies ─────────────────╮\\n` +\n `│ │\\n` +\n missing.map((d) =>\n `│ ✗ ${d}${' '.repeat(Math.max(0, 52 - d.length))}│\\n`\n ).join('') +\n `│ │\\n` +\n `│ Run \\`npm install\\` in the project root to fix this. │\\n` +\n `╰──────────────────────────────────────────────────────────╯\\n\\n`,\n )\n process.exit(1)\n}\n\n// All deps present; boot the real server\nawait import('./index.js')\n\nexport {}\n"],"mappings":";;;AAUA,IAAM,gBAA2D;AAAA,EAC/D,CAAC,6BAA6B,kCAAkC;AAAA,EAChE,CAAC,+BAA+B,6BAA6B;AAAA,EAC7D,CAAC,YAAY,UAAU;AAAA,EACvB,CAAC,UAAU,QAAQ;AACrB;AAEA,IAAM,UAAoB,CAAC;AAE3B,WAAW,CAAC,OAAO,SAAS,KAAK,eAAe;AAC9C,MAAI;AACF,UAAM,OAAO;AAAA,EACf,QAAQ;AACN,YAAQ,KAAK,KAAK;AAAA,EACpB;AACF;AAEA,IAAI,QAAQ,SAAS,GAAG;AACtB,UAAQ,OAAO;AAAA,IACb;AAAA;AAAA;AAAA,IAEA,QAAQ;AAAA,MAAI,CAAC,MACX,kBAAQ,CAAC,GAAG,IAAI,OAAO,KAAK,IAAI,GAAG,KAAK,EAAE,MAAM,CAAC,CAAC;AAAA;AAAA,IACpD,EAAE,KAAK,EAAE,IACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAGF;AACA,UAAQ,KAAK,CAAC;AAChB;AAGA,MAAM,OAAO,YAAY;","names":[]}
|
package/dist/tools-manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "2",
|
|
3
3
|
"package": "@unified-product-graph/mcp-server",
|
|
4
|
-
"package_version": "0.7.
|
|
4
|
+
"package_version": "0.7.4",
|
|
5
5
|
"tool_count": 93,
|
|
6
6
|
"domains": [
|
|
7
7
|
"context",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
{
|
|
36
36
|
"description": "Live call against the Notion example graph.",
|
|
37
37
|
"input": "{}",
|
|
38
|
-
"output": "{\n \"product\": {\n \"title\": \"Notion (SATURATED test graph)\",\n \"stage\": \"concept\"\n },\n \"counts\": {\n \"total_nodes\": 2054,\n \"total_edges\":
|
|
38
|
+
"output": "{\n \"product\": {\n \"title\": \"Notion (SATURATED test graph)\",\n \"stage\": \"concept\"\n },\n \"counts\": {\n \"total_nodes\": 2054,\n \"total_edges\": 3216,\n \"by_type\": {\n \"product\": 13,\n \"capability\": 20,\n \"value_stream\": 3,\n \"decision\": 13,\n \"evidence\": 10,\n \"assumption\": 30,\n \"outcome\": 6,\n \"document\": 9,\n \"objective\": 6,\n \"key_result\": 14,\n \"design_component\": 15,\n \"hypothesis\": 6,\n \"experiment\": 5,\n \"experiment_plan\": 13,\n \"job\": 10,\n \"bounded_context\": 13,\n \"initiative\": 11,\n \"strategic_pillar\": 6,\n \"test_plan\": 8,\n \"screen\": 15,\n \"experiment_run\": 18,\n \"design_system\": 4,\n \"team\": 1,\n \"compliance_requirement\": 5,\n \"workspace\": 3,\n \"epic\": 4,\n \"bug\": 6,\n \"task\": 3,\n \"feature_area\": 3,\n \"mission\": 2,\n \"desired_outcome\": 4,\n \"model_comparison\": 3,\n \"agent_session\": 3,\n \"learning\": 17,\n \"research_plan\": 6,\n \"constraint\": 3,\n \"stakeholder\": 10,\n \"feature\": 12,\n \"security_review\": 8,\n \"metric\": 23,\n \"person\": 215,\n \"technical_debt_item\": 12,\n \"risk\": 9,\n \"service\": 11,\n \"opportunity\": 7,\n \"solution\": 11,\n \"feasibility_study\": 3,\n \"design_sprint\": 3,\n \"prototype\": 8,\n \"design_concept\": 7,\n \"vision\": 1,\n… (truncated)"
|
|
39
39
|
}
|
|
40
40
|
],
|
|
41
41
|
"warnings": [],
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
{
|
|
70
70
|
"description": "Live call against the Notion example graph.",
|
|
71
71
|
"input": "{}",
|
|
72
|
-
"output": "## Notion (SATURATED test graph)\n\nStage: concept\n\nLens: product\n\n### 🧭 Product Lens\n- Personas: 4\n- Outcomes: 6\n- Hypotheses: 6 (0 validated)\n\n### Graph Stats\n- Nodes: 2054\n- Edges:
|
|
72
|
+
"output": "## Notion (SATURATED test graph)\n\nStage: concept\n\nLens: product\n\n### 🧭 Product Lens\n- Personas: 4\n- Outcomes: 6\n- Hypotheses: 6 (0 validated)\n\n### Graph Stats\n- Nodes: 2054\n- Edges: 3216\n- Entity types: 312\n\n### Entities by Type\n- Person (`person`): 215\n- Journey Step (`journey_step`): 53\n- Test Case (`test_case`): 48\n- Screen State (`screen_state`): 36\n- Assumption (`assumption`): 30\n- Journey Phase (`journey_phase`): 28\n- Journey Action (`journey_action`): 28\n- Interaction Spec (`interaction_spec`): 28\n- Metric (`metric`): 23\n- Test Result (`test_result`): 23\n- Capability (`capability`): 20\n- Participant (`participant`): 19\n- Regression Test (`regression_test`): 19\n- Experiment Run (`experiment_run`): 18\n- Alert Rule (`alert_rule`): 18\n- Validated Learning (`learning`): 17\n- Observation (`observation`): 17\n- Survey Response (`survey_response`): 17\n- Annotation (`annotation`): 17\n- Vulnerability (`vulnerability`): 16\n- Design Component (`design_component`): 15\n- Screen (`screen`): 15\n- Monitor (`monitor`): 15\n- Research Question (`research_question`): 15\n- Service Level Indicator (`service_level_indicator`): 15\n- Error Budget (`error_budget`): 15\n- Key Result (`key_result`): 14\n- Product (`product`): 13\n- Decision (`decision`): 13\n- Experiment Plan (`experiment_plan`): 13\n- Bounded Context (`bounded_context`): 13\n- Insight (`insight`): 13\n- Theme (`theme`): 13\n- Feature\n… (truncated)"
|
|
73
73
|
}
|
|
74
74
|
],
|
|
75
75
|
"warnings": [],
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
86
|
"name": "get_session_context",
|
|
87
|
-
"description": "Read session context: which skills ran, what was recommended, current focus area. Returns `recommendations_to_avoid
|
|
87
|
+
"description": "Read session context: which skills ran, what was recommended, current focus area. Returns `recommendations_to_avoid`; the deduped list of recommendations already given this session. Pick your next recommendation NOT in that array (data-layer dedup, not prose).",
|
|
88
88
|
"domain": "context",
|
|
89
89
|
"inputSchema": {
|
|
90
90
|
"type": "object",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
],
|
|
105
105
|
"source": "src/tools/context.ts:295",
|
|
106
106
|
"symbol": "getSessionContext",
|
|
107
|
-
"returns": "JSON: `{ lens, skills_invoked, recommendations_given,\nrecommendations_to_avoid, focus_area, custom, skills_count, last_skill,\nlast_recommendation }`. `recommendations_to_avoid` is the deduped list of\nevery recommendation given this session
|
|
107
|
+
"returns": "JSON: `{ lens, skills_invoked, recommendations_given,\nrecommendations_to_avoid, focus_area, custom, skills_count, last_skill,\nlast_recommendation }`. `recommendations_to_avoid` is the deduped list of\nevery recommendation given this session; runners should filter their\nnext recommendation against this array rather than re-deriving the\ndedup rule from prose.",
|
|
108
108
|
"atomicity": "atomic (read-only)"
|
|
109
109
|
},
|
|
110
110
|
{
|
|
@@ -255,7 +255,7 @@
|
|
|
255
255
|
{
|
|
256
256
|
"description": "Live call against the Notion example graph.",
|
|
257
257
|
"input": "{\n \"nodes\": [\n {\n \"type\": \"person\",\n \"title\": \"Example node A\"\n },\n {\n \"type\": \"person\",\n \"title\": \"Example node B\"\n }\n ]\n}",
|
|
258
|
-
"output": "{\n \"created\": [\n {\n \"id\": \"
|
|
258
|
+
"output": "{\n \"created\": [\n {\n \"id\": \"n_psZXNbg3DydBoRqy\",\n \"type\": \"person\",\n \"title\": \"Example node A\"\n },\n {\n \"id\": \"n_UJalQ1iIh93K5eJ9\",\n \"type\": \"person\",\n \"title\": \"Example node B\"\n }\n ],\n \"edges\": [],\n \"count\": 2,\n \"warnings\": [\n \"Created 2 nodes with no edges; they are orphans. Use the edges[] array in this call to link them. See get_entity_schema(<type>) for canonical edges per type.\"\n ]\n}"
|
|
259
259
|
}
|
|
260
260
|
],
|
|
261
261
|
"warnings": [],
|
|
@@ -294,7 +294,7 @@
|
|
|
294
294
|
{
|
|
295
295
|
"description": "Live call against the Notion example graph.",
|
|
296
296
|
"input": "{\n \"node_ids\": [\n \"1c051617-6cb7-4a59-b0a1-7779f404145b\"\n ]\n}",
|
|
297
|
-
"output": "{\n \"deleted\": [\n {\n \"id\": \"1c051617-6cb7-4a59-b0a1-7779f404145b\",\n \"title\": \"Real-time multi-cursor collaboration\"\n }\n ],\n \"edges_removed\":
|
|
297
|
+
"output": "{\n \"deleted\": [\n {\n \"id\": \"1c051617-6cb7-4a59-b0a1-7779f404145b\",\n \"title\": \"Real-time multi-cursor collaboration\"\n }\n ],\n \"edges_removed\": 10,\n \"count\": 1\n}"
|
|
298
298
|
}
|
|
299
299
|
],
|
|
300
300
|
"warnings": [],
|
|
@@ -421,7 +421,7 @@
|
|
|
421
421
|
{
|
|
422
422
|
"description": "Live call against the Notion example graph.",
|
|
423
423
|
"input": "{\n \"type\": \"person\",\n \"title\": \"Example node\"\n}",
|
|
424
|
-
"output": "{\n \"node\": {\n \"id\": \"
|
|
424
|
+
"output": "{\n \"node\": {\n \"id\": \"n_lsZ0CjPWcrZ6Hhw8\",\n \"type\": \"person\",\n \"title\": \"Example node\",\n \"slug\": \"example-node\"\n },\n \"edge\": null\n}"
|
|
425
425
|
}
|
|
426
426
|
],
|
|
427
427
|
"warnings": [],
|
|
@@ -1377,7 +1377,7 @@
|
|
|
1377
1377
|
{
|
|
1378
1378
|
"description": "Live call against the Notion example graph.",
|
|
1379
1379
|
"input": "{\n \"title\": \"Example node\"\n}",
|
|
1380
|
-
"output": "{\n \"node\": {\n \"id\": \"
|
|
1380
|
+
"output": "{\n \"node\": {\n \"id\": \"n_ntp_s5A9-x-aKjjS\",\n \"title\": \"Example node\"\n },\n \"portfolio_file\": \"/Users/FH/Documents/_Code/tpc-emdash-packages/packages/upg-mcp-server/.upg/portfolio.upg\",\n \"written_to\": \"product_areas\"\n}"
|
|
1381
1381
|
}
|
|
1382
1382
|
],
|
|
1383
1383
|
"warnings": [],
|
|
@@ -1387,7 +1387,7 @@
|
|
|
1387
1387
|
"source": "src/tools/areas.ts:261",
|
|
1388
1388
|
"symbol": "createArea",
|
|
1389
1389
|
"returns": "JSON: `{ node, portfolio_file, written_to }`. `node` is the typed\n`UPGProductArea` record persisted to `portfolio_areas[]`.",
|
|
1390
|
-
"atomicity": "atomic per write
|
|
1390
|
+
"atomicity": "atomic per write; the portfolio file is read, mutated, and\nflushed in one pass."
|
|
1391
1391
|
},
|
|
1392
1392
|
{
|
|
1393
1393
|
"name": "get_area_context",
|
|
@@ -1466,7 +1466,7 @@
|
|
|
1466
1466
|
{
|
|
1467
1467
|
"description": "Live call against the Notion example graph.",
|
|
1468
1468
|
"input": "{}",
|
|
1469
|
-
"output": "{\n \"changes\": [\n {\n \"action\": \"create\",\n \"entity\": \"node\",\n \"id\": \"
|
|
1469
|
+
"output": "{\n \"changes\": [\n {\n \"action\": \"create\",\n \"entity\": \"node\",\n \"id\": \"n_lsZ0CjPWcrZ6Hhw8\",\n \"type\": \"person\",\n \"title\": \"Example node\",\n \"timestamp\": \"2026-05-29T20:13:19.656Z\"\n },\n {\n \"action\": \"update\",\n \"entity\": \"node\",\n \"id\": \"ec3d5479-4947-4bd9-9e77-b5ee01beb851\",\n \"type\": \"product\",\n \"title\": \"Notion (SATURATED test graph)\",\n \"timestamp\": \"2026-05-29T20:13:19.656Z\"\n },\n {\n \"action\": \"delete\",\n \"entity\": \"node\",\n \"id\": \"ec3d5479-4947-4bd9-9e77-b5ee01beb851\",\n \"type\": \"product\",\n \"title\": \"Notion (SATURATED test graph)\",\n \"timestamp\": \"2026-05-29T20:13:19.658Z\"\n },\n {\n \"action\": \"delete\",\n \"entity\": \"edge\",\n \"id\": \"1d645a2e-391b-4bc7-b0de-e15691c8a7d6\",\n \"type\": \"cascade\",\n \"timestamp\": \"2026-05-29T20:13:19.658Z\"\n },\n {\n \"action\": \"delete\",\n \"entity\": \"edge\",\n \"id\": \"b4a77a49-7d28-4926-831f-464574d927fe\",\n \"type\": \"cascade\",\n \"timestamp\": \"2026-05-29T20:13:19.658Z\"\n },\n {\n \"action\": \"delete\",\n \"entity\": \"edge\",\n \"id\": \"1ee422bc-64c1-4da1-b797-62e4d206b79c\",\n \"type\": \"cascade\",\n \"timestamp\": \"2026-05-29T20:13:19.658Z\"\n },\n {\n \"action\": \"delete\",\n \"entity\": \"edge\",\n \"id\": \"013ac760-b99a-423e-bb94-700acda058c0\",\n \"type\": \"cascade\",\n \"timestamp\":\n… (truncated)"
|
|
1470
1470
|
}
|
|
1471
1471
|
],
|
|
1472
1472
|
"warnings": [],
|
|
@@ -1598,7 +1598,7 @@
|
|
|
1598
1598
|
{
|
|
1599
1599
|
"description": "Live call against the Notion example graph.",
|
|
1600
1600
|
"input": "{\n \"name\": \"example\"\n}",
|
|
1601
|
-
"output": "{\n \"message\": \"Created product: example\",\n \"id\": \"
|
|
1601
|
+
"output": "{\n \"message\": \"Created product: example\",\n \"id\": \"p_P9zFGBICvycswgnv\",\n \"file\": \"example.upg\",\n \"slug\": \"example\",\n \"title\": \"example\",\n \"workspace_path\": \".upg/\",\n \"portfolio_attached\": false\n}"
|
|
1602
1602
|
}
|
|
1603
1603
|
],
|
|
1604
1604
|
"warnings": [],
|
|
@@ -1648,7 +1648,7 @@
|
|
|
1648
1648
|
{
|
|
1649
1649
|
"description": "Live call against the Notion example graph.",
|
|
1650
1650
|
"input": "{}",
|
|
1651
|
-
"output": "{\n \"mode\": \"single-file\",\n \"current_file\": \"
|
|
1651
|
+
"output": "{\n \"mode\": \"single-file\",\n \"current_file\": \"../../../../../../../tmp/claude-502/upg-capture-vP3Dh5/fixture.upg\",\n \"products\": [\n {\n \"file\": \"../../../../../../../tmp/claude-502/upg-capture-vP3Dh5/fixture.upg\",\n \"title\": \"Notion (SATURATED test graph)\",\n \"active\": true\n }\n ]\n}"
|
|
1652
1652
|
}
|
|
1653
1653
|
],
|
|
1654
1654
|
"warnings": [],
|
|
@@ -1865,7 +1865,7 @@
|
|
|
1865
1865
|
{
|
|
1866
1866
|
"description": "Live call against the Notion example graph.",
|
|
1867
1867
|
"input": "{\n \"type\": \"person\"\n}",
|
|
1868
|
-
"output": "{\n \"type\": \"person\",\n \"domain\": {\n \"id\": \"team_org\",\n \"label\": \"Team & Organisation\"\n },\n \"expected_properties\": {\n \"email\": {\n \"type\": \"string\",\n \"description\": \"Primary contact email. Stable identifier for de-duplication.\"\n },\n \"role_title\": {\n \"type\": \"string\",\n \"description\": \"Free-text job title. Distinct from the structured `role` entity.\"\n },\n \"time_zone\": {\n \"type\": \"string\",\n \"description\": \"IANA time zone (e.g. \\\"Europe/Berlin\\\"). Useful for capacity / on-call planning.\"\n }\n },\n \"edges_out\": [],\n \"edges_in\": [\n {\n \"edge_type\": \"node_owned_by_person\",\n \"source_type\": \"node\",\n \"reverse_verb\": \"owns\"\n }\n ],\n \"domain_guide\": {\n \"anchor_entity\": \"team\",\n \"creation_sequence\": [\n \"team\",\n \"role\",\n \"stakeholder\",\n \"person\",\n \"team_okr\",\n \"retrospective\",\n \"dependency\",\n \"department\",\n \"skill\",\n \"ceremony\",\n \"capacity_plan\"\n ],\n \"position_in_sequence\": 3,\n \"anti_patterns\": [\n {\n \"description\": \"Teams without OKRs
|
|
1868
|
+
"output": "{\n \"type\": \"person\",\n \"domain\": {\n \"id\": \"team_org\",\n \"label\": \"Team & Organisation\"\n },\n \"expected_properties\": {\n \"email\": {\n \"type\": \"string\",\n \"description\": \"Primary contact email. Stable identifier for de-duplication.\"\n },\n \"role_title\": {\n \"type\": \"string\",\n \"description\": \"Free-text job title. Distinct from the structured `role` entity.\"\n },\n \"time_zone\": {\n \"type\": \"string\",\n \"description\": \"IANA time zone (e.g. \\\"Europe/Berlin\\\"). Useful for capacity / on-call planning.\"\n }\n },\n \"edges_out\": [],\n \"edges_in\": [\n {\n \"edge_type\": \"node_owned_by_person\",\n \"source_type\": \"node\",\n \"reverse_verb\": \"owns\"\n }\n ],\n \"domain_guide\": {\n \"anchor_entity\": \"team\",\n \"creation_sequence\": [\n \"team\",\n \"role\",\n \"stakeholder\",\n \"person\",\n \"team_okr\",\n \"retrospective\",\n \"dependency\",\n \"department\",\n \"skill\",\n \"ceremony\",\n \"capacity_plan\"\n ],\n \"position_in_sequence\": 3,\n \"anti_patterns\": [\n {\n \"description\": \"Teams without OKRs: every team needs clear goals\"\n },\n {\n \"description\": \"Dependencies without both teams linked: a dependency must connect blocker and blocked\"\n },\n {\n \"description\": \"Retrospectives without action items: reflection without action is just venting\"\n }\n ]\n }\n}"
|
|
1869
1869
|
}
|
|
1870
1870
|
],
|
|
1871
1871
|
"warnings": [],
|
|
@@ -2178,7 +2178,7 @@
|
|
|
2178
2178
|
{
|
|
2179
2179
|
"description": "Live call against the Notion example graph.",
|
|
2180
2180
|
"input": "{\n \"id\": \"product\"\n}",
|
|
2181
|
-
"output": "{\n \"id\": \"product\",\n \"name\": \"Product\",\n \"description\": \"Full graph, PM vocabulary, outcome-driven workflow\",\n \"icon\": \"target\",\n \"framework_id\": \"ost\",\n \"label_overrides\": {\n \"experiment\": \"Experiment\",\n \"learning\": \"Validated Learning\"\n },\n \"visible_domains\": [],\n \"benchmark_domains\": [\n \"strategy\",\n \"user\",\n \"discovery\",\n \"validation\",\n \"market_intelligence\",\n \"product_spec\",\n \"growth\"\n ],\n \"intelligence_prompts\": [\n {\n \"condition\": \"outcomes.length === 0\",\n \"structured_condition\": {\n \"check\": {\n \"type\": \"entity_count\",\n \"entity_type\": \"outcome\",\n \"comparison\": \"zero\"\n }\n },\n \"message\": \"No outcomes defined yet. Start with what success looks like
|
|
2181
|
+
"output": "{\n \"id\": \"product\",\n \"name\": \"Product\",\n \"description\": \"Full graph, PM vocabulary, outcome-driven workflow\",\n \"icon\": \"target\",\n \"framework_id\": \"ost\",\n \"label_overrides\": {\n \"experiment\": \"Experiment\",\n \"learning\": \"Validated Learning\"\n },\n \"visible_domains\": [],\n \"benchmark_domains\": [\n \"strategy\",\n \"user\",\n \"discovery\",\n \"validation\",\n \"market_intelligence\",\n \"product_spec\",\n \"growth\"\n ],\n \"intelligence_prompts\": [\n {\n \"condition\": \"outcomes.length === 0\",\n \"structured_condition\": {\n \"check\": {\n \"type\": \"entity_count\",\n \"entity_type\": \"outcome\",\n \"comparison\": \"zero\"\n }\n },\n \"message\": \"No outcomes defined yet. Start with what success looks like: what measurable result should this product drive?\"\n },\n {\n \"condition\": \"hypotheses.untested.length > 3\",\n \"structured_condition\": {\n \"check\": {\n \"type\": \"entity_count\",\n \"entity_type\": \"hypothesis\",\n \"filter\": {\n \"status\": \"untested\"\n },\n \"comparison\": \"gt\",\n \"threshold\": 3\n }\n },\n \"message\": \"You have untested hypotheses stacking up. Pick the riskiest one and design an experiment before adding more.\"\n },\n {\n \"condition\": \"features.length > 0 && hypotheses.length === 0\",\n \"structured_condition\": {\n… (truncated)"
|
|
2182
2182
|
}
|
|
2183
2183
|
],
|
|
2184
2184
|
"warnings": [],
|
|
@@ -2251,7 +2251,7 @@
|
|
|
2251
2251
|
{
|
|
2252
2252
|
"description": "Live call against the Notion example graph.",
|
|
2253
2253
|
"input": "{\n \"id\": \"playbook:strategy-outcomes\"\n}",
|
|
2254
|
-
"output": "{\n \"id\": \"playbook:strategy-outcomes\",\n \"name\": \"Strategy & Outcomes\",\n \"version\": \"0.2.0\",\n \"description\": \"Cascade vision through themes, outcomes, objectives, key results
|
|
2254
|
+
"output": "{\n \"id\": \"playbook:strategy-outcomes\",\n \"name\": \"Strategy & Outcomes\",\n \"version\": \"0.2.0\",\n \"description\": \"Cascade vision through themes, outcomes, objectives, key results, and the bets you are making to get there.\",\n \"region\": \"strategy_outcomes\",\n \"is_canonical\": true,\n \"target_anchor_entity\": \"objective\",\n \"creation_sequence\": [\n {\n \"kind\": \"entity_sequence\",\n \"order\": 1,\n \"phase\": \"Vision & Mission\",\n \"name\": \"Vision & Mission\",\n \"prompt_hint\": \"Name what you are building toward and how you will get there. Vision is the destination; mission is the orientation. One of each, no more.\",\n \"entity_types\": [\n \"vision\",\n \"mission\"\n ]\n },\n {\n \"kind\": \"entity_sequence\",\n \"order\": 2,\n \"phase\": \"Themes\",\n \"name\": \"Themes\",\n \"prompt_hint\": \"Choose 2–4 strategic themes that focus the work. Past four, you have lost focus, not gained coverage.\",\n \"entity_types\": [\n \"strategic_theme\",\n \"strategic_pillar\"\n ]\n },\n {\n \"kind\": \"entity_sequence\",\n \"order\": 3,\n \"phase\": \"Outcomes\",\n \"name\": \"Outcomes\",\n \"prompt_hint\": \"Frame the changes in the world the product is trying to cause: shifts in behavior, perception, or position. Not features shipped.\",\n \"entity_types\": [\n \"outcome\"\n ]\n },\n {\n \"kind\": \"entity_sequence\",\n… (truncated)"
|
|
2255
2255
|
}
|
|
2256
2256
|
],
|
|
2257
2257
|
"warnings": [],
|
|
@@ -2383,7 +2383,7 @@
|
|
|
2383
2383
|
{
|
|
2384
2384
|
"description": "Live call against the Notion example graph.",
|
|
2385
2385
|
"input": "{}",
|
|
2386
|
-
"output": "{\n \"upg_version\": \"0.
|
|
2386
|
+
"output": "{\n \"upg_version\": \"0.7.3\",\n \"markdown_format_version\": \"0.1\",\n \"entity_count\": 312,\n \"edge_count\": 946,\n \"domain_count\": 36,\n \"region_count\": 10\n}"
|
|
2387
2387
|
}
|
|
2388
2388
|
],
|
|
2389
2389
|
"warnings": [],
|
|
@@ -2483,7 +2483,7 @@
|
|
|
2483
2483
|
},
|
|
2484
2484
|
{
|
|
2485
2485
|
"name": "inspect",
|
|
2486
|
-
"description": "[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing inspection, invoke the /upg-inspect skill instead of calling this tool directly.
|
|
2486
|
+
"description": "[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing inspection, invoke the /upg-inspect skill instead of calling this tool directly. Inspect approach: path of arrival to \"what's broken?\". Returns the Inspect record + invocation params in the family-resemblance envelope. The LLM consumes `signature_hint` and emits `{ violations: [{ severity, kind, entity_id, description, fix_hint }] }` against `UPG_ANTI_PATTERNS` + the live graph. Optional `region` or `entities[]` scope the audit.",
|
|
2487
2487
|
"domain": "spec",
|
|
2488
2488
|
"inputSchema": {
|
|
2489
2489
|
"type": "object",
|
|
@@ -2785,7 +2785,7 @@
|
|
|
2785
2785
|
{
|
|
2786
2786
|
"description": "Live call against the Notion example graph.",
|
|
2787
2787
|
"input": "{}",
|
|
2788
|
-
"output": "{\n \"migrations\": [\n {\n \"kind\": \"rename\",\n \"from\": \"
|
|
2788
|
+
"output": "{\n \"migrations\": [\n {\n \"kind\": \"rename\",\n \"from\": \"task_implements_story_statement\",\n \"to\": \"task_implements_user_story\",\n \"since\": \"0.7.0\"\n },\n {\n \"kind\": \"rename\",\n \"from\": \"epic_specified_by_story_statement\",\n \"to\": \"epic_specified_by_user_story\",\n \"since\": \"0.7.0\"\n },\n {\n \"kind\": \"rename\",\n \"from\": \"story_statement_verified_by_acceptance_criterion\",\n \"to\": \"user_story_verified_by_acceptance_criterion\",\n \"since\": \"0.7.0\"\n },\n {\n \"kind\": \"rename\",\n \"from\": \"test_case_covers_story_statement\",\n \"to\": \"test_case_covers_user_story\",\n \"since\": \"0.7.0\"\n },\n {\n \"kind\": \"rename\",\n \"from\": \"solution_proposes_hypothesis_claim\",\n \"to\": \"solution_proposes_hypothesis\",\n \"since\": \"0.4.0\"\n },\n {\n \"kind\": \"rename\",\n \"from\": \"hypothesis_claim_requires_experiment_plan\",\n \"to\": \"hypothesis_requires_experiment_plan\",\n \"since\": \"0.4.0\"\n },\n {\n \"kind\": \"rename\",\n \"from\": \"hypothesis_claim_planned_via_test_plan\",\n \"to\": \"hypothesis_planned_via_test_plan\",\n \"since\": \"0.4.0\"\n },\n {\n \"kind\": \"rename\",\n \"from\": \"hypothesis_claim_investigated_via_research_plan\",\n \"to\": \"hypothesis_investigated_via_research_plan\",\n \"since\": \"0.4.0\"\n },\n {\n \"kind\": \"rename\",\n \"from\":\n… (truncated)"
|
|
2789
2789
|
}
|
|
2790
2790
|
],
|
|
2791
2791
|
"warnings": [],
|
|
@@ -2823,7 +2823,7 @@
|
|
|
2823
2823
|
{
|
|
2824
2824
|
"description": "Live call against the Notion example graph.",
|
|
2825
2825
|
"input": "{}",
|
|
2826
|
-
"output": "{\n \"count\":
|
|
2826
|
+
"output": "{\n \"count\": 946,\n \"edges\": [\n {\n \"type\": \"product_targets_persona\",\n \"forward_verb\": \"targets\",\n \"reverse_verb\": \"targeted_by\",\n \"classification\": \"semantic\",\n \"source_type\": \"product\",\n \"target_type\": \"persona\"\n },\n {\n \"type\": \"persona_pursues_job\",\n \"forward_verb\": \"pursues\",\n \"reverse_verb\": \"pursued_by\",\n \"classification\": \"semantic\",\n \"source_type\": \"persona\",\n \"target_type\": \"job\"\n },\n {\n \"type\": \"persona_experiences_need\",\n \"forward_verb\": \"experiences\",\n \"reverse_verb\": \"experienced_by\",\n \"classification\": \"semantic\",\n \"source_type\": \"persona\",\n \"target_type\": \"need\"\n },\n {\n \"type\": \"persona_aspires_to_desired_outcome\",\n \"forward_verb\": \"aspires_to\",\n \"reverse_verb\": \"aspirational_for\",\n \"classification\": \"hierarchy\",\n \"source_type\": \"persona\",\n \"target_type\": \"desired_outcome\"\n },\n {\n \"type\": \"persona_incurs_switching_cost\",\n \"forward_verb\": \"incurs\",\n \"reverse_verb\": \"incurred_by\",\n \"classification\": \"hierarchy\",\n \"source_type\": \"persona\",\n \"target_type\": \"switching_cost\"\n },\n {\n \"type\": \"job_surfaces_need\",\n \"forward_verb\": \"surfaces\",\n \"reverse_verb\": \"surfaces_from\",\n \"classification\": \"causal\",\n \"source_type\": \"job\",\n \"target_type\": \"need\"\n },\n {\n… (truncated)"
|
|
2827
2827
|
}
|
|
2828
2828
|
],
|
|
2829
2829
|
"warnings": [],
|
|
@@ -2951,7 +2951,7 @@
|
|
|
2951
2951
|
},
|
|
2952
2952
|
{
|
|
2953
2953
|
"name": "list_frameworks",
|
|
2954
|
-
"description": "List the canonical `UPGFramework` definitions
|
|
2954
|
+
"description": "List the canonical `UPGFramework` definitions; the 34 curated, famous product frameworks that anchor the public catalog (spanning strategy, discovery, prioritisation, design, growth, engineering, and reflection classics). Paginated (default 50, max 200). Cursor is opaque: pass `next_cursor` from a previous response. Optional `category` is exact-match against `UPGFramework.category` and applies before pagination.",
|
|
2955
2955
|
"domain": "spec",
|
|
2956
2956
|
"inputSchema": {
|
|
2957
2957
|
"type": "object",
|
|
@@ -2975,7 +2975,7 @@
|
|
|
2975
2975
|
{
|
|
2976
2976
|
"description": "Live call against the Notion example graph.",
|
|
2977
2977
|
"input": "{}",
|
|
2978
|
-
"output": "{\n \"total\":
|
|
2978
|
+
"output": "{\n \"total\": 34,\n \"count\": 34,\n \"frameworks\": [\n {\n \"id\": \"opportunity-solution-tree\",\n \"approach_ids\": [\n \"trace\"\n ],\n \"name\": \"Opportunity Solution Tree\",\n \"version\": \"1.0.0\",\n \"description\": \"Map desired outcomes to opportunities, then branch into solutions and experiments. Ensures every solution traces back to a real user need.\",\n \"category\": \"discovery\",\n \"origin\": {\n \"type\": \"practitioner\",\n \"attribution\": \"Teresa Torres\",\n \"description\": \"Introduced in Continuous Discovery Habits. Maps outcomes to opportunities, solutions, and experiments.\",\n \"url\": \"https://www.producttalk.org/opportunity-solution-tree/\",\n \"year\": 2021,\n \"license\": \"published_methodology\"\n },\n \"tags\": [\n \"discovery\",\n \"tree\"\n ],\n \"slots\": [\n {\n \"label\": \"Root Outcome\",\n \"entityTypeId\": \"outcome\",\n \"description\": \"The desired business or user outcome\"\n },\n {\n \"label\": \"Opportunities\",\n \"entityTypeId\": \"opportunity\",\n \"description\": \"User needs, pain points, or desires\"\n },\n {\n \"label\": \"Solutions\",\n \"entityTypeId\": \"solution\",\n \"description\": \"Ideas to address each opportunity\"\n },\n {\n \"label\": \"Experiments\",\n \"entityTypeId\":\n… (truncated)"
|
|
2979
2979
|
}
|
|
2980
2980
|
],
|
|
2981
2981
|
"warnings": [],
|
|
@@ -3041,7 +3041,7 @@
|
|
|
3041
3041
|
{
|
|
3042
3042
|
"description": "Live call against the Notion example graph.",
|
|
3043
3043
|
"input": "{}",
|
|
3044
|
-
"output": "{\n \"total\":
|
|
3044
|
+
"output": "{\n \"total\": 188,\n \"lifecycles\": [\n {\n \"entity_type\": \"product\",\n \"initial_phase\": \"concept\",\n \"terminal_phases\": [\n \"sunset\"\n ],\n \"phases\": [\n {\n \"id\": \"concept\",\n \"label\": \"Concept\",\n \"description\": \"Napkin idea. Problem shape and solution sketch, pre-validation.\",\n \"transitions_to\": [\n \"validation\",\n \"build\",\n \"beta\",\n \"launch\",\n \"growth\",\n \"mature\",\n \"sunset\"\n ]\n },\n {\n \"id\": \"validation\",\n \"label\": \"Validation\",\n \"description\": \"Testing demand. User conversations and experiments pressure-test assumptions before build commits.\",\n \"transitions_to\": [\n \"build\",\n \"beta\",\n \"launch\",\n \"growth\",\n \"mature\",\n \"sunset\"\n ]\n },\n {\n \"id\": \"build\",\n \"label\": \"Build\",\n \"description\": \"Actively developing v1. Core functionality is being authored, pre-user.\",\n \"transitions_to\": [\n \"beta\",\n \"launch\",\n \"growth\",\n \"mature\",\n \"sunset\"\n ]\n },\n {\n \"id\": \"beta\",\n \"label\": \"Beta\",\n \"description\": \"Early users, iterating. Feature-complete enough to learn from,\n… (truncated)"
|
|
3045
3045
|
}
|
|
3046
3046
|
],
|
|
3047
3047
|
"warnings": [],
|
|
@@ -3081,7 +3081,7 @@
|
|
|
3081
3081
|
{
|
|
3082
3082
|
"description": "Live call against the Notion example graph.",
|
|
3083
3083
|
"input": "{}",
|
|
3084
|
-
"output": "{\n \"count\": 23,\n \"playbooks\": [\n {\n \"id\": \"playbook:strategy-outcomes\",\n \"name\": \"Strategy & Outcomes\",\n \"version\": \"0.2.0\",\n \"description\": \"Cascade vision through themes, outcomes, objectives, key results
|
|
3084
|
+
"output": "{\n \"count\": 23,\n \"playbooks\": [\n {\n \"id\": \"playbook:strategy-outcomes\",\n \"name\": \"Strategy & Outcomes\",\n \"version\": \"0.2.0\",\n \"description\": \"Cascade vision through themes, outcomes, objectives, key results, and the bets you are making to get there.\",\n \"region\": \"strategy_outcomes\",\n \"is_canonical\": true,\n \"target_anchor_entity\": \"objective\",\n \"creation_sequence\": [\n {\n \"kind\": \"entity_sequence\",\n \"order\": 1,\n \"phase\": \"Vision & Mission\",\n \"name\": \"Vision & Mission\",\n \"prompt_hint\": \"Name what you are building toward and how you will get there. Vision is the destination; mission is the orientation. One of each, no more.\",\n \"entity_types\": [\n \"vision\",\n \"mission\"\n ]\n },\n {\n \"kind\": \"entity_sequence\",\n \"order\": 2,\n \"phase\": \"Themes\",\n \"name\": \"Themes\",\n \"prompt_hint\": \"Choose 2–4 strategic themes that focus the work. Past four, you have lost focus, not gained coverage.\",\n \"entity_types\": [\n \"strategic_theme\",\n \"strategic_pillar\"\n ]\n },\n {\n \"kind\": \"entity_sequence\",\n \"order\": 3,\n \"phase\": \"Outcomes\",\n \"name\": \"Outcomes\",\n \"prompt_hint\": \"Frame the changes in the world the product is trying\n… (truncated)"
|
|
3085
3085
|
}
|
|
3086
3086
|
],
|
|
3087
3087
|
"warnings": [],
|
|
@@ -3260,7 +3260,7 @@
|
|
|
3260
3260
|
{
|
|
3261
3261
|
"description": "Live call against the Notion example graph.",
|
|
3262
3262
|
"input": "{}",
|
|
3263
|
-
"output": "{\n \"migrations\": [\n {\n \"from\": \"
|
|
3263
|
+
"output": "{\n \"migrations\": [\n {\n \"from\": \"story_statement\",\n \"to\": \"user_story\",\n \"since\": \"0.7.0\"\n },\n {\n \"from\": \"hypothesis_claim\",\n \"to\": \"hypothesis\",\n \"since\": \"0.4.0\"\n },\n {\n \"from\": \"hypothesis_evidence\",\n \"to\": \"evidence\",\n \"since\": \"0.4.0\"\n },\n {\n \"from\": \"story_task\",\n \"to\": \"task\",\n \"since\": \"0.4.0\"\n },\n {\n \"from\": \"hypothesis\",\n \"to\": \"hypothesis_claim\",\n \"since\": \"0.2.8\"\n },\n {\n \"from\": \"pain_point\",\n \"to\": \"need\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"user_need\",\n \"to\": \"need\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"research_insight\",\n \"to\": \"insight\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"finding\",\n \"to\": \"insight\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"ux_insight\",\n \"to\": \"insight\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"highlight\",\n \"to\": \"observation\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"kpi\",\n \"to\": \"metric\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"north_star_metric\",\n \"to\": \"metric\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"input_metric\",\n \"to\": \"metric\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"metric_definition\",\n \"to\": \"metric\",\n \"since\": \"0.1.0\"\n },\n {\n \"from\": \"ab_test\",\n… (truncated)"
|
|
3264
3264
|
}
|
|
3265
3265
|
],
|
|
3266
3266
|
"warnings": [],
|
|
@@ -3295,7 +3295,7 @@
|
|
|
3295
3295
|
{
|
|
3296
3296
|
"description": "Live call against the Notion example graph.",
|
|
3297
3297
|
"input": "{}",
|
|
3298
|
-
"output": "{\n \"approach_id\": \"plan\",\n \"scope\": null,\n \"generated_at\": \"2026-05-
|
|
3298
|
+
"output": "{\n \"approach_id\": \"plan\",\n \"scope\": null,\n \"generated_at\": \"2026-05-29T20:13:19.977Z\",\n \"approach\": {\n \"id\": \"plan\",\n \"label\": \"Plan\",\n \"description\": \"The path of arrival to \\\"what should I build next?\\\". Plan engages a region by surveying its entity coverage against canonical expectations and surfacing the missing scaffolding: the entities a healthy region carries that this graph does not. Cartographic sense: you are walking the coastline of a region and noting where the contour is incomplete, not deciding a strategy. Frameworks like Now/Next/Later, MoSCoW, and Wardley Mapping live within Plan as the named techniques for organising the gap-filling sequence.\",\n \"question_answered\": \"what should I build next?\",\n \"signature_hint\": \"({ region?: UPGRegionId }) → { missing_entities, coverage_score }\",\n \"framework_id_examples\": [\n \"now-next-later\",\n \"moscow\",\n \"wardley-map\",\n \"okr-framework\",\n \"three-horizons\"\n ]\n },\n \"params\": {\n \"region\": null\n },\n \"region\": null,\n \"missing_entities\": [],\n \"coverage_score\": 1,\n \"expected_count\": 312,\n \"covered_count\": 312,\n \"execution_mode\": \"execution_v0_4_0\"\n}"
|
|
3299
3299
|
}
|
|
3300
3300
|
],
|
|
3301
3301
|
"warnings": [],
|
|
@@ -3313,7 +3313,7 @@
|
|
|
3313
3313
|
},
|
|
3314
3314
|
{
|
|
3315
3315
|
"name": "prioritise",
|
|
3316
|
-
"description": "[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing prioritisation, invoke the /upg-prioritise skill instead of calling this tool directly.
|
|
3316
|
+
"description": "[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing prioritisation, invoke the /upg-prioritise skill instead of calling this tool directly. Prioritise approach: path of arrival to \"what's most important?\". Returns the Prioritise record + invocation params + framework metadata in the family-resemblance envelope. Both `candidates` and `framework_id` are required. The LLM looks up the framework via `get_framework`, reads its scoring spec, and emits `{ ranked: [{ entity_id, score, rationale }], framework_used }`.",
|
|
3317
3317
|
"domain": "spec",
|
|
3318
3318
|
"inputSchema": {
|
|
3319
3319
|
"type": "object",
|
|
@@ -3354,7 +3354,7 @@
|
|
|
3354
3354
|
},
|
|
3355
3355
|
{
|
|
3356
3356
|
"name": "reflect",
|
|
3357
|
-
"description": "[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing reflection, invoke the /upg-reflect skill instead of calling this tool directly.
|
|
3357
|
+
"description": "[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing reflection, invoke the /upg-reflect skill instead of calling this tool directly. Reflect approach: path of arrival to \"what should I be questioning?\". Returns the Reflect record + invocation params in the family-resemblance envelope. The LLM consumes `mode` + `scope` + `signature_hint` and emits `{ prompts: [{ kind, question, target_entities? }] }`. `mode` is one of: `assumptions`, `alternatives`, `blind-spots`, `load-bearing`; omit for open reflection. `scope` accepts a region id, entity id, or `null` for whole-graph.",
|
|
3358
3358
|
"domain": "spec",
|
|
3359
3359
|
"inputSchema": {
|
|
3360
3360
|
"type": "object",
|
|
@@ -3385,7 +3385,7 @@
|
|
|
3385
3385
|
{
|
|
3386
3386
|
"description": "Live call against the Notion example graph.",
|
|
3387
3387
|
"input": "{}",
|
|
3388
|
-
"output": "{\n \"approach_id\": \"reflect\",\n \"scope\": null,\n \"generated_at\": \"2026-05-
|
|
3388
|
+
"output": "{\n \"approach_id\": \"reflect\",\n \"scope\": null,\n \"generated_at\": \"2026-05-29T20:13:20.019Z\",\n \"approach\": {\n \"id\": \"reflect\",\n \"label\": \"Reflect\",\n \"description\": \"The path of arrival to \\\"what should I be questioning?\\\". Reflect engages an optional scope (region, entity, or `null` for the whole graph) and emits structured prompts a thinker should consider: assumptions to test, alternatives to weigh, blind-spots to surface, load-bearing claims to verify. Mode is optional; absence is open reflection. Cartographic sense: before approaching the coastline, you are asking which features of your chart you have not actually verified; the prompts mark the parts of the map that may be conjecture. Five Whys, Pre-mortem, Red Team, and Devil's Advocate are the named techniques inside this approach.\",\n \"question_answered\": \"what should I be questioning?\",\n \"signature_hint\": \"({ scope?: UPGRegionId | entity_id | null, mode?: 'assumptions' | 'alternatives' | 'blind-spots' | 'load-bearing' }) → { prompts: [{ kind, question, target_entities? }] }\",\n \"framework_id_examples\": [\n \"five-whys\",\n \"pre-mortem\",\n \"red-team\",\n \"devils-advocate\",\n \"second-order-thinking\",\n \"retrospective\",\n \"four-forces-of-progress\",\n \"assumption-canvas\",\n \"win-loss-analysis\"\n ]\n },\n \"params\": {\n \"scope\": null,\n \"mode\": null\n },\n \"prompts\": [\n… (truncated)"
|
|
3389
3389
|
}
|
|
3390
3390
|
],
|
|
3391
3391
|
"warnings": [],
|
|
@@ -3447,7 +3447,7 @@
|
|
|
3447
3447
|
},
|
|
3448
3448
|
{
|
|
3449
3449
|
"name": "trace",
|
|
3450
|
-
"description": "[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing tracing, invoke the /upg-trace skill instead of calling this tool directly.
|
|
3450
|
+
"description": "[LLM-mediated] This tool returns a routing envelope, not computed results. For user-facing tracing, invoke the /upg-trace skill instead of calling this tool directly. Trace approach: path of arrival to \"walk a meaningful path through existing graph\". Returns the Trace record + invocation params in the family-resemblance envelope. The LLM uses `anchor` + `path` to compose `query()` calls and emits `{ trail: [{ depth, entity_id, edge_type_in }], reached: entity_id[] }`. `path` is type-shorthand: `[\"persona\",\"job\",\"feature\"]` walks persona→job→feature using the canonical edge per pair (via `resolve_edge_for_pair`). Optional `edges_override` selects non-canonical edges per hop; `null` per element means \"use canonical\".",
|
|
3451
3451
|
"domain": "spec",
|
|
3452
3452
|
"inputSchema": {
|
|
3453
3453
|
"type": "object",
|
|
@@ -3486,7 +3486,7 @@
|
|
|
3486
3486
|
{
|
|
3487
3487
|
"description": "Live call against the Notion example graph.",
|
|
3488
3488
|
"input": "{\n \"anchor\": \"ec3d5479-4947-4bd9-9e77-b5ee01beb851\",\n \"path\": [\n \"opportunity_drives_solution\"\n ]\n}",
|
|
3489
|
-
"output": "{\n \"approach_id\": \"trace\",\n \"scope\": \"ec3d5479-4947-4bd9-9e77-b5ee01beb851\",\n \"generated_at\": \"2026-05-
|
|
3489
|
+
"output": "{\n \"approach_id\": \"trace\",\n \"scope\": \"ec3d5479-4947-4bd9-9e77-b5ee01beb851\",\n \"generated_at\": \"2026-05-29T20:13:19.988Z\",\n \"approach\": {\n \"id\": \"trace\",\n \"label\": \"Trace\",\n \"description\": \"The path of arrival to \\\"walk a meaningful path through existing graph\\\". Trace engages an anchor entity and follows a path expressed as a UPGEntityType[] shorthand. Example: `[\\\"persona\\\", \\\"job\\\", \\\"feature\\\"]` walks persona→job→feature using the canonical edge for each pair (resolved via `resolve_edge_for_pair`). An optional `edges_override` array selects non-canonical edges per hop when a pair has multiple resolutions. Cartographic sense: you are tracing a route across charted terrain; anchor is the departure, path is the heading sequence, the canonical edges are the roads. No DSL invented; the shorthand IS the path expression.\",\n \"question_answered\": \"walk a meaningful path through existing graph\",\n \"signature_hint\": \"({ anchor: entity_id, path: UPGEntityType[], edges_override?: (string | null)[] }) → { trail: [{ depth, entity_id, edge_type_in }], reached: entity_id[] }\",\n \"framework_id_examples\": [\n \"opportunity-solution-tree\",\n \"strategic-cascade\",\n \"metrics-tree\",\n \"user-journey-map\",\n \"impact-map\",\n \"dependency-map\"\n ]\n },\n \"params\": {\n \"anchor\": \"ec3d5479-4947-4bd9-9e77-b5ee01beb851\",\n \"path\": [\n… (truncated)"
|
|
3490
3490
|
}
|
|
3491
3491
|
],
|
|
3492
3492
|
"warnings": [],
|
|
@@ -3736,7 +3736,7 @@
|
|
|
3736
3736
|
},
|
|
3737
3737
|
"include_polymorphic_upgrades": {
|
|
3738
3738
|
"type": "boolean",
|
|
3739
|
-
"description": "When true, include a `polymorphic_with_typed_alternative` array listing polymorphic edges (e.g. node_owned_by_person, node_constrains_node) that have a more-specific typed alternative for their actual source/target pair. Opt-in only
|
|
3739
|
+
"description": "When true, include a `polymorphic_with_typed_alternative` array listing polymorphic edges (e.g. node_owned_by_person, node_constrains_node) that have a more-specific typed alternative for their actual source/target pair. Opt-in only; omitted by default to avoid cluttering routine validation output. Does not affect `valid`; these are advisory suggestions."
|
|
3740
3740
|
}
|
|
3741
3741
|
}
|
|
3742
3742
|
},
|
|
@@ -3747,7 +3747,7 @@
|
|
|
3747
3747
|
{
|
|
3748
3748
|
"description": "Live call against the Notion example graph.",
|
|
3749
3749
|
"input": "{}",
|
|
3750
|
-
"output": "{\n \"valid\": false,\n \"summary\": {\n \"entity_drift\": 0,\n \"edge_drift\": 0,\n \"top_level_drift\": 0,\n \"lifecycle_drift\": 0,\n \"self_referential\": 0,\n \"property_drift\": 164,\n \"total_nodes\": 2054,\n \"total_edges\":
|
|
3750
|
+
"output": "{\n \"valid\": false,\n \"summary\": {\n \"entity_drift\": 0,\n \"edge_drift\": 0,\n \"top_level_drift\": 0,\n \"lifecycle_drift\": 0,\n \"self_referential\": 0,\n \"property_drift\": 164,\n \"total_nodes\": 2054,\n \"total_edges\": 3216,\n \"spec_version\": \"0.7.3\",\n \"scope\": \"all\",\n \"limit\": 100,\n \"anti_pattern_violations_high\": 0,\n \"anti_pattern_violations_medium\": 1,\n \"anti_pattern_violations_low\": 0,\n \"edge_type_pair_drift\": 100,\n \"graph_topology_self_loops\": 0,\n \"property_type_drift\": 100\n },\n \"_hash\": \"c0f701e327319f2e\",\n \"entity_drift\": [],\n \"edge_drift\": [],\n \"top_level_drift\": [],\n \"lifecycle_drift\": [],\n \"self_referential\": [],\n \"property_drift\": [\n {\n \"id\": \"ec3d5479-4947-4bd9-9e77-b5ee01beb851\",\n \"type\": \"product\",\n \"property\": \"stage\",\n \"via\": \"UPG_PROPERTY_MIGRATIONS['0.2.13']\"\n },\n {\n \"id\": \"3f1c1804-b33b-4b1f-9094-c91cc8957912\",\n \"type\": \"assumption\",\n \"property\": \"validation_status\",\n \"via\": \"UPG_PROPERTY_MIGRATIONS['0.5.0']\"\n },\n {\n \"id\": \"6719fce7-61e7-44df-b6cf-92f7c7312554\",\n \"type\": \"assumption\",\n \"property\": \"validation_status\",\n \"via\": \"UPG_PROPERTY_MIGRATIONS['0.5.0']\"\n },\n {\n \"id\": \"7b22f5f3-b344-4e49-8d5a-35cf9087dc6c\",\n \"type\": \"assumption\",\n \"property\": \"validation_status\",\n \"via\": \"UPG_PROPERTY_MIGRATIONS['0.5.0']\"\n… (truncated)"
|
|
3751
3751
|
}
|
|
3752
3752
|
],
|
|
3753
3753
|
"warnings": [
|
|
@@ -3804,7 +3804,7 @@
|
|
|
3804
3804
|
}
|
|
3805
3805
|
],
|
|
3806
3806
|
"warnings": [
|
|
3807
|
-
"Default is `dry_run: true`. Pass `dry_run: false` to commit.\nIdempotent on retry
|
|
3807
|
+
"Default is `dry_run: true`. Pass `dry_run: false` to commit.\nIdempotent on retry; re-running after a successful commit reports\nzero changes (canonical statuses pass the validity check)."
|
|
3808
3808
|
],
|
|
3809
3809
|
"see": [
|
|
3810
3810
|
"migrate_type",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unified-product-graph/mcp-server",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.4",
|
|
4
4
|
"description": "Local MCP server for .upg files. Read and write product knowledge graphs offline.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "The Product Creator <hello@theproductcreator.com>",
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
This project uses the Unified Product Graph to structure product thinking. A `.upg` file in the repo root contains the product graph.
|
|
4
4
|
|
|
5
5
|
### Available Commands
|
|
6
|
-
- `/upg
|
|
7
|
-
- `/upg-journey
|
|
8
|
-
- `/upg-init
|
|
9
|
-
- `/upg-explore
|
|
10
|
-
- `/upg-status
|
|
11
|
-
- `/upg-gaps
|
|
12
|
-
- `/upg-capture
|
|
6
|
+
- `/upg`: See your product graph status and all available commands
|
|
7
|
+
- `/upg-journey`: Guided 7-phase product journey with progress tracking
|
|
8
|
+
- `/upg-init`: Bootstrap a new product graph (~5 min guided setup)
|
|
9
|
+
- `/upg-explore`: Create any entity (90+ types across 32 domains)
|
|
10
|
+
- `/upg-status`: Health dashboard with maturity scoring
|
|
11
|
+
- `/upg-gaps`: Gap analysis across 8 business areas
|
|
12
|
+
- `/upg-capture`: Capture session work into the graph
|
|
13
13
|
|
|
14
14
|
### Graph Awareness
|
|
15
|
-
When a `.upg` file exists, be aware of the product graph context. During conversations about product decisions, features, user research, or business strategy, offer to capture relevant insights into the graph. Don't be pushy
|
|
15
|
+
When a `.upg` file exists, be aware of the product graph context. During conversations about product decisions, features, user research, or business strategy, offer to capture relevant insights into the graph. Don't be pushy; only suggest when the work is clearly graph-worthy (new features, strategic decisions, user insights). Routine code changes are not graph-worthy.
|
|
16
16
|
|
|
17
17
|
At natural checkpoints (after commits, before session end, after design discussions), suggest running `/upg-capture` to review and save session work.
|
|
18
18
|
|
|
@@ -129,7 +129,7 @@ for t in "${SELECTED_TARGETS[@]}"; do
|
|
|
129
129
|
if [ -n "$dir" ]; then
|
|
130
130
|
VALID_TARGETS+=("$t")
|
|
131
131
|
else
|
|
132
|
-
echo "Warning: Unknown target '$t'
|
|
132
|
+
echo "Warning: Unknown target '$t', skipping"
|
|
133
133
|
fi
|
|
134
134
|
done
|
|
135
135
|
|
|
@@ -205,7 +205,7 @@ if [ "$NO_CLAUDEMD" = false ]; then
|
|
|
205
205
|
|
|
206
206
|
# Check if snippet already exists
|
|
207
207
|
if [ -f "$CLAUDEMD_PATH" ] && grep -q "## Unified Product Graph" "$CLAUDEMD_PATH" 2>/dev/null; then
|
|
208
|
-
echo " CLAUDE.md already has UPG awareness
|
|
208
|
+
echo " CLAUDE.md already has UPG awareness, skipping"
|
|
209
209
|
CLAUDEMD_UPDATED=true
|
|
210
210
|
else
|
|
211
211
|
printf "Add UPG awareness to your CLAUDE.md? [Y/n] "
|
|
@@ -213,7 +213,7 @@ if [ "$NO_CLAUDEMD" = false ]; then
|
|
|
213
213
|
|
|
214
214
|
if [ "${answer:-Y}" != "n" ] && [ "${answer:-Y}" != "N" ]; then
|
|
215
215
|
if [ ! -f "$SNIPPET_FILE" ]; then
|
|
216
|
-
echo "Warning: Snippet file not found at $SNIPPET_FILE
|
|
216
|
+
echo "Warning: Snippet file not found at $SNIPPET_FILE, skipping"
|
|
217
217
|
else
|
|
218
218
|
# Create CLAUDE.md if it doesn't exist
|
|
219
219
|
if [ ! -f "$CLAUDEMD_PATH" ]; then
|
|
@@ -251,9 +251,9 @@ if [ "$CLAUDEMD_UPDATED" = true ]; then
|
|
|
251
251
|
fi
|
|
252
252
|
echo ""
|
|
253
253
|
echo "Quick start:"
|
|
254
|
-
echo " /upg
|
|
255
|
-
echo " /upg-init
|
|
256
|
-
echo " /upg-journey
|
|
254
|
+
echo " /upg: see your product graph"
|
|
255
|
+
echo " /upg-init: bootstrap a new graph (~5 min)"
|
|
256
|
+
echo " /upg-journey: guided product journey"
|
|
257
257
|
echo ""
|
|
258
|
-
echo "Skills are symlinked
|
|
258
|
+
echo "Skills are symlinked; edits in the source are live immediately."
|
|
259
259
|
echo ""
|