@unified-product-graph/mcp-server 0.8.15 → 0.8.16
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/README.md +2 -2
- package/TOOLS.md +194 -6
- package/dist/index.js +346 -7
- package/dist/index.js.map +1 -1
- package/dist/tools-manifest.json +345 -23
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ For Claude Code, add to `.mcp.json`:
|
|
|
21
21
|
```json
|
|
22
22
|
{
|
|
23
23
|
"mcpServers": {
|
|
24
|
-
"
|
|
24
|
+
"unified-product-graph": {
|
|
25
25
|
"command": "npx",
|
|
26
26
|
"args": ["upg-mcp-server"]
|
|
27
27
|
}
|
|
@@ -34,7 +34,7 @@ The server auto-discovers `.upg` files in the current directory. To point at a s
|
|
|
34
34
|
```json
|
|
35
35
|
{
|
|
36
36
|
"mcpServers": {
|
|
37
|
-
"
|
|
37
|
+
"unified-product-graph": {
|
|
38
38
|
"command": "npx",
|
|
39
39
|
"args": ["upg-mcp-server", "--file", "path/to/product.upg"]
|
|
40
40
|
}
|
package/TOOLS.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# UPG MCP Server: Tool Reference
|
|
2
2
|
|
|
3
|
-
Reference for the
|
|
3
|
+
Reference for the 106 tools exposed by `@unified-product-graph/mcp-server`. Generated from JSDoc on `src/tools/*.ts` (do not edit by hand).
|
|
4
4
|
|
|
5
5
|
## Contents
|
|
6
6
|
|
|
7
7
|
- [Context & Session](#context-session): 5 tools
|
|
8
8
|
- [Nodes](#nodes): 15 tools
|
|
9
9
|
- [Edges](#edges): 9 tools
|
|
10
|
-
- [Areas & Change Log](#areas-change-log):
|
|
11
|
-
- [Workspace & Portfolios](#workspace-portfolios):
|
|
10
|
+
- [Areas & Change Log](#areas-change-log): 10 tools
|
|
11
|
+
- [Workspace & Portfolios](#workspace-portfolios): 15 tools
|
|
12
12
|
- [Schema](#schema): 1 tool
|
|
13
13
|
- [Spec Introspection](#spec-introspection): 45 tools
|
|
14
14
|
- [Cloud Sync](#cloud-sync): 3 tools
|
|
@@ -948,10 +948,14 @@ _Product areas, the `.upg-area.json` cwd scoper, and the session change log._
|
|
|
948
948
|
|
|
949
949
|
- [`assign_product_to_area`](#assign-product-to-area)
|
|
950
950
|
- [`create_area`](#create-area)
|
|
951
|
+
- [`delete_area`](#delete-area)
|
|
951
952
|
- [`get_area_context`](#get-area-context)
|
|
952
953
|
- [`get_area_graph`](#get-area-graph)
|
|
953
954
|
- [`get_changes`](#get-changes)
|
|
954
955
|
- [`list_product_areas`](#list-product-areas)
|
|
956
|
+
- [`move_product_to_area`](#move-product-to-area)
|
|
957
|
+
- [`remove_product_from_area`](#remove-product-from-area)
|
|
958
|
+
- [`update_area`](#update-area)
|
|
955
959
|
|
|
956
960
|
### `assign_product_to_area`
|
|
957
961
|
|
|
@@ -1009,6 +1013,31 @@ fails.
|
|
|
1009
1013
|
**See also:** `list_product_areas`
|
|
1010
1014
|
|
|
1011
1015
|
|
|
1016
|
+
### `delete_area`
|
|
1017
|
+
|
|
1018
|
+
Delete a product area from `.upg/portfolio.upg`. Guarded: refuses while the area still has products unless `force: true`. Child areas are un-nested (their parent link is cleared) so no parent reference dangles.
|
|
1019
|
+
|
|
1020
|
+
**Atomicity:** `atomic (single portfolio.upg flush).`
|
|
1021
|
+
|
|
1022
|
+
**Arguments:**
|
|
1023
|
+
|
|
1024
|
+
| Name | Type | Required | Description |
|
|
1025
|
+
| ---- | ---- | -------- | ----------- |
|
|
1026
|
+
| `area_id` | string | ✓ | Product area id to delete (from list_product_areas) |
|
|
1027
|
+
| `force` | boolean | | Delete even if the area still has products (default false) |
|
|
1028
|
+
|
|
1029
|
+
**Returns:**
|
|
1030
|
+
|
|
1031
|
+
JSON: `{ message, area_id, deleted, unnested_children: string[] }`.
|
|
1032
|
+
|
|
1033
|
+
**Throws:**
|
|
1034
|
+
|
|
1035
|
+
- textError on a missing workspace, unknown area, or a non-empty area without
|
|
1036
|
+
`force`.
|
|
1037
|
+
|
|
1038
|
+
**See also:** `create_area`, `remove_product_from_area`
|
|
1039
|
+
|
|
1040
|
+
|
|
1012
1041
|
### `get_area_context`
|
|
1013
1042
|
|
|
1014
1043
|
Check whether the current working directory has a `.upg-area.json` that scopes work to a specific product area.
|
|
@@ -1093,13 +1122,96 @@ parent_area_id?, products? }>, total }`.
|
|
|
1093
1122
|
**See also:** `create_area`, `get_area_graph`
|
|
1094
1123
|
|
|
1095
1124
|
|
|
1125
|
+
### `move_product_to_area`
|
|
1126
|
+
|
|
1127
|
+
Move a product to a different product area: remove it from `from_area_id` (or, when omitted, from every area it currently sits in) and add it to `to_area_id`. Convenience over remove_product_from_area + assign_product_to_area.
|
|
1128
|
+
|
|
1129
|
+
**Atomicity:** `atomic (single portfolio.upg flush).`
|
|
1130
|
+
|
|
1131
|
+
**Arguments:**
|
|
1132
|
+
|
|
1133
|
+
| Name | Type | Required | Description |
|
|
1134
|
+
| ---- | ---- | -------- | ----------- |
|
|
1135
|
+
| `from_area_id` | string | | Source area id to remove from; omit to remove from all areas |
|
|
1136
|
+
| `product_id` | string | ✓ | Product id (from list_local_products) |
|
|
1137
|
+
| `to_area_id` | string | ✓ | Destination product area id (from list_product_areas) |
|
|
1138
|
+
|
|
1139
|
+
**Returns:**
|
|
1140
|
+
|
|
1141
|
+
JSON: `{ product_id, to_area_id, to_area_title?, removed_from: string[], added }`.
|
|
1142
|
+
|
|
1143
|
+
**Throws:**
|
|
1144
|
+
|
|
1145
|
+
- textError on a missing workspace, unknown product, or unknown target area.
|
|
1146
|
+
|
|
1147
|
+
**See also:** `assign_product_to_area`, `remove_product_from_area`
|
|
1148
|
+
|
|
1149
|
+
|
|
1150
|
+
### `remove_product_from_area`
|
|
1151
|
+
|
|
1152
|
+
Remove a product from a product area's `products[]` in `.upg/portfolio.upg` (the product stays registered on the portfolio and in any other container). The inverse of `assign_product_to_area`.
|
|
1153
|
+
|
|
1154
|
+
**Atomicity:** `atomic (single portfolio.upg flush).`
|
|
1155
|
+
|
|
1156
|
+
**Arguments:**
|
|
1157
|
+
|
|
1158
|
+
| Name | Type | Required | Description |
|
|
1159
|
+
| ---- | ---- | -------- | ----------- |
|
|
1160
|
+
| `area_id` | string | ✓ | Product area id (from list_product_areas) |
|
|
1161
|
+
| `product_id` | string | ✓ | Product id (from list_local_products) |
|
|
1162
|
+
|
|
1163
|
+
**Returns:**
|
|
1164
|
+
|
|
1165
|
+
JSON: `{ product_id, container_id, container_kind: "product_area",
|
|
1166
|
+
container_title?, removed }`. `removed: false` (not an error) when the product
|
|
1167
|
+
was not a member, so retries are idempotent.
|
|
1168
|
+
|
|
1169
|
+
**Throws:**
|
|
1170
|
+
|
|
1171
|
+
- textError on a missing workspace or an unknown area id.
|
|
1172
|
+
|
|
1173
|
+
**See also:** `assign_product_to_area`, `move_product_to_area`
|
|
1174
|
+
|
|
1175
|
+
|
|
1176
|
+
### `update_area`
|
|
1177
|
+
|
|
1178
|
+
Edit a product area in `.upg/portfolio.upg` (title, description, strategic_priority, owner) and/or re-parent it via `parent_area_id`. The mirror of `update_product` for the organisational axis. `parent_area_id` is tri-state: omit to leave unchanged, pass null to un-nest (top-level), or pass an area id to re-parent (rejected if it would create a cycle).
|
|
1179
|
+
|
|
1180
|
+
**Atomicity:** `atomic (single portfolio.upg flush).`
|
|
1181
|
+
|
|
1182
|
+
**Arguments:**
|
|
1183
|
+
|
|
1184
|
+
| Name | Type | Required | Description |
|
|
1185
|
+
| ---- | ---- | -------- | ----------- |
|
|
1186
|
+
| `area_id` | string | ✓ | Product area id to edit (from list_product_areas) |
|
|
1187
|
+
| `description` | string | | New area description |
|
|
1188
|
+
| `owner` | string | | Person or team that owns this area |
|
|
1189
|
+
| `parent_area_id` | string,null | | Re-parent under this area id; null un-nests (top-level); omit to leave unchanged |
|
|
1190
|
+
| `strategic_priority` | `urgent` \| `high` \| `medium` \| `low` \| `none` | | Strategic priority (canonical Priority scale) |
|
|
1191
|
+
| `title` | string | | New area title |
|
|
1192
|
+
|
|
1193
|
+
**Returns:**
|
|
1194
|
+
|
|
1195
|
+
JSON: `{ message, area, updated: string[] }`.
|
|
1196
|
+
|
|
1197
|
+
**Throws:**
|
|
1198
|
+
|
|
1199
|
+
- textError on a missing workspace, unknown area/parent, a re-parent cycle, or
|
|
1200
|
+
when no editable field is supplied.
|
|
1201
|
+
|
|
1202
|
+
**See also:** `create_area`, `list_product_areas`
|
|
1203
|
+
|
|
1204
|
+
|
|
1096
1205
|
## Workspace & Portfolios
|
|
1097
1206
|
|
|
1098
1207
|
_Multi-product discovery, switching, init, cross-product edges._
|
|
1099
1208
|
|
|
1100
1209
|
- [`attach_product_to_portfolio`](#attach-product-to-portfolio)
|
|
1210
|
+
- [`batch_create_cross_product_edges`](#batch-create-cross-product-edges)
|
|
1101
1211
|
- [`create_cross_product_edge`](#create-cross-product-edge)
|
|
1102
1212
|
- [`create_product`](#create-product)
|
|
1213
|
+
- [`delete_cross_product_edge`](#delete-cross-product-edge)
|
|
1214
|
+
- [`detach_product_from_portfolio`](#detach-product-from-portfolio)
|
|
1103
1215
|
- [`get_organization`](#get-organization)
|
|
1104
1216
|
- [`get_workspace_info`](#get-workspace-info)
|
|
1105
1217
|
- [`init_workspace`](#init-workspace)
|
|
@@ -1136,9 +1248,35 @@ portfolio id (the message points at list_portfolios / list_local_products).
|
|
|
1136
1248
|
**See also:** `assign_product_to_area`, `create_product`
|
|
1137
1249
|
|
|
1138
1250
|
|
|
1251
|
+
### `batch_create_cross_product_edges`
|
|
1252
|
+
|
|
1253
|
+
Create up to 50 cross-product edges in one atomic write (the portfolio-tier mirror of batch_create_edges). Every edge is validated and qualified before anything is written; if any is invalid the whole batch is rejected. Referenced products are auto-registered.
|
|
1254
|
+
|
|
1255
|
+
**Atomicity:** `atomic. All edges validated first, then a single portfolio.upg flush.`
|
|
1256
|
+
|
|
1257
|
+
**Arguments:**
|
|
1258
|
+
|
|
1259
|
+
| Name | Type | Required | Description |
|
|
1260
|
+
| ---- | ---- | -------- | ----------- |
|
|
1261
|
+
| `auto_create_portfolio` | boolean | | Create an empty portfolio document if none exists (default false) |
|
|
1262
|
+
| `edges` | array | ✓ | Cross-product edges to create (max 50). Each: { source_id, target_id, type, source_product_id?, target_product_id? }. |
|
|
1263
|
+
|
|
1264
|
+
**Returns:**
|
|
1265
|
+
|
|
1266
|
+
JSON: `{ message, created: UPGCrossEdge[], count, portfolio_file,
|
|
1267
|
+
registered_products? }`.
|
|
1268
|
+
|
|
1269
|
+
**Throws:**
|
|
1270
|
+
|
|
1271
|
+
- textError when `edges` is missing/empty/oversized, when any edge is invalid,
|
|
1272
|
+
or when no portfolio document exists (pass `auto_create_portfolio: true` to mint one).
|
|
1273
|
+
|
|
1274
|
+
**See also:** `create_cross_product_edge`, `list_cross_edge_types`
|
|
1275
|
+
|
|
1276
|
+
|
|
1139
1277
|
### `create_cross_product_edge`
|
|
1140
1278
|
|
|
1141
|
-
Create a cross-product relationship between two entities in different products within a portfolio graph. Types: `shares_persona`, `shares_competitor`, `shares_metric`, `depends_on_product`, `cannibalises`, `succeeds
|
|
1279
|
+
Create a cross-product relationship between two entities in different products within a portfolio graph. Types: `shares_persona`, `shares_competitor`, `shares_metric`, `depends_on_product`, `cannibalises`, `succeeds`, `hosts` (host product runs the hosted product inside itself, directed host to hosted).
|
|
1142
1280
|
|
|
1143
1281
|
**Atomicity:** `non-atomic. Portfolio file create (if new) + edge append are
|
|
1144
1282
|
separate filesystem operations.`
|
|
@@ -1151,7 +1289,7 @@ separate filesystem operations.`
|
|
|
1151
1289
|
| `source_product_id` | string | | Product ID of the source node |
|
|
1152
1290
|
| `target_id` | string | ✓ | Target node ID |
|
|
1153
1291
|
| `target_product_id` | string | | Product ID of the target node |
|
|
1154
|
-
| `type` | `shares_persona` \| `shares_competitor` \| `shares_metric` \| `depends_on_product` \| `cannibalises` \| `succeeds` | ✓ | Cross-product relationship type |
|
|
1292
|
+
| `type` | `shares_persona` \| `shares_competitor` \| `shares_metric` \| `depends_on_product` \| `cannibalises` \| `succeeds` \| `hosts` | ✓ | Cross-product relationship type |
|
|
1155
1293
|
|
|
1156
1294
|
**Returns:**
|
|
1157
1295
|
|
|
@@ -1197,6 +1335,56 @@ JSON: `{ message, ...result }`. `result` carries `id`, `title`,
|
|
|
1197
1335
|
**See also:** `init_workspace`
|
|
1198
1336
|
|
|
1199
1337
|
|
|
1338
|
+
### `delete_cross_product_edge`
|
|
1339
|
+
|
|
1340
|
+
Delete a cross-product edge from `.upg/portfolio.upg` by id. The inverse of `create_cross_product_edge`. Returns `deleted: false` (not an error) when no edge with that id exists.
|
|
1341
|
+
|
|
1342
|
+
**Atomicity:** `atomic (single portfolio.upg flush).`
|
|
1343
|
+
|
|
1344
|
+
**Arguments:**
|
|
1345
|
+
|
|
1346
|
+
| Name | Type | Required | Description |
|
|
1347
|
+
| ---- | ---- | -------- | ----------- |
|
|
1348
|
+
| `edge_id` | string | ✓ | Cross-product edge id (from list_portfolio_cross_edges) |
|
|
1349
|
+
|
|
1350
|
+
**Returns:**
|
|
1351
|
+
|
|
1352
|
+
JSON: `{ edge_id, deleted, edge? }`. `deleted: false` (not an error) when
|
|
1353
|
+
no edge with that id exists, so retries are idempotent.
|
|
1354
|
+
|
|
1355
|
+
**Throws:**
|
|
1356
|
+
|
|
1357
|
+
- textError on a missing workspace.
|
|
1358
|
+
|
|
1359
|
+
**See also:** `create_cross_product_edge`, `list_portfolio_cross_edges`
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
### `detach_product_from_portfolio`
|
|
1363
|
+
|
|
1364
|
+
Remove a product from a portfolio's `products[]` in `.upg/portfolio.upg` (the product stays registered and in any other container). The inverse of `attach_product_to_portfolio`.
|
|
1365
|
+
|
|
1366
|
+
**Atomicity:** `atomic (single portfolio.upg flush).`
|
|
1367
|
+
|
|
1368
|
+
**Arguments:**
|
|
1369
|
+
|
|
1370
|
+
| Name | Type | Required | Description |
|
|
1371
|
+
| ---- | ---- | -------- | ----------- |
|
|
1372
|
+
| `portfolio_id` | string | ✓ | Portfolio id (from list_portfolios) |
|
|
1373
|
+
| `product_id` | string | ✓ | Product id (from list_local_products) |
|
|
1374
|
+
|
|
1375
|
+
**Returns:**
|
|
1376
|
+
|
|
1377
|
+
JSON: `{ product_id, container_id, container_kind: "portfolio",
|
|
1378
|
+
container_title?, removed }`. `removed: false` (not an error) when the product was
|
|
1379
|
+
not a member, so retries are idempotent.
|
|
1380
|
+
|
|
1381
|
+
**Throws:**
|
|
1382
|
+
|
|
1383
|
+
- textError on a missing workspace or an unknown portfolio id.
|
|
1384
|
+
|
|
1385
|
+
**See also:** `attach_product_to_portfolio`
|
|
1386
|
+
|
|
1387
|
+
|
|
1200
1388
|
### `get_organization`
|
|
1201
1389
|
|
|
1202
1390
|
Get the organisation that owns the current workspace's portfolio. Reads the singleton `portfolio.upg.organization`. Returns `{ organization: null }` when no portfolio document exists yet.
|
|
@@ -1971,7 +2159,7 @@ JSON: `{ kind, total, count, benchmarks: ... }`
|
|
|
1971
2159
|
|
|
1972
2160
|
### `list_cross_edge_types`
|
|
1973
2161
|
|
|
1974
|
-
List the canonical cross-product edge types from `UPG_CROSS_EDGE_TYPES`: `shares_persona`, `shares_competitor`, `shares_metric`, `depends_on_product`, `cannibalises`, `succeeds`. Portfolio-level relationships across products. Distinct from the within-product `UPG_EDGE_CATALOG`.
|
|
2162
|
+
List the canonical cross-product edge types from `UPG_CROSS_EDGE_TYPES`: `shares_persona`, `shares_competitor`, `shares_metric`, `depends_on_product`, `cannibalises`, `succeeds`, `hosts`. Portfolio-level relationships across products. Distinct from the within-product `UPG_EDGE_CATALOG`.
|
|
1975
2163
|
|
|
1976
2164
|
**Atomicity:** `atomic (read-only)`
|
|
1977
2165
|
|