@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.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schema_version": "2",
3
3
  "package": "@unified-product-graph/mcp-server",
4
- "package_version": "0.8.15",
5
- "tool_count": 99,
4
+ "package_version": "0.8.16",
5
+ "tool_count": 106,
6
6
  "domains": [
7
7
  "context",
8
8
  "nodes",
@@ -1553,7 +1553,7 @@
1553
1553
  "attach_product_to_portfolio",
1554
1554
  "create_product"
1555
1555
  ],
1556
- "source": "src/tools/areas.ts:67",
1556
+ "source": "src/tools/areas.ts:71",
1557
1557
  "symbol": "assignProductToAreaTool",
1558
1558
  "returns": "JSON: `{ product_id, container_id, container_kind: \"product_area\",\ncontainer_title?, already_member, registered }`.",
1559
1559
  "return_shape": "{ product_id, container_id, container_kind: \"product_area\", container_title?, already_member, registered }",
@@ -1612,7 +1612,7 @@
1612
1612
  "see": [
1613
1613
  "list_product_areas"
1614
1614
  ],
1615
- "source": "src/tools/areas.ts:290",
1615
+ "source": "src/tools/areas.ts:294",
1616
1616
  "symbol": "createArea",
1617
1617
  "returns": "JSON: `{ node, portfolio_file, written_to }`. `node` is the typed\n`UPGProductArea` record persisted to `portfolio_areas[]`.",
1618
1618
  "return_shape": "{ node, portfolio_file, written_to }",
@@ -1621,6 +1621,41 @@
1621
1621
  ],
1622
1622
  "atomicity": "atomic per write; the portfolio file is read, mutated, and\nflushed in one pass."
1623
1623
  },
1624
+ {
1625
+ "name": "delete_area",
1626
+ "description": "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.",
1627
+ "domain": "areas",
1628
+ "inputSchema": {
1629
+ "type": "object",
1630
+ "properties": {
1631
+ "area_id": {
1632
+ "type": "string",
1633
+ "description": "Product area id to delete (from list_product_areas)"
1634
+ },
1635
+ "force": {
1636
+ "type": "boolean",
1637
+ "description": "Delete even if the area still has products (default false)"
1638
+ }
1639
+ },
1640
+ "required": [
1641
+ "area_id"
1642
+ ]
1643
+ },
1644
+ "throws": [
1645
+ "textError on a missing workspace, unknown area, or a non-empty area without\n`force`."
1646
+ ],
1647
+ "examples": [],
1648
+ "warnings": [],
1649
+ "see": [
1650
+ "create_area",
1651
+ "remove_product_from_area"
1652
+ ],
1653
+ "source": "src/tools/areas.ts:441",
1654
+ "symbol": "deleteAreaTool",
1655
+ "returns": "JSON: `{ message, area_id, deleted, unnested_children: string[] }`.",
1656
+ "return_shape": "{ message, area_id, deleted, unnested_children: string[] }",
1657
+ "atomicity": "atomic (single portfolio.upg flush)."
1658
+ },
1624
1659
  {
1625
1660
  "name": "get_area_context",
1626
1661
  "description": "Check whether the current working directory has a `.upg-area.json` that scopes work to a specific product area.",
@@ -1639,7 +1674,7 @@
1639
1674
  ],
1640
1675
  "warnings": [],
1641
1676
  "see": [],
1642
- "source": "src/tools/areas.ts:240",
1677
+ "source": "src/tools/areas.ts:244",
1643
1678
  "symbol": "getAreaContext",
1644
1679
  "returns": "JSON: `{ has_area_context: false }` or\n`{ has_area_context: true, area_id, area_name, found_at }`.",
1645
1680
  "return_shape": "{ has_area_context: false }",
@@ -1679,7 +1714,7 @@
1679
1714
  "see": [
1680
1715
  "list_product_areas"
1681
1716
  ],
1682
- "source": "src/tools/areas.ts:98",
1717
+ "source": "src/tools/areas.ts:102",
1683
1718
  "symbol": "getAreaGraph",
1684
1719
  "returns": "JSON: `{ area, nodes, edges, node_count, edge_count }`. May\ninclude a `degraded` block when the response was auto-trimmed.",
1685
1720
  "return_shape": "{ area, nodes, edges, node_count, edge_count }",
@@ -1711,7 +1746,7 @@
1711
1746
  ],
1712
1747
  "warnings": [],
1713
1748
  "see": [],
1714
- "source": "src/tools/areas.ts:329",
1749
+ "source": "src/tools/areas.ts:333",
1715
1750
  "symbol": "getChanges",
1716
1751
  "returns": "JSON: `{ changes, summary: { create, update, delete }, total }`.\n`since` filters to ISO 8601 timestamps after the cutoff.",
1717
1752
  "return_shape": "{ changes, summary: { create, update, delete }, total }",
@@ -1741,12 +1776,152 @@
1741
1776
  "create_area",
1742
1777
  "get_area_graph"
1743
1778
  ],
1744
- "source": "src/tools/areas.ts:34",
1779
+ "source": "src/tools/areas.ts:38",
1745
1780
  "symbol": "listProductAreas",
1746
1781
  "returns": "JSON: `{ areas: Array<{ id, title, strategic_priority?,\nparent_area_id?, products? }>, total }`.",
1747
1782
  "return_shape": "{ areas: Array<{ id, title, strategic_priority?, parent_area_id?, products? }>, total }",
1748
1783
  "atomicity": "atomic (read-only)"
1749
1784
  },
1785
+ {
1786
+ "name": "move_product_to_area",
1787
+ "description": "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.",
1788
+ "domain": "areas",
1789
+ "inputSchema": {
1790
+ "type": "object",
1791
+ "properties": {
1792
+ "product_id": {
1793
+ "type": "string",
1794
+ "description": "Product id (from list_local_products)"
1795
+ },
1796
+ "to_area_id": {
1797
+ "type": "string",
1798
+ "description": "Destination product area id (from list_product_areas)"
1799
+ },
1800
+ "from_area_id": {
1801
+ "type": "string",
1802
+ "description": "Source area id to remove from; omit to remove from all areas"
1803
+ }
1804
+ },
1805
+ "required": [
1806
+ "product_id",
1807
+ "to_area_id"
1808
+ ]
1809
+ },
1810
+ "throws": [
1811
+ "textError on a missing workspace, unknown product, or unknown target area."
1812
+ ],
1813
+ "examples": [],
1814
+ "warnings": [],
1815
+ "see": [
1816
+ "assign_product_to_area",
1817
+ "remove_product_from_area"
1818
+ ],
1819
+ "source": "src/tools/areas.ts:464",
1820
+ "symbol": "moveProductToAreaTool",
1821
+ "returns": "JSON: `{ product_id, to_area_id, to_area_title?, removed_from: string[], added }`.",
1822
+ "return_shape": "{ product_id, to_area_id, to_area_title?, removed_from: string[], added }",
1823
+ "atomicity": "atomic (single portfolio.upg flush)."
1824
+ },
1825
+ {
1826
+ "name": "remove_product_from_area",
1827
+ "description": "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`.",
1828
+ "domain": "areas",
1829
+ "inputSchema": {
1830
+ "type": "object",
1831
+ "properties": {
1832
+ "product_id": {
1833
+ "type": "string",
1834
+ "description": "Product id (from list_local_products)"
1835
+ },
1836
+ "area_id": {
1837
+ "type": "string",
1838
+ "description": "Product area id (from list_product_areas)"
1839
+ }
1840
+ },
1841
+ "required": [
1842
+ "product_id",
1843
+ "area_id"
1844
+ ]
1845
+ },
1846
+ "throws": [
1847
+ "textError on a missing workspace or an unknown area id."
1848
+ ],
1849
+ "examples": [],
1850
+ "warnings": [],
1851
+ "see": [
1852
+ "assign_product_to_area",
1853
+ "move_product_to_area"
1854
+ ],
1855
+ "source": "src/tools/areas.ts:414",
1856
+ "symbol": "removeProductFromAreaTool",
1857
+ "returns": "JSON: `{ product_id, container_id, container_kind: \"product_area\",\ncontainer_title?, removed }`. `removed: false` (not an error) when the product\nwas not a member, so retries are idempotent.",
1858
+ "return_shape": "{ product_id, container_id, container_kind: \"product_area\", container_title?, removed }",
1859
+ "return_notes": [
1860
+ "`removed: false` (not an error) when the product was not a member, so retries are idempotent."
1861
+ ],
1862
+ "atomicity": "atomic (single portfolio.upg flush)."
1863
+ },
1864
+ {
1865
+ "name": "update_area",
1866
+ "description": "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).",
1867
+ "domain": "areas",
1868
+ "inputSchema": {
1869
+ "type": "object",
1870
+ "properties": {
1871
+ "area_id": {
1872
+ "type": "string",
1873
+ "description": "Product area id to edit (from list_product_areas)"
1874
+ },
1875
+ "title": {
1876
+ "type": "string",
1877
+ "description": "New area title"
1878
+ },
1879
+ "description": {
1880
+ "type": "string",
1881
+ "description": "New area description"
1882
+ },
1883
+ "strategic_priority": {
1884
+ "type": "string",
1885
+ "enum": [
1886
+ "urgent",
1887
+ "high",
1888
+ "medium",
1889
+ "low",
1890
+ "none"
1891
+ ],
1892
+ "description": "Strategic priority (canonical Priority scale)"
1893
+ },
1894
+ "parent_area_id": {
1895
+ "type": [
1896
+ "string",
1897
+ "null"
1898
+ ],
1899
+ "description": "Re-parent under this area id; null un-nests (top-level); omit to leave unchanged"
1900
+ },
1901
+ "owner": {
1902
+ "type": "string",
1903
+ "description": "Person or team that owns this area"
1904
+ }
1905
+ },
1906
+ "required": [
1907
+ "area_id"
1908
+ ]
1909
+ },
1910
+ "throws": [
1911
+ "textError on a missing workspace, unknown area/parent, a re-parent cycle, or\nwhen no editable field is supplied."
1912
+ ],
1913
+ "examples": [],
1914
+ "warnings": [],
1915
+ "see": [
1916
+ "create_area",
1917
+ "list_product_areas"
1918
+ ],
1919
+ "source": "src/tools/areas.ts:367",
1920
+ "symbol": "updateAreaTool",
1921
+ "returns": "JSON: `{ message, area, updated: string[] }`.",
1922
+ "return_shape": "{ message, area, updated: string[] }",
1923
+ "atomicity": "atomic (single portfolio.upg flush)."
1924
+ },
1750
1925
  {
1751
1926
  "name": "attach_product_to_portfolio",
1752
1927
  "description": "Place an existing product under a portfolio (adds it to the portfolio's `products[]` in `.upg/portfolio.upg`). Resolves the portfolio against the portfolio document and auto-registers the product on the portfolio registry. Use after `create_product`, or pass `portfolio_id` to `create_product` directly.",
@@ -1777,15 +1952,89 @@
1777
1952
  "assign_product_to_area",
1778
1953
  "create_product"
1779
1954
  ],
1780
- "source": "src/tools/workspace.ts:737",
1955
+ "source": "src/tools/workspace.ts:777",
1781
1956
  "symbol": "attachProductToPortfolioTool",
1782
1957
  "returns": "JSON: `{ product_id, container_id, container_kind: \"portfolio\",\ncontainer_title?, already_member, registered }`.",
1783
1958
  "return_shape": "{ product_id, container_id, container_kind: \"portfolio\", container_title?, already_member, registered }",
1784
1959
  "atomicity": "atomic (single portfolio.upg flush)."
1785
1960
  },
1961
+ {
1962
+ "name": "batch_create_cross_product_edges",
1963
+ "description": "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.",
1964
+ "domain": "workspace",
1965
+ "inputSchema": {
1966
+ "type": "object",
1967
+ "properties": {
1968
+ "edges": {
1969
+ "type": "array",
1970
+ "description": "Cross-product edges to create (max 50). Each: { source_id, target_id, type, source_product_id?, target_product_id? }.",
1971
+ "items": {
1972
+ "type": "object",
1973
+ "properties": {
1974
+ "source_id": {
1975
+ "type": "string",
1976
+ "description": "Source node ID (bare or qualified {product_id}/{node_id})"
1977
+ },
1978
+ "target_id": {
1979
+ "type": "string",
1980
+ "description": "Target node ID (bare or qualified {product_id}/{node_id})"
1981
+ },
1982
+ "type": {
1983
+ "type": "string",
1984
+ "enum": [
1985
+ "shares_persona",
1986
+ "shares_competitor",
1987
+ "shares_metric",
1988
+ "depends_on_product",
1989
+ "cannibalises",
1990
+ "succeeds",
1991
+ "hosts"
1992
+ ],
1993
+ "description": "Cross-product relationship type"
1994
+ },
1995
+ "source_product_id": {
1996
+ "type": "string",
1997
+ "description": "Product ID of the source node (qualifies a bare source_id)"
1998
+ },
1999
+ "target_product_id": {
2000
+ "type": "string",
2001
+ "description": "Product ID of the target node (qualifies a bare target_id)"
2002
+ }
2003
+ },
2004
+ "required": [
2005
+ "source_id",
2006
+ "target_id",
2007
+ "type"
2008
+ ]
2009
+ }
2010
+ },
2011
+ "auto_create_portfolio": {
2012
+ "type": "boolean",
2013
+ "description": "Create an empty portfolio document if none exists (default false)"
2014
+ }
2015
+ },
2016
+ "required": [
2017
+ "edges"
2018
+ ]
2019
+ },
2020
+ "throws": [
2021
+ "textError when `edges` is missing/empty/oversized, when any edge is invalid,\nor when no portfolio document exists (pass `auto_create_portfolio: true` to mint one)."
2022
+ ],
2023
+ "examples": [],
2024
+ "warnings": [],
2025
+ "see": [
2026
+ "create_cross_product_edge",
2027
+ "list_cross_edge_types"
2028
+ ],
2029
+ "source": "src/tools/workspace.ts:860",
2030
+ "symbol": "batchCreateCrossProductEdges",
2031
+ "returns": "JSON: `{ message, created: UPGCrossEdge[], count, portfolio_file,\nregistered_products? }`.",
2032
+ "return_shape": "{ message, created: UPGCrossEdge[], count, portfolio_file, registered_products? }",
2033
+ "atomicity": "atomic. All edges validated first, then a single portfolio.upg flush."
2034
+ },
1786
2035
  {
1787
2036
  "name": "create_cross_product_edge",
1788
- "description": "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`.",
2037
+ "description": "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).",
1789
2038
  "domain": "workspace",
1790
2039
  "inputSchema": {
1791
2040
  "type": "object",
@@ -1806,7 +2055,8 @@
1806
2055
  "shares_metric",
1807
2056
  "depends_on_product",
1808
2057
  "cannibalises",
1809
- "succeeds"
2058
+ "succeeds",
2059
+ "hosts"
1810
2060
  ],
1811
2061
  "description": "Cross-product relationship type"
1812
2062
  },
@@ -1835,7 +2085,7 @@
1835
2085
  "list_portfolio_cross_edges",
1836
2086
  "migrate_cross_edges"
1837
2087
  ],
1838
- "source": "src/tools/workspace.ts:454",
2088
+ "source": "src/tools/workspace.ts:494",
1839
2089
  "symbol": "createCrossProductEdge",
1840
2090
  "returns": "JSON: `{ edge, portfolio_file }`.",
1841
2091
  "return_shape": "{ edge, portfolio_file }",
@@ -1891,7 +2141,7 @@
1891
2141
  "see": [
1892
2142
  "init_workspace"
1893
2143
  ],
1894
- "source": "src/tools/workspace.ts:295",
2144
+ "source": "src/tools/workspace.ts:335",
1895
2145
  "symbol": "createProductTool",
1896
2146
  "returns": "JSON: `{ message, ...result }`. `result` carries `id`, `title`,\n`slug`, `file_path`, and the optional portfolio edge.",
1897
2147
  "return_shape": "{ message,...result }",
@@ -1900,6 +2150,78 @@
1900
2150
  ],
1901
2151
  "atomicity": "non-atomic. File write + workspace.json patch + optional\nportfolio edge are separate mutations."
1902
2152
  },
2153
+ {
2154
+ "name": "delete_cross_product_edge",
2155
+ "description": "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.",
2156
+ "domain": "workspace",
2157
+ "inputSchema": {
2158
+ "type": "object",
2159
+ "properties": {
2160
+ "edge_id": {
2161
+ "type": "string",
2162
+ "description": "Cross-product edge id (from list_portfolio_cross_edges)"
2163
+ }
2164
+ },
2165
+ "required": [
2166
+ "edge_id"
2167
+ ]
2168
+ },
2169
+ "throws": [
2170
+ "textError on a missing workspace."
2171
+ ],
2172
+ "examples": [],
2173
+ "warnings": [],
2174
+ "see": [
2175
+ "create_cross_product_edge",
2176
+ "list_portfolio_cross_edges"
2177
+ ],
2178
+ "source": "src/tools/workspace.ts:831",
2179
+ "symbol": "deleteCrossProductEdgeTool",
2180
+ "returns": "JSON: `{ edge_id, deleted, edge? }`. `deleted: false` (not an error) when\nno edge with that id exists, so retries are idempotent.",
2181
+ "return_shape": "{ edge_id, deleted, edge? }",
2182
+ "return_notes": [
2183
+ "`deleted: false` (not an error) when no edge with that id exists, so retries are idempotent."
2184
+ ],
2185
+ "atomicity": "atomic (single portfolio.upg flush)."
2186
+ },
2187
+ {
2188
+ "name": "detach_product_from_portfolio",
2189
+ "description": "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`.",
2190
+ "domain": "workspace",
2191
+ "inputSchema": {
2192
+ "type": "object",
2193
+ "properties": {
2194
+ "product_id": {
2195
+ "type": "string",
2196
+ "description": "Product id (from list_local_products)"
2197
+ },
2198
+ "portfolio_id": {
2199
+ "type": "string",
2200
+ "description": "Portfolio id (from list_portfolios)"
2201
+ }
2202
+ },
2203
+ "required": [
2204
+ "product_id",
2205
+ "portfolio_id"
2206
+ ]
2207
+ },
2208
+ "throws": [
2209
+ "textError on a missing workspace or an unknown portfolio id."
2210
+ ],
2211
+ "examples": [],
2212
+ "warnings": [],
2213
+ "see": [
2214
+ "attach_product_to_portfolio"
2215
+ ],
2216
+ "source": "src/tools/workspace.ts:804",
2217
+ "symbol": "detachProductFromPortfolioTool",
2218
+ "returns": "JSON: `{ product_id, container_id, container_kind: \"portfolio\",\ncontainer_title?, removed }`. `removed: false` (not an error) when the product was\nnot a member, so retries are idempotent.",
2219
+ "return_shape": "{ product_id, container_id, container_kind: \"portfolio\", container_title?, removed }",
2220
+ "return_notes": [
2221
+ "`removed: false` (not an error) when the product was not a member, so retries are idempotent."
2222
+ ],
2223
+ "atomicity": "atomic (single portfolio.upg flush)."
2224
+ },
1903
2225
  {
1904
2226
  "name": "get_organization",
1905
2227
  "description": "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.",
@@ -1920,7 +2242,7 @@
1920
2242
  "see": [
1921
2243
  "list_portfolios"
1922
2244
  ],
1923
- "source": "src/tools/workspace.ts:403",
2245
+ "source": "src/tools/workspace.ts:443",
1924
2246
  "symbol": "getOrganization",
1925
2247
  "returns": "JSON: `{ organization: UPGOrganization | null, portfolio_file? }`.\nReturns `{ organization: null }` when no portfolio document exists yet.",
1926
2248
  "return_shape": "{ organization: UPGOrganization | null, portfolio_file? }",
@@ -1949,7 +2271,7 @@
1949
2271
  "see": [
1950
2272
  "init_workspace"
1951
2273
  ],
1952
- "source": "src/tools/workspace.ts:183",
2274
+ "source": "src/tools/workspace.ts:223",
1953
2275
  "symbol": "getWorkspaceInfo",
1954
2276
  "returns": "JSON: `{ mode, workspace_path?, current_product?, current_file?,\nproducts }`. The shape depends on whether `.upg/workspace.json` exists.",
1955
2277
  "return_shape": "{ mode, workspace_path?, current_product?, current_file?, products }",
@@ -1989,7 +2311,7 @@
1989
2311
  "switch_product",
1990
2312
  "get_workspace_info"
1991
2313
  ],
1992
- "source": "src/tools/workspace.ts:259",
2314
+ "source": "src/tools/workspace.ts:299",
1993
2315
  "symbol": "initWorkspaceTool",
1994
2316
  "returns": "JSON: `{ message, ...result }`. `result` carries the workspace\npath and the moved file's new location.",
1995
2317
  "return_shape": "{ message,...result }",
@@ -2019,7 +2341,7 @@
2019
2341
  "switch_product",
2020
2342
  "get_workspace_info"
2021
2343
  ],
2022
- "source": "src/tools/workspace.ts:46",
2344
+ "source": "src/tools/workspace.ts:48",
2023
2345
  "symbol": "listLocalProducts",
2024
2346
  "returns": "JSON: `{ products: Array<{ file, title, stage, nodes, edges }> }`.\n`stage` is the CANONICAL UPGProductStage (legacy values like `idea` are\ncoerced to `concept`), or `null` when unset — matching what\n`get_product_context` reports for the same product (UPG-611 / DT-MCP-3).",
2025
2347
  "return_shape": "{ products: Array<{ file, title, stage, nodes, edges }> }",
@@ -2042,7 +2364,7 @@
2042
2364
  "see": [
2043
2365
  "create_cross_product_edge"
2044
2366
  ],
2045
- "source": "src/tools/workspace.ts:593",
2367
+ "source": "src/tools/workspace.ts:633",
2046
2368
  "symbol": "listPortfolioCrossEdges",
2047
2369
  "returns": "JSON: `{ cross_edges: UPGCrossEdge[], total, portfolio_file? }`.",
2048
2370
  "return_shape": "{ cross_edges: UPGCrossEdge[], total, portfolio_file? }",
@@ -2069,7 +2391,7 @@
2069
2391
  "create_cross_product_edge",
2070
2392
  "get_organization"
2071
2393
  ],
2072
- "source": "src/tools/workspace.ts:376",
2394
+ "source": "src/tools/workspace.ts:416",
2073
2395
  "symbol": "listPortfolios",
2074
2396
  "returns": "JSON: `{ portfolios: Array<{ id, title, description?,\nparent_portfolio_id?, hierarchy_model?, products? }>, total }`.",
2075
2397
  "return_shape": "{ portfolios: Array<{ id, title, description?, parent_portfolio_id?, hierarchy_model?, products? }>, total }",
@@ -2112,7 +2434,7 @@
2112
2434
  "list_cross_edge_types",
2113
2435
  "init_workspace"
2114
2436
  ],
2115
- "source": "src/tools/workspace.ts:662",
2437
+ "source": "src/tools/workspace.ts:702",
2116
2438
  "symbol": "migrateCrossEdges",
2117
2439
  "returns": "JSON: `{ migrated, skipped, dry_run, portfolio_file? }`.",
2118
2440
  "return_shape": "{ migrated, skipped, dry_run, portfolio_file? }",
@@ -2150,7 +2472,7 @@
2150
2472
  "list_local_products",
2151
2473
  "init_workspace"
2152
2474
  ],
2153
- "source": "src/tools/workspace.ts:120",
2475
+ "source": "src/tools/workspace.ts:160",
2154
2476
  "symbol": "switchProduct",
2155
2477
  "returns": "JSON: `{ message, file, product: { title, stage }, entities }`.",
2156
2478
  "return_shape": "{ message, file, product: { title, stage }, entities }",
@@ -2193,7 +2515,7 @@
2193
2515
  "see": [
2194
2516
  "create_product"
2195
2517
  ],
2196
- "source": "src/tools/workspace.ts:336",
2518
+ "source": "src/tools/workspace.ts:376",
2197
2519
  "symbol": "updateProductTool",
2198
2520
  "returns": "JSON: `{ product, updated: string[] }` (the fields changed).",
2199
2521
  "return_shape": "{ product, updated: string[] }",
@@ -3142,7 +3464,7 @@
3142
3464
  },
3143
3465
  {
3144
3466
  "name": "list_cross_edge_types",
3145
- "description": "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`.",
3467
+ "description": "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`.",
3146
3468
  "domain": "spec",
3147
3469
  "inputSchema": {
3148
3470
  "type": "object",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unified-product-graph/mcp-server",
3
- "version": "0.8.15",
3
+ "version": "0.8.16",
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>",
@@ -52,8 +52,8 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@modelcontextprotocol/sdk": "^1.27.0",
55
- "@unified-product-graph/core": "0.8.15",
56
- "@unified-product-graph/sdk": "0.8.15",
55
+ "@unified-product-graph/core": "0.8.16",
56
+ "@unified-product-graph/sdk": "0.8.16",
57
57
  "chokidar": "^4.0.0",
58
58
  "nanoid": "^5.1.0"
59
59
  },