mindgraph-mcp 0.13.4 → 0.13.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +228 -205
- package/dist/index.js +217 -202
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1486,9 +1486,13 @@ var init_tools = __esm({
|
|
|
1486
1486
|
|
|
1487
1487
|
// src/generated-tools.ts
|
|
1488
1488
|
async function getGeneratedTools(client2) {
|
|
1489
|
-
|
|
1489
|
+
const now = Date.now();
|
|
1490
|
+
if (cache && now - cache.fetchedAt < CACHE_TTL_MS) {
|
|
1490
1491
|
return { tools: cache.tools, byName: cache.byName };
|
|
1491
1492
|
}
|
|
1493
|
+
if (now < retryNotBefore) {
|
|
1494
|
+
return cache ? { tools: cache.tools, byName: cache.byName } : EMPTY;
|
|
1495
|
+
}
|
|
1492
1496
|
try {
|
|
1493
1497
|
const c = client2;
|
|
1494
1498
|
if (typeof c.listOntologyTools !== "function") {
|
|
@@ -1512,11 +1516,12 @@ async function getGeneratedTools(client2) {
|
|
|
1512
1516
|
});
|
|
1513
1517
|
}
|
|
1514
1518
|
cache = { tools, byName, fetchedAt: Date.now() };
|
|
1519
|
+
retryNotBefore = 0;
|
|
1515
1520
|
return { tools, byName };
|
|
1516
1521
|
} catch (error) {
|
|
1517
1522
|
if (error instanceof DuplicateGeneratedToolError) throw error;
|
|
1518
|
-
|
|
1519
|
-
return { tools: cache.tools, byName: cache.byName };
|
|
1523
|
+
retryNotBefore = Date.now() + FAILURE_COOLDOWN_MS;
|
|
1524
|
+
return cache ? { tools: cache.tools, byName: cache.byName } : EMPTY;
|
|
1520
1525
|
}
|
|
1521
1526
|
}
|
|
1522
1527
|
async function handleGeneratedTool(client2, desc, args) {
|
|
@@ -1586,11 +1591,14 @@ async function handleGeneratedTool(client2, desc, args) {
|
|
|
1586
1591
|
"structured ontology tools require a graph-aware version of the mindgraph SDK"
|
|
1587
1592
|
);
|
|
1588
1593
|
}
|
|
1589
|
-
|
|
1590
|
-
...args,
|
|
1594
|
+
const request = {
|
|
1591
1595
|
schema_id: desc.schema_id,
|
|
1592
1596
|
select
|
|
1593
|
-
}
|
|
1597
|
+
};
|
|
1598
|
+
for (const field of STRUCTURED_QUERY_PASSTHROUGH) {
|
|
1599
|
+
if (args[field] !== void 0) request[field] = args[field];
|
|
1600
|
+
}
|
|
1601
|
+
return ok2(await ontologyClient.queryDomainStructured(request));
|
|
1594
1602
|
}
|
|
1595
1603
|
default:
|
|
1596
1604
|
return err2(`unknown generated tool mapping: ${desc.maps_to}`);
|
|
@@ -1599,7 +1607,7 @@ async function handleGeneratedTool(client2, desc, args) {
|
|
|
1599
1607
|
return err2(e instanceof Error ? e.message : String(e));
|
|
1600
1608
|
}
|
|
1601
1609
|
}
|
|
1602
|
-
var ok2, err2, CACHE_TTL_MS, cache, DuplicateGeneratedToolError;
|
|
1610
|
+
var ok2, err2, CACHE_TTL_MS, FAILURE_COOLDOWN_MS, cache, retryNotBefore, EMPTY, DuplicateGeneratedToolError, STRUCTURED_QUERY_PASSTHROUGH;
|
|
1603
1611
|
var init_generated_tools = __esm({
|
|
1604
1612
|
"src/generated-tools.ts"() {
|
|
1605
1613
|
"use strict";
|
|
@@ -1611,13 +1619,33 @@ var init_generated_tools = __esm({
|
|
|
1611
1619
|
isError: true
|
|
1612
1620
|
});
|
|
1613
1621
|
CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
1622
|
+
FAILURE_COOLDOWN_MS = 15 * 1e3;
|
|
1614
1623
|
cache = null;
|
|
1624
|
+
retryNotBefore = 0;
|
|
1625
|
+
EMPTY = {
|
|
1626
|
+
tools: [],
|
|
1627
|
+
byName: /* @__PURE__ */ new Map()
|
|
1628
|
+
};
|
|
1615
1629
|
DuplicateGeneratedToolError = class extends Error {
|
|
1616
1630
|
};
|
|
1631
|
+
STRUCTURED_QUERY_PASSTHROUGH = [
|
|
1632
|
+
"anchor",
|
|
1633
|
+
"path",
|
|
1634
|
+
"where",
|
|
1635
|
+
"include",
|
|
1636
|
+
"page",
|
|
1637
|
+
"aggregate"
|
|
1638
|
+
];
|
|
1617
1639
|
}
|
|
1618
1640
|
});
|
|
1619
1641
|
|
|
1620
1642
|
// src/governance.ts
|
|
1643
|
+
function isTransientStatus(status) {
|
|
1644
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
1645
|
+
}
|
|
1646
|
+
function sleep(ms) {
|
|
1647
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1648
|
+
}
|
|
1621
1649
|
function headers(apiKey, orgId) {
|
|
1622
1650
|
const value = {
|
|
1623
1651
|
authorization: `Bearer ${apiKey}`,
|
|
@@ -1633,41 +1661,81 @@ function unsupportedResponse(status, body) {
|
|
|
1633
1661
|
return lower.includes("unknown governance action") || lower.includes("unknown action") || lower.includes("invalid_governance_action");
|
|
1634
1662
|
}
|
|
1635
1663
|
async function checkMcpGovernance(toolName, args, config) {
|
|
1636
|
-
if (config.disabled
|
|
1664
|
+
if (config.disabled) return { allowed: true };
|
|
1665
|
+
if (capability === "unsupported") {
|
|
1666
|
+
if (Date.now() < unsupportedUntil) return { allowed: true };
|
|
1667
|
+
capability = "unknown";
|
|
1668
|
+
}
|
|
1637
1669
|
const fetchImpl = config.fetchImpl ?? fetch;
|
|
1670
|
+
const retryDelays = config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS;
|
|
1638
1671
|
let response;
|
|
1639
|
-
let body;
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1672
|
+
let body = "";
|
|
1673
|
+
let lastFailure = "";
|
|
1674
|
+
for (let attempt = 0; attempt <= retryDelays.length; attempt++) {
|
|
1675
|
+
try {
|
|
1676
|
+
const candidate = await fetchImpl(
|
|
1677
|
+
`${config.baseUrl.replace(/\/$/, "")}/agent/governance`,
|
|
1678
|
+
{
|
|
1679
|
+
method: "POST",
|
|
1680
|
+
headers: headers(config.apiKey, config.orgId),
|
|
1681
|
+
body: JSON.stringify({
|
|
1682
|
+
action: "check",
|
|
1683
|
+
act: "tool_invoke",
|
|
1684
|
+
agent_id: String(args.agent_id || config.agentId),
|
|
1685
|
+
target: { tool_name: toolName },
|
|
1686
|
+
context: { adapter: "mindgraph-mcp", ...config.context },
|
|
1687
|
+
tier: "checkpoint"
|
|
1688
|
+
})
|
|
1689
|
+
}
|
|
1690
|
+
);
|
|
1691
|
+
const candidateBody = await candidate.text();
|
|
1692
|
+
if (isTransientStatus(candidate.status) && attempt < retryDelays.length) {
|
|
1693
|
+
lastFailure = `HTTP ${candidate.status}`;
|
|
1694
|
+
await sleep(retryDelays[attempt]);
|
|
1695
|
+
continue;
|
|
1696
|
+
}
|
|
1697
|
+
response = candidate;
|
|
1698
|
+
body = candidateBody;
|
|
1699
|
+
break;
|
|
1700
|
+
} catch (error) {
|
|
1701
|
+
lastFailure = error instanceof Error ? error.message : String(error);
|
|
1702
|
+
if (attempt < retryDelays.length) {
|
|
1703
|
+
await sleep(retryDelays[attempt]);
|
|
1704
|
+
continue;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
if (!response) {
|
|
1655
1709
|
return {
|
|
1656
1710
|
allowed: false,
|
|
1657
|
-
message: `MindGraph governance could not establish permission
|
|
1711
|
+
message: `MindGraph governance could not establish permission after ${retryDelays.length + 1} attempts (${lastFailure}). Set MINDGRAPH_GOVERNANCE=off to run this adapter ungoverned.`
|
|
1658
1712
|
};
|
|
1659
1713
|
}
|
|
1660
1714
|
if (!response.ok) {
|
|
1661
1715
|
if (capability === "unknown" && unsupportedResponse(response.status, body)) {
|
|
1662
1716
|
capability = "unsupported";
|
|
1717
|
+
unsupportedUntil = Date.now() + UNSUPPORTED_LEASE_MS;
|
|
1718
|
+
if (!unsupportedLogged) {
|
|
1719
|
+
unsupportedLogged = true;
|
|
1720
|
+
console.error(
|
|
1721
|
+
`[mindgraph-mcp] This MindGraph server does not implement the governance checkpoint (HTTP ${response.status}); tool calls proceed ungoverned. Re-probing every ${Math.round(UNSUPPORTED_LEASE_MS / 6e4)} minutes.`
|
|
1722
|
+
);
|
|
1723
|
+
}
|
|
1663
1724
|
return { allowed: true };
|
|
1664
1725
|
}
|
|
1726
|
+
if (response.status === 401 || response.status === 403) {
|
|
1727
|
+
return {
|
|
1728
|
+
allowed: false,
|
|
1729
|
+
message: `This credential is not permitted to evaluate MindGraph governance (HTTP ${response.status}). Use a user-scoped API key, or set MINDGRAPH_GOVERNANCE=off to run this adapter ungoverned.`
|
|
1730
|
+
};
|
|
1731
|
+
}
|
|
1665
1732
|
return {
|
|
1666
1733
|
allowed: false,
|
|
1667
1734
|
message: `MindGraph governance check failed (${response.status})`
|
|
1668
1735
|
};
|
|
1669
1736
|
}
|
|
1670
1737
|
capability = "supported";
|
|
1738
|
+
unsupportedLogged = false;
|
|
1671
1739
|
let decision;
|
|
1672
1740
|
try {
|
|
1673
1741
|
decision = JSON.parse(body);
|
|
@@ -1701,15 +1769,130 @@ async function checkMcpGovernance(toolName, args, config) {
|
|
|
1701
1769
|
message: verdict === "conditional" ? `Approval is required${policy ? ` by policy ${policy}` : ""}${approvalUid ? ` (approval ${approvalUid})` : ""}` : `Denied by MindGraph governance${policy ? ` policy ${policy}` : ""}`
|
|
1702
1770
|
};
|
|
1703
1771
|
}
|
|
1704
|
-
var capability, KNOWN_DUTIES;
|
|
1772
|
+
var capability, UNSUPPORTED_LEASE_MS, unsupportedUntil, unsupportedLogged, DEFAULT_RETRY_DELAYS_MS, KNOWN_DUTIES;
|
|
1705
1773
|
var init_governance = __esm({
|
|
1706
1774
|
"src/governance.ts"() {
|
|
1707
1775
|
"use strict";
|
|
1708
1776
|
capability = "unknown";
|
|
1777
|
+
UNSUPPORTED_LEASE_MS = 5 * 60 * 1e3;
|
|
1778
|
+
unsupportedUntil = 0;
|
|
1779
|
+
unsupportedLogged = false;
|
|
1780
|
+
DEFAULT_RETRY_DELAYS_MS = [150, 600];
|
|
1709
1781
|
KNOWN_DUTIES = /* @__PURE__ */ new Set(["log", "require_approval"]);
|
|
1710
1782
|
}
|
|
1711
1783
|
});
|
|
1712
1784
|
|
|
1785
|
+
// src/resources.ts
|
|
1786
|
+
function json(uri, data) {
|
|
1787
|
+
return {
|
|
1788
|
+
contents: [{ uri, mimeType: "application/json", text: JSON.stringify(data, null, 2) }]
|
|
1789
|
+
};
|
|
1790
|
+
}
|
|
1791
|
+
async function readResource(client2, uri) {
|
|
1792
|
+
switch (uri) {
|
|
1793
|
+
case "mindgraph://stats":
|
|
1794
|
+
return json(uri, await client2.stats());
|
|
1795
|
+
case "mindgraph://goals":
|
|
1796
|
+
return json(uri, await client2.getGoals());
|
|
1797
|
+
case "mindgraph://questions":
|
|
1798
|
+
return json(uri, await client2.getOpenQuestions());
|
|
1799
|
+
case "mindgraph://contradictions":
|
|
1800
|
+
return json(uri, await client2.getContradictions());
|
|
1801
|
+
case "mindgraph://decisions":
|
|
1802
|
+
return json(uri, await client2.getOpenDecisions());
|
|
1803
|
+
}
|
|
1804
|
+
const nodeMatch = uri.match(/^mindgraph:\/\/node\/(.+)$/);
|
|
1805
|
+
if (nodeMatch) {
|
|
1806
|
+
const uid = decodeURIComponent(nodeMatch[1]);
|
|
1807
|
+
const node = await client2.getNode(uid);
|
|
1808
|
+
const edges = await client2.getEdges({ from_uid: uid });
|
|
1809
|
+
const inEdges = await client2.getEdges({ to_uid: uid });
|
|
1810
|
+
return json(uri, { node, outgoing_edges: edges, incoming_edges: inEdges });
|
|
1811
|
+
}
|
|
1812
|
+
const searchMatch = uri.match(/^mindgraph:\/\/search\/(.+)$/);
|
|
1813
|
+
if (searchMatch) {
|
|
1814
|
+
const query = decodeURIComponent(searchMatch[1]);
|
|
1815
|
+
return json(uri, await client2.search(query, { limit: 20 }));
|
|
1816
|
+
}
|
|
1817
|
+
const layerMatch = uri.match(/^mindgraph:\/\/layer\/(.+)$/);
|
|
1818
|
+
if (layerMatch) {
|
|
1819
|
+
const layer = decodeURIComponent(layerMatch[1]);
|
|
1820
|
+
return json(uri, await client2.getNodes({ layer, limit: 50 }));
|
|
1821
|
+
}
|
|
1822
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
1823
|
+
}
|
|
1824
|
+
async function readGovernedResource(client2, uri, governanceConfig) {
|
|
1825
|
+
const governance = await checkMcpGovernance(
|
|
1826
|
+
RESOURCE_GOVERNANCE_TOOL,
|
|
1827
|
+
{},
|
|
1828
|
+
{ ...governanceConfig, context: { resource_uri: uri } }
|
|
1829
|
+
);
|
|
1830
|
+
if (!governance.allowed) {
|
|
1831
|
+
throw new Error(governance.message);
|
|
1832
|
+
}
|
|
1833
|
+
return readResource(client2, uri);
|
|
1834
|
+
}
|
|
1835
|
+
var RESOURCES, RESOURCE_TEMPLATES, RESOURCE_GOVERNANCE_TOOL;
|
|
1836
|
+
var init_resources = __esm({
|
|
1837
|
+
"src/resources.ts"() {
|
|
1838
|
+
"use strict";
|
|
1839
|
+
init_governance();
|
|
1840
|
+
RESOURCES = [
|
|
1841
|
+
{
|
|
1842
|
+
uri: "mindgraph://stats",
|
|
1843
|
+
name: "Graph Statistics",
|
|
1844
|
+
description: "Current knowledge graph statistics: node counts, edge counts, and layer distribution",
|
|
1845
|
+
mimeType: "application/json"
|
|
1846
|
+
},
|
|
1847
|
+
{
|
|
1848
|
+
uri: "mindgraph://goals",
|
|
1849
|
+
name: "Active Goals",
|
|
1850
|
+
description: "All active goals in the knowledge graph",
|
|
1851
|
+
mimeType: "application/json"
|
|
1852
|
+
},
|
|
1853
|
+
{
|
|
1854
|
+
uri: "mindgraph://questions",
|
|
1855
|
+
name: "Open Questions",
|
|
1856
|
+
description: "All open questions in the knowledge graph",
|
|
1857
|
+
mimeType: "application/json"
|
|
1858
|
+
},
|
|
1859
|
+
{
|
|
1860
|
+
uri: "mindgraph://contradictions",
|
|
1861
|
+
name: "Contradictions",
|
|
1862
|
+
description: "Contradictory claims in the knowledge graph",
|
|
1863
|
+
mimeType: "application/json"
|
|
1864
|
+
},
|
|
1865
|
+
{
|
|
1866
|
+
uri: "mindgraph://decisions",
|
|
1867
|
+
name: "Open Decisions",
|
|
1868
|
+
description: "Unresolved decisions awaiting resolution",
|
|
1869
|
+
mimeType: "application/json"
|
|
1870
|
+
}
|
|
1871
|
+
];
|
|
1872
|
+
RESOURCE_TEMPLATES = [
|
|
1873
|
+
{
|
|
1874
|
+
uriTemplate: "mindgraph://node/{uid}",
|
|
1875
|
+
name: "Graph Node",
|
|
1876
|
+
description: "Retrieve a specific node by its UID, including all properties, edges, and version history",
|
|
1877
|
+
mimeType: "application/json"
|
|
1878
|
+
},
|
|
1879
|
+
{
|
|
1880
|
+
uriTemplate: "mindgraph://search/{query}",
|
|
1881
|
+
name: "Search Results",
|
|
1882
|
+
description: "BM25 keyword search across all nodes \u2014 pass 1\u20133 discriminating terms (e.g. 'Kissinger NATO'), not natural language sentences",
|
|
1883
|
+
mimeType: "application/json"
|
|
1884
|
+
},
|
|
1885
|
+
{
|
|
1886
|
+
uriTemplate: "mindgraph://layer/{layer}",
|
|
1887
|
+
name: "Layer Nodes",
|
|
1888
|
+
description: "List all nodes in a specific cognitive layer (reality, epistemic, intent, action, memory, agent)",
|
|
1889
|
+
mimeType: "application/json"
|
|
1890
|
+
}
|
|
1891
|
+
];
|
|
1892
|
+
RESOURCE_GOVERNANCE_TOOL = "mindgraph_retrieve";
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
|
|
1713
1896
|
// src/index.ts
|
|
1714
1897
|
var src_exports = {};
|
|
1715
1898
|
async function main() {
|
|
@@ -1719,7 +1902,7 @@ async function main() {
|
|
|
1719
1902
|
`MindGraph MCP server v0.7.1 running on stdio (${BASE_URL})`
|
|
1720
1903
|
);
|
|
1721
1904
|
}
|
|
1722
|
-
var import_server, import_stdio, import_types, import_mindgraph, API_KEY, BASE_URL, AGENT_ID, ORG_ID, client, INSTRUCTIONS, server, PROMPTS;
|
|
1905
|
+
var import_server, import_stdio, import_types, import_mindgraph, API_KEY, BASE_URL, AGENT_ID, ORG_ID, client, INSTRUCTIONS, server, GOVERNANCE_CONFIG, PROMPTS;
|
|
1723
1906
|
var init_src = __esm({
|
|
1724
1907
|
"src/index.ts"() {
|
|
1725
1908
|
"use strict";
|
|
@@ -1730,6 +1913,7 @@ var init_src = __esm({
|
|
|
1730
1913
|
init_tools();
|
|
1731
1914
|
init_generated_tools();
|
|
1732
1915
|
init_governance();
|
|
1916
|
+
init_resources();
|
|
1733
1917
|
API_KEY = process.env.MINDGRAPH_API_KEY;
|
|
1734
1918
|
BASE_URL = process.env.MINDGRAPH_BASE_URL || "https://api.mindgraph.cloud";
|
|
1735
1919
|
AGENT_ID = process.env.MINDGRAPH_AGENT_ID || "mcp";
|
|
@@ -1827,7 +2011,7 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
1827
2011
|
server = new import_server.Server(
|
|
1828
2012
|
{
|
|
1829
2013
|
name: "mindgraph",
|
|
1830
|
-
version: "0.13.
|
|
2014
|
+
version: "0.13.5"
|
|
1831
2015
|
},
|
|
1832
2016
|
{
|
|
1833
2017
|
capabilities: {
|
|
@@ -1842,19 +2026,23 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
1842
2026
|
const generated = await getGeneratedTools(client);
|
|
1843
2027
|
return { tools: [...TOOLS, ...generated.tools] };
|
|
1844
2028
|
});
|
|
2029
|
+
GOVERNANCE_CONFIG = {
|
|
2030
|
+
baseUrl: BASE_URL,
|
|
2031
|
+
apiKey: API_KEY,
|
|
2032
|
+
orgId: ORG_ID,
|
|
2033
|
+
agentId: AGENT_ID,
|
|
2034
|
+
get disabled() {
|
|
2035
|
+
return process.env.MINDGRAPH_GOVERNANCE === "off";
|
|
2036
|
+
}
|
|
2037
|
+
};
|
|
1845
2038
|
server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
|
|
1846
2039
|
const { name, arguments: args } = request.params;
|
|
1847
|
-
const
|
|
2040
|
+
const rawArgs = { ...args || {} };
|
|
2041
|
+
const toolArgs = { ...rawArgs };
|
|
1848
2042
|
if (!toolArgs.agent_id) {
|
|
1849
2043
|
toolArgs.agent_id = AGENT_ID;
|
|
1850
2044
|
}
|
|
1851
|
-
const governance = await checkMcpGovernance(name, toolArgs,
|
|
1852
|
-
baseUrl: BASE_URL,
|
|
1853
|
-
apiKey: API_KEY,
|
|
1854
|
-
orgId: ORG_ID,
|
|
1855
|
-
agentId: AGENT_ID,
|
|
1856
|
-
disabled: process.env.MINDGRAPH_GOVERNANCE === "off"
|
|
1857
|
-
});
|
|
2045
|
+
const governance = await checkMcpGovernance(name, toolArgs, GOVERNANCE_CONFIG);
|
|
1858
2046
|
if (!governance.allowed) {
|
|
1859
2047
|
return {
|
|
1860
2048
|
content: [{ type: "text", text: JSON.stringify({ error: governance.message, ...governance }) }],
|
|
@@ -1864,7 +2052,7 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
1864
2052
|
const generated = await getGeneratedTools(client);
|
|
1865
2053
|
const desc = generated.byName.get(name);
|
|
1866
2054
|
if (desc) {
|
|
1867
|
-
return handleGeneratedTool(client, desc,
|
|
2055
|
+
return handleGeneratedTool(client, desc, rawArgs);
|
|
1868
2056
|
}
|
|
1869
2057
|
return handleTool(client, name, toolArgs);
|
|
1870
2058
|
});
|
|
@@ -2025,178 +2213,13 @@ ${conversation}`
|
|
|
2025
2213
|
}
|
|
2026
2214
|
});
|
|
2027
2215
|
server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => {
|
|
2028
|
-
return {
|
|
2029
|
-
resources: [
|
|
2030
|
-
{
|
|
2031
|
-
uri: "mindgraph://stats",
|
|
2032
|
-
name: "Graph Statistics",
|
|
2033
|
-
description: "Current knowledge graph statistics: node counts, edge counts, and layer distribution",
|
|
2034
|
-
mimeType: "application/json"
|
|
2035
|
-
},
|
|
2036
|
-
{
|
|
2037
|
-
uri: "mindgraph://goals",
|
|
2038
|
-
name: "Active Goals",
|
|
2039
|
-
description: "All active goals in the knowledge graph",
|
|
2040
|
-
mimeType: "application/json"
|
|
2041
|
-
},
|
|
2042
|
-
{
|
|
2043
|
-
uri: "mindgraph://questions",
|
|
2044
|
-
name: "Open Questions",
|
|
2045
|
-
description: "All open questions in the knowledge graph",
|
|
2046
|
-
mimeType: "application/json"
|
|
2047
|
-
},
|
|
2048
|
-
{
|
|
2049
|
-
uri: "mindgraph://contradictions",
|
|
2050
|
-
name: "Contradictions",
|
|
2051
|
-
description: "Contradictory claims in the knowledge graph",
|
|
2052
|
-
mimeType: "application/json"
|
|
2053
|
-
},
|
|
2054
|
-
{
|
|
2055
|
-
uri: "mindgraph://decisions",
|
|
2056
|
-
name: "Open Decisions",
|
|
2057
|
-
description: "Unresolved decisions awaiting resolution",
|
|
2058
|
-
mimeType: "application/json"
|
|
2059
|
-
}
|
|
2060
|
-
]
|
|
2061
|
-
};
|
|
2216
|
+
return { resources: RESOURCES };
|
|
2062
2217
|
});
|
|
2063
2218
|
server.setRequestHandler(import_types.ListResourceTemplatesRequestSchema, async () => {
|
|
2064
|
-
return {
|
|
2065
|
-
resourceTemplates: [
|
|
2066
|
-
{
|
|
2067
|
-
uriTemplate: "mindgraph://node/{uid}",
|
|
2068
|
-
name: "Graph Node",
|
|
2069
|
-
description: "Retrieve a specific node by its UID, including all properties, edges, and version history",
|
|
2070
|
-
mimeType: "application/json"
|
|
2071
|
-
},
|
|
2072
|
-
{
|
|
2073
|
-
uriTemplate: "mindgraph://search/{query}",
|
|
2074
|
-
name: "Search Results",
|
|
2075
|
-
description: "BM25 keyword search across all nodes \u2014 pass 1\u20133 discriminating terms (e.g. 'Kissinger NATO'), not natural language sentences",
|
|
2076
|
-
mimeType: "application/json"
|
|
2077
|
-
},
|
|
2078
|
-
{
|
|
2079
|
-
uriTemplate: "mindgraph://layer/{layer}",
|
|
2080
|
-
name: "Layer Nodes",
|
|
2081
|
-
description: "List all nodes in a specific cognitive layer (reality, epistemic, intent, action, memory, agent)",
|
|
2082
|
-
mimeType: "application/json"
|
|
2083
|
-
}
|
|
2084
|
-
]
|
|
2085
|
-
};
|
|
2219
|
+
return { resourceTemplates: RESOURCE_TEMPLATES };
|
|
2086
2220
|
});
|
|
2087
2221
|
server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
|
|
2088
|
-
|
|
2089
|
-
switch (uri) {
|
|
2090
|
-
case "mindgraph://stats": {
|
|
2091
|
-
const stats = await client.stats();
|
|
2092
|
-
return {
|
|
2093
|
-
contents: [
|
|
2094
|
-
{
|
|
2095
|
-
uri,
|
|
2096
|
-
mimeType: "application/json",
|
|
2097
|
-
text: JSON.stringify(stats, null, 2)
|
|
2098
|
-
}
|
|
2099
|
-
]
|
|
2100
|
-
};
|
|
2101
|
-
}
|
|
2102
|
-
case "mindgraph://goals": {
|
|
2103
|
-
const goals = await client.getGoals();
|
|
2104
|
-
return {
|
|
2105
|
-
contents: [
|
|
2106
|
-
{
|
|
2107
|
-
uri,
|
|
2108
|
-
mimeType: "application/json",
|
|
2109
|
-
text: JSON.stringify(goals, null, 2)
|
|
2110
|
-
}
|
|
2111
|
-
]
|
|
2112
|
-
};
|
|
2113
|
-
}
|
|
2114
|
-
case "mindgraph://questions": {
|
|
2115
|
-
const questions = await client.getOpenQuestions();
|
|
2116
|
-
return {
|
|
2117
|
-
contents: [
|
|
2118
|
-
{
|
|
2119
|
-
uri,
|
|
2120
|
-
mimeType: "application/json",
|
|
2121
|
-
text: JSON.stringify(questions, null, 2)
|
|
2122
|
-
}
|
|
2123
|
-
]
|
|
2124
|
-
};
|
|
2125
|
-
}
|
|
2126
|
-
case "mindgraph://contradictions": {
|
|
2127
|
-
const contradictions = await client.getContradictions();
|
|
2128
|
-
return {
|
|
2129
|
-
contents: [
|
|
2130
|
-
{
|
|
2131
|
-
uri,
|
|
2132
|
-
mimeType: "application/json",
|
|
2133
|
-
text: JSON.stringify(contradictions, null, 2)
|
|
2134
|
-
}
|
|
2135
|
-
]
|
|
2136
|
-
};
|
|
2137
|
-
}
|
|
2138
|
-
case "mindgraph://decisions": {
|
|
2139
|
-
const decisions = await client.getOpenDecisions();
|
|
2140
|
-
return {
|
|
2141
|
-
contents: [
|
|
2142
|
-
{
|
|
2143
|
-
uri,
|
|
2144
|
-
mimeType: "application/json",
|
|
2145
|
-
text: JSON.stringify(decisions, null, 2)
|
|
2146
|
-
}
|
|
2147
|
-
]
|
|
2148
|
-
};
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
const nodeMatch = uri.match(/^mindgraph:\/\/node\/(.+)$/);
|
|
2152
|
-
if (nodeMatch) {
|
|
2153
|
-
const uid = decodeURIComponent(nodeMatch[1]);
|
|
2154
|
-
const node = await client.getNode(uid);
|
|
2155
|
-
const edges = await client.getEdges({ from_uid: uid });
|
|
2156
|
-
const inEdges = await client.getEdges({ to_uid: uid });
|
|
2157
|
-
return {
|
|
2158
|
-
contents: [
|
|
2159
|
-
{
|
|
2160
|
-
uri,
|
|
2161
|
-
mimeType: "application/json",
|
|
2162
|
-
text: JSON.stringify(
|
|
2163
|
-
{ node, outgoing_edges: edges, incoming_edges: inEdges },
|
|
2164
|
-
null,
|
|
2165
|
-
2
|
|
2166
|
-
)
|
|
2167
|
-
}
|
|
2168
|
-
]
|
|
2169
|
-
};
|
|
2170
|
-
}
|
|
2171
|
-
const searchMatch = uri.match(/^mindgraph:\/\/search\/(.+)$/);
|
|
2172
|
-
if (searchMatch) {
|
|
2173
|
-
const query = decodeURIComponent(searchMatch[1]);
|
|
2174
|
-
const results = await client.search(query, { limit: 20 });
|
|
2175
|
-
return {
|
|
2176
|
-
contents: [
|
|
2177
|
-
{
|
|
2178
|
-
uri,
|
|
2179
|
-
mimeType: "application/json",
|
|
2180
|
-
text: JSON.stringify(results, null, 2)
|
|
2181
|
-
}
|
|
2182
|
-
]
|
|
2183
|
-
};
|
|
2184
|
-
}
|
|
2185
|
-
const layerMatch = uri.match(/^mindgraph:\/\/layer\/(.+)$/);
|
|
2186
|
-
if (layerMatch) {
|
|
2187
|
-
const layer = decodeURIComponent(layerMatch[1]);
|
|
2188
|
-
const nodes = await client.getNodes({ layer, limit: 50 });
|
|
2189
|
-
return {
|
|
2190
|
-
contents: [
|
|
2191
|
-
{
|
|
2192
|
-
uri,
|
|
2193
|
-
mimeType: "application/json",
|
|
2194
|
-
text: JSON.stringify(nodes, null, 2)
|
|
2195
|
-
}
|
|
2196
|
-
]
|
|
2197
|
-
};
|
|
2198
|
-
}
|
|
2199
|
-
throw new Error(`Unknown resource: ${uri}`);
|
|
2222
|
+
return readGovernedResource(client, request.params.uri, GOVERNANCE_CONFIG);
|
|
2200
2223
|
});
|
|
2201
2224
|
main().catch((error) => {
|
|
2202
2225
|
console.error("Fatal error:", error);
|
package/dist/index.js
CHANGED
|
@@ -1467,13 +1467,23 @@ var err2 = (message) => ({
|
|
|
1467
1467
|
isError: true
|
|
1468
1468
|
});
|
|
1469
1469
|
var CACHE_TTL_MS = 5 * 60 * 1e3;
|
|
1470
|
+
var FAILURE_COOLDOWN_MS = 15 * 1e3;
|
|
1470
1471
|
var cache = null;
|
|
1472
|
+
var retryNotBefore = 0;
|
|
1473
|
+
var EMPTY = {
|
|
1474
|
+
tools: [],
|
|
1475
|
+
byName: /* @__PURE__ */ new Map()
|
|
1476
|
+
};
|
|
1471
1477
|
var DuplicateGeneratedToolError = class extends Error {
|
|
1472
1478
|
};
|
|
1473
1479
|
async function getGeneratedTools(client2) {
|
|
1474
|
-
|
|
1480
|
+
const now = Date.now();
|
|
1481
|
+
if (cache && now - cache.fetchedAt < CACHE_TTL_MS) {
|
|
1475
1482
|
return { tools: cache.tools, byName: cache.byName };
|
|
1476
1483
|
}
|
|
1484
|
+
if (now < retryNotBefore) {
|
|
1485
|
+
return cache ? { tools: cache.tools, byName: cache.byName } : EMPTY;
|
|
1486
|
+
}
|
|
1477
1487
|
try {
|
|
1478
1488
|
const c = client2;
|
|
1479
1489
|
if (typeof c.listOntologyTools !== "function") {
|
|
@@ -1497,13 +1507,22 @@ async function getGeneratedTools(client2) {
|
|
|
1497
1507
|
});
|
|
1498
1508
|
}
|
|
1499
1509
|
cache = { tools, byName, fetchedAt: Date.now() };
|
|
1510
|
+
retryNotBefore = 0;
|
|
1500
1511
|
return { tools, byName };
|
|
1501
1512
|
} catch (error) {
|
|
1502
1513
|
if (error instanceof DuplicateGeneratedToolError) throw error;
|
|
1503
|
-
|
|
1504
|
-
return { tools: cache.tools, byName: cache.byName };
|
|
1514
|
+
retryNotBefore = Date.now() + FAILURE_COOLDOWN_MS;
|
|
1515
|
+
return cache ? { tools: cache.tools, byName: cache.byName } : EMPTY;
|
|
1505
1516
|
}
|
|
1506
1517
|
}
|
|
1518
|
+
var STRUCTURED_QUERY_PASSTHROUGH = [
|
|
1519
|
+
"anchor",
|
|
1520
|
+
"path",
|
|
1521
|
+
"where",
|
|
1522
|
+
"include",
|
|
1523
|
+
"page",
|
|
1524
|
+
"aggregate"
|
|
1525
|
+
];
|
|
1507
1526
|
async function handleGeneratedTool(client2, desc, args) {
|
|
1508
1527
|
try {
|
|
1509
1528
|
const ontologyClient = client2;
|
|
@@ -1571,11 +1590,14 @@ async function handleGeneratedTool(client2, desc, args) {
|
|
|
1571
1590
|
"structured ontology tools require a graph-aware version of the mindgraph SDK"
|
|
1572
1591
|
);
|
|
1573
1592
|
}
|
|
1574
|
-
|
|
1575
|
-
...args,
|
|
1593
|
+
const request = {
|
|
1576
1594
|
schema_id: desc.schema_id,
|
|
1577
1595
|
select
|
|
1578
|
-
}
|
|
1596
|
+
};
|
|
1597
|
+
for (const field of STRUCTURED_QUERY_PASSTHROUGH) {
|
|
1598
|
+
if (args[field] !== void 0) request[field] = args[field];
|
|
1599
|
+
}
|
|
1600
|
+
return ok2(await ontologyClient.queryDomainStructured(request));
|
|
1579
1601
|
}
|
|
1580
1602
|
default:
|
|
1581
1603
|
return err2(`unknown generated tool mapping: ${desc.maps_to}`);
|
|
@@ -1587,6 +1609,16 @@ async function handleGeneratedTool(client2, desc, args) {
|
|
|
1587
1609
|
|
|
1588
1610
|
// src/governance.ts
|
|
1589
1611
|
var capability = "unknown";
|
|
1612
|
+
var UNSUPPORTED_LEASE_MS = 5 * 60 * 1e3;
|
|
1613
|
+
var unsupportedUntil = 0;
|
|
1614
|
+
var unsupportedLogged = false;
|
|
1615
|
+
var DEFAULT_RETRY_DELAYS_MS = [150, 600];
|
|
1616
|
+
function isTransientStatus(status) {
|
|
1617
|
+
return status === 408 || status === 425 || status === 429 || status >= 500;
|
|
1618
|
+
}
|
|
1619
|
+
function sleep(ms) {
|
|
1620
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1621
|
+
}
|
|
1590
1622
|
var KNOWN_DUTIES = /* @__PURE__ */ new Set(["log", "require_approval"]);
|
|
1591
1623
|
function headers(apiKey, orgId) {
|
|
1592
1624
|
const value = {
|
|
@@ -1603,41 +1635,81 @@ function unsupportedResponse(status, body) {
|
|
|
1603
1635
|
return lower.includes("unknown governance action") || lower.includes("unknown action") || lower.includes("invalid_governance_action");
|
|
1604
1636
|
}
|
|
1605
1637
|
async function checkMcpGovernance(toolName, args, config) {
|
|
1606
|
-
if (config.disabled
|
|
1638
|
+
if (config.disabled) return { allowed: true };
|
|
1639
|
+
if (capability === "unsupported") {
|
|
1640
|
+
if (Date.now() < unsupportedUntil) return { allowed: true };
|
|
1641
|
+
capability = "unknown";
|
|
1642
|
+
}
|
|
1607
1643
|
const fetchImpl = config.fetchImpl ?? fetch;
|
|
1644
|
+
const retryDelays = config.retryDelaysMs ?? DEFAULT_RETRY_DELAYS_MS;
|
|
1608
1645
|
let response;
|
|
1609
|
-
let body;
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1646
|
+
let body = "";
|
|
1647
|
+
let lastFailure = "";
|
|
1648
|
+
for (let attempt = 0; attempt <= retryDelays.length; attempt++) {
|
|
1649
|
+
try {
|
|
1650
|
+
const candidate = await fetchImpl(
|
|
1651
|
+
`${config.baseUrl.replace(/\/$/, "")}/agent/governance`,
|
|
1652
|
+
{
|
|
1653
|
+
method: "POST",
|
|
1654
|
+
headers: headers(config.apiKey, config.orgId),
|
|
1655
|
+
body: JSON.stringify({
|
|
1656
|
+
action: "check",
|
|
1657
|
+
act: "tool_invoke",
|
|
1658
|
+
agent_id: String(args.agent_id || config.agentId),
|
|
1659
|
+
target: { tool_name: toolName },
|
|
1660
|
+
context: { adapter: "mindgraph-mcp", ...config.context },
|
|
1661
|
+
tier: "checkpoint"
|
|
1662
|
+
})
|
|
1663
|
+
}
|
|
1664
|
+
);
|
|
1665
|
+
const candidateBody = await candidate.text();
|
|
1666
|
+
if (isTransientStatus(candidate.status) && attempt < retryDelays.length) {
|
|
1667
|
+
lastFailure = `HTTP ${candidate.status}`;
|
|
1668
|
+
await sleep(retryDelays[attempt]);
|
|
1669
|
+
continue;
|
|
1670
|
+
}
|
|
1671
|
+
response = candidate;
|
|
1672
|
+
body = candidateBody;
|
|
1673
|
+
break;
|
|
1674
|
+
} catch (error) {
|
|
1675
|
+
lastFailure = error instanceof Error ? error.message : String(error);
|
|
1676
|
+
if (attempt < retryDelays.length) {
|
|
1677
|
+
await sleep(retryDelays[attempt]);
|
|
1678
|
+
continue;
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
if (!response) {
|
|
1625
1683
|
return {
|
|
1626
1684
|
allowed: false,
|
|
1627
|
-
message: `MindGraph governance could not establish permission
|
|
1685
|
+
message: `MindGraph governance could not establish permission after ${retryDelays.length + 1} attempts (${lastFailure}). Set MINDGRAPH_GOVERNANCE=off to run this adapter ungoverned.`
|
|
1628
1686
|
};
|
|
1629
1687
|
}
|
|
1630
1688
|
if (!response.ok) {
|
|
1631
1689
|
if (capability === "unknown" && unsupportedResponse(response.status, body)) {
|
|
1632
1690
|
capability = "unsupported";
|
|
1691
|
+
unsupportedUntil = Date.now() + UNSUPPORTED_LEASE_MS;
|
|
1692
|
+
if (!unsupportedLogged) {
|
|
1693
|
+
unsupportedLogged = true;
|
|
1694
|
+
console.error(
|
|
1695
|
+
`[mindgraph-mcp] This MindGraph server does not implement the governance checkpoint (HTTP ${response.status}); tool calls proceed ungoverned. Re-probing every ${Math.round(UNSUPPORTED_LEASE_MS / 6e4)} minutes.`
|
|
1696
|
+
);
|
|
1697
|
+
}
|
|
1633
1698
|
return { allowed: true };
|
|
1634
1699
|
}
|
|
1700
|
+
if (response.status === 401 || response.status === 403) {
|
|
1701
|
+
return {
|
|
1702
|
+
allowed: false,
|
|
1703
|
+
message: `This credential is not permitted to evaluate MindGraph governance (HTTP ${response.status}). Use a user-scoped API key, or set MINDGRAPH_GOVERNANCE=off to run this adapter ungoverned.`
|
|
1704
|
+
};
|
|
1705
|
+
}
|
|
1635
1706
|
return {
|
|
1636
1707
|
allowed: false,
|
|
1637
1708
|
message: `MindGraph governance check failed (${response.status})`
|
|
1638
1709
|
};
|
|
1639
1710
|
}
|
|
1640
1711
|
capability = "supported";
|
|
1712
|
+
unsupportedLogged = false;
|
|
1641
1713
|
let decision;
|
|
1642
1714
|
try {
|
|
1643
1715
|
decision = JSON.parse(body);
|
|
@@ -1672,6 +1744,110 @@ async function checkMcpGovernance(toolName, args, config) {
|
|
|
1672
1744
|
};
|
|
1673
1745
|
}
|
|
1674
1746
|
|
|
1747
|
+
// src/resources.ts
|
|
1748
|
+
var RESOURCES = [
|
|
1749
|
+
{
|
|
1750
|
+
uri: "mindgraph://stats",
|
|
1751
|
+
name: "Graph Statistics",
|
|
1752
|
+
description: "Current knowledge graph statistics: node counts, edge counts, and layer distribution",
|
|
1753
|
+
mimeType: "application/json"
|
|
1754
|
+
},
|
|
1755
|
+
{
|
|
1756
|
+
uri: "mindgraph://goals",
|
|
1757
|
+
name: "Active Goals",
|
|
1758
|
+
description: "All active goals in the knowledge graph",
|
|
1759
|
+
mimeType: "application/json"
|
|
1760
|
+
},
|
|
1761
|
+
{
|
|
1762
|
+
uri: "mindgraph://questions",
|
|
1763
|
+
name: "Open Questions",
|
|
1764
|
+
description: "All open questions in the knowledge graph",
|
|
1765
|
+
mimeType: "application/json"
|
|
1766
|
+
},
|
|
1767
|
+
{
|
|
1768
|
+
uri: "mindgraph://contradictions",
|
|
1769
|
+
name: "Contradictions",
|
|
1770
|
+
description: "Contradictory claims in the knowledge graph",
|
|
1771
|
+
mimeType: "application/json"
|
|
1772
|
+
},
|
|
1773
|
+
{
|
|
1774
|
+
uri: "mindgraph://decisions",
|
|
1775
|
+
name: "Open Decisions",
|
|
1776
|
+
description: "Unresolved decisions awaiting resolution",
|
|
1777
|
+
mimeType: "application/json"
|
|
1778
|
+
}
|
|
1779
|
+
];
|
|
1780
|
+
var RESOURCE_TEMPLATES = [
|
|
1781
|
+
{
|
|
1782
|
+
uriTemplate: "mindgraph://node/{uid}",
|
|
1783
|
+
name: "Graph Node",
|
|
1784
|
+
description: "Retrieve a specific node by its UID, including all properties, edges, and version history",
|
|
1785
|
+
mimeType: "application/json"
|
|
1786
|
+
},
|
|
1787
|
+
{
|
|
1788
|
+
uriTemplate: "mindgraph://search/{query}",
|
|
1789
|
+
name: "Search Results",
|
|
1790
|
+
description: "BM25 keyword search across all nodes \u2014 pass 1\u20133 discriminating terms (e.g. 'Kissinger NATO'), not natural language sentences",
|
|
1791
|
+
mimeType: "application/json"
|
|
1792
|
+
},
|
|
1793
|
+
{
|
|
1794
|
+
uriTemplate: "mindgraph://layer/{layer}",
|
|
1795
|
+
name: "Layer Nodes",
|
|
1796
|
+
description: "List all nodes in a specific cognitive layer (reality, epistemic, intent, action, memory, agent)",
|
|
1797
|
+
mimeType: "application/json"
|
|
1798
|
+
}
|
|
1799
|
+
];
|
|
1800
|
+
var RESOURCE_GOVERNANCE_TOOL = "mindgraph_retrieve";
|
|
1801
|
+
function json(uri, data) {
|
|
1802
|
+
return {
|
|
1803
|
+
contents: [{ uri, mimeType: "application/json", text: JSON.stringify(data, null, 2) }]
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
async function readResource(client2, uri) {
|
|
1807
|
+
switch (uri) {
|
|
1808
|
+
case "mindgraph://stats":
|
|
1809
|
+
return json(uri, await client2.stats());
|
|
1810
|
+
case "mindgraph://goals":
|
|
1811
|
+
return json(uri, await client2.getGoals());
|
|
1812
|
+
case "mindgraph://questions":
|
|
1813
|
+
return json(uri, await client2.getOpenQuestions());
|
|
1814
|
+
case "mindgraph://contradictions":
|
|
1815
|
+
return json(uri, await client2.getContradictions());
|
|
1816
|
+
case "mindgraph://decisions":
|
|
1817
|
+
return json(uri, await client2.getOpenDecisions());
|
|
1818
|
+
}
|
|
1819
|
+
const nodeMatch = uri.match(/^mindgraph:\/\/node\/(.+)$/);
|
|
1820
|
+
if (nodeMatch) {
|
|
1821
|
+
const uid = decodeURIComponent(nodeMatch[1]);
|
|
1822
|
+
const node = await client2.getNode(uid);
|
|
1823
|
+
const edges = await client2.getEdges({ from_uid: uid });
|
|
1824
|
+
const inEdges = await client2.getEdges({ to_uid: uid });
|
|
1825
|
+
return json(uri, { node, outgoing_edges: edges, incoming_edges: inEdges });
|
|
1826
|
+
}
|
|
1827
|
+
const searchMatch = uri.match(/^mindgraph:\/\/search\/(.+)$/);
|
|
1828
|
+
if (searchMatch) {
|
|
1829
|
+
const query = decodeURIComponent(searchMatch[1]);
|
|
1830
|
+
return json(uri, await client2.search(query, { limit: 20 }));
|
|
1831
|
+
}
|
|
1832
|
+
const layerMatch = uri.match(/^mindgraph:\/\/layer\/(.+)$/);
|
|
1833
|
+
if (layerMatch) {
|
|
1834
|
+
const layer = decodeURIComponent(layerMatch[1]);
|
|
1835
|
+
return json(uri, await client2.getNodes({ layer, limit: 50 }));
|
|
1836
|
+
}
|
|
1837
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
1838
|
+
}
|
|
1839
|
+
async function readGovernedResource(client2, uri, governanceConfig) {
|
|
1840
|
+
const governance = await checkMcpGovernance(
|
|
1841
|
+
RESOURCE_GOVERNANCE_TOOL,
|
|
1842
|
+
{},
|
|
1843
|
+
{ ...governanceConfig, context: { resource_uri: uri } }
|
|
1844
|
+
);
|
|
1845
|
+
if (!governance.allowed) {
|
|
1846
|
+
throw new Error(governance.message);
|
|
1847
|
+
}
|
|
1848
|
+
return readResource(client2, uri);
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1675
1851
|
// src/index.ts
|
|
1676
1852
|
var API_KEY = process.env.MINDGRAPH_API_KEY;
|
|
1677
1853
|
var BASE_URL = process.env.MINDGRAPH_BASE_URL || "https://api.mindgraph.cloud";
|
|
@@ -1770,7 +1946,7 @@ Capture knowledge when the user shares something worth remembering:
|
|
|
1770
1946
|
var server = new import_server.Server(
|
|
1771
1947
|
{
|
|
1772
1948
|
name: "mindgraph",
|
|
1773
|
-
version: "0.13.
|
|
1949
|
+
version: "0.13.5"
|
|
1774
1950
|
},
|
|
1775
1951
|
{
|
|
1776
1952
|
capabilities: {
|
|
@@ -1785,19 +1961,23 @@ server.setRequestHandler(import_types.ListToolsRequestSchema, async () => {
|
|
|
1785
1961
|
const generated = await getGeneratedTools(client);
|
|
1786
1962
|
return { tools: [...TOOLS, ...generated.tools] };
|
|
1787
1963
|
});
|
|
1964
|
+
var GOVERNANCE_CONFIG = {
|
|
1965
|
+
baseUrl: BASE_URL,
|
|
1966
|
+
apiKey: API_KEY,
|
|
1967
|
+
orgId: ORG_ID,
|
|
1968
|
+
agentId: AGENT_ID,
|
|
1969
|
+
get disabled() {
|
|
1970
|
+
return process.env.MINDGRAPH_GOVERNANCE === "off";
|
|
1971
|
+
}
|
|
1972
|
+
};
|
|
1788
1973
|
server.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
|
|
1789
1974
|
const { name, arguments: args } = request.params;
|
|
1790
|
-
const
|
|
1975
|
+
const rawArgs = { ...args || {} };
|
|
1976
|
+
const toolArgs = { ...rawArgs };
|
|
1791
1977
|
if (!toolArgs.agent_id) {
|
|
1792
1978
|
toolArgs.agent_id = AGENT_ID;
|
|
1793
1979
|
}
|
|
1794
|
-
const governance = await checkMcpGovernance(name, toolArgs,
|
|
1795
|
-
baseUrl: BASE_URL,
|
|
1796
|
-
apiKey: API_KEY,
|
|
1797
|
-
orgId: ORG_ID,
|
|
1798
|
-
agentId: AGENT_ID,
|
|
1799
|
-
disabled: process.env.MINDGRAPH_GOVERNANCE === "off"
|
|
1800
|
-
});
|
|
1980
|
+
const governance = await checkMcpGovernance(name, toolArgs, GOVERNANCE_CONFIG);
|
|
1801
1981
|
if (!governance.allowed) {
|
|
1802
1982
|
return {
|
|
1803
1983
|
content: [{ type: "text", text: JSON.stringify({ error: governance.message, ...governance }) }],
|
|
@@ -1807,7 +1987,7 @@ server.setRequestHandler(import_types.CallToolRequestSchema, async (request) =>
|
|
|
1807
1987
|
const generated = await getGeneratedTools(client);
|
|
1808
1988
|
const desc = generated.byName.get(name);
|
|
1809
1989
|
if (desc) {
|
|
1810
|
-
return handleGeneratedTool(client, desc,
|
|
1990
|
+
return handleGeneratedTool(client, desc, rawArgs);
|
|
1811
1991
|
}
|
|
1812
1992
|
return handleTool(client, name, toolArgs);
|
|
1813
1993
|
});
|
|
@@ -1968,178 +2148,13 @@ ${conversation}`
|
|
|
1968
2148
|
}
|
|
1969
2149
|
});
|
|
1970
2150
|
server.setRequestHandler(import_types.ListResourcesRequestSchema, async () => {
|
|
1971
|
-
return {
|
|
1972
|
-
resources: [
|
|
1973
|
-
{
|
|
1974
|
-
uri: "mindgraph://stats",
|
|
1975
|
-
name: "Graph Statistics",
|
|
1976
|
-
description: "Current knowledge graph statistics: node counts, edge counts, and layer distribution",
|
|
1977
|
-
mimeType: "application/json"
|
|
1978
|
-
},
|
|
1979
|
-
{
|
|
1980
|
-
uri: "mindgraph://goals",
|
|
1981
|
-
name: "Active Goals",
|
|
1982
|
-
description: "All active goals in the knowledge graph",
|
|
1983
|
-
mimeType: "application/json"
|
|
1984
|
-
},
|
|
1985
|
-
{
|
|
1986
|
-
uri: "mindgraph://questions",
|
|
1987
|
-
name: "Open Questions",
|
|
1988
|
-
description: "All open questions in the knowledge graph",
|
|
1989
|
-
mimeType: "application/json"
|
|
1990
|
-
},
|
|
1991
|
-
{
|
|
1992
|
-
uri: "mindgraph://contradictions",
|
|
1993
|
-
name: "Contradictions",
|
|
1994
|
-
description: "Contradictory claims in the knowledge graph",
|
|
1995
|
-
mimeType: "application/json"
|
|
1996
|
-
},
|
|
1997
|
-
{
|
|
1998
|
-
uri: "mindgraph://decisions",
|
|
1999
|
-
name: "Open Decisions",
|
|
2000
|
-
description: "Unresolved decisions awaiting resolution",
|
|
2001
|
-
mimeType: "application/json"
|
|
2002
|
-
}
|
|
2003
|
-
]
|
|
2004
|
-
};
|
|
2151
|
+
return { resources: RESOURCES };
|
|
2005
2152
|
});
|
|
2006
2153
|
server.setRequestHandler(import_types.ListResourceTemplatesRequestSchema, async () => {
|
|
2007
|
-
return {
|
|
2008
|
-
resourceTemplates: [
|
|
2009
|
-
{
|
|
2010
|
-
uriTemplate: "mindgraph://node/{uid}",
|
|
2011
|
-
name: "Graph Node",
|
|
2012
|
-
description: "Retrieve a specific node by its UID, including all properties, edges, and version history",
|
|
2013
|
-
mimeType: "application/json"
|
|
2014
|
-
},
|
|
2015
|
-
{
|
|
2016
|
-
uriTemplate: "mindgraph://search/{query}",
|
|
2017
|
-
name: "Search Results",
|
|
2018
|
-
description: "BM25 keyword search across all nodes \u2014 pass 1\u20133 discriminating terms (e.g. 'Kissinger NATO'), not natural language sentences",
|
|
2019
|
-
mimeType: "application/json"
|
|
2020
|
-
},
|
|
2021
|
-
{
|
|
2022
|
-
uriTemplate: "mindgraph://layer/{layer}",
|
|
2023
|
-
name: "Layer Nodes",
|
|
2024
|
-
description: "List all nodes in a specific cognitive layer (reality, epistemic, intent, action, memory, agent)",
|
|
2025
|
-
mimeType: "application/json"
|
|
2026
|
-
}
|
|
2027
|
-
]
|
|
2028
|
-
};
|
|
2154
|
+
return { resourceTemplates: RESOURCE_TEMPLATES };
|
|
2029
2155
|
});
|
|
2030
2156
|
server.setRequestHandler(import_types.ReadResourceRequestSchema, async (request) => {
|
|
2031
|
-
|
|
2032
|
-
switch (uri) {
|
|
2033
|
-
case "mindgraph://stats": {
|
|
2034
|
-
const stats = await client.stats();
|
|
2035
|
-
return {
|
|
2036
|
-
contents: [
|
|
2037
|
-
{
|
|
2038
|
-
uri,
|
|
2039
|
-
mimeType: "application/json",
|
|
2040
|
-
text: JSON.stringify(stats, null, 2)
|
|
2041
|
-
}
|
|
2042
|
-
]
|
|
2043
|
-
};
|
|
2044
|
-
}
|
|
2045
|
-
case "mindgraph://goals": {
|
|
2046
|
-
const goals = await client.getGoals();
|
|
2047
|
-
return {
|
|
2048
|
-
contents: [
|
|
2049
|
-
{
|
|
2050
|
-
uri,
|
|
2051
|
-
mimeType: "application/json",
|
|
2052
|
-
text: JSON.stringify(goals, null, 2)
|
|
2053
|
-
}
|
|
2054
|
-
]
|
|
2055
|
-
};
|
|
2056
|
-
}
|
|
2057
|
-
case "mindgraph://questions": {
|
|
2058
|
-
const questions = await client.getOpenQuestions();
|
|
2059
|
-
return {
|
|
2060
|
-
contents: [
|
|
2061
|
-
{
|
|
2062
|
-
uri,
|
|
2063
|
-
mimeType: "application/json",
|
|
2064
|
-
text: JSON.stringify(questions, null, 2)
|
|
2065
|
-
}
|
|
2066
|
-
]
|
|
2067
|
-
};
|
|
2068
|
-
}
|
|
2069
|
-
case "mindgraph://contradictions": {
|
|
2070
|
-
const contradictions = await client.getContradictions();
|
|
2071
|
-
return {
|
|
2072
|
-
contents: [
|
|
2073
|
-
{
|
|
2074
|
-
uri,
|
|
2075
|
-
mimeType: "application/json",
|
|
2076
|
-
text: JSON.stringify(contradictions, null, 2)
|
|
2077
|
-
}
|
|
2078
|
-
]
|
|
2079
|
-
};
|
|
2080
|
-
}
|
|
2081
|
-
case "mindgraph://decisions": {
|
|
2082
|
-
const decisions = await client.getOpenDecisions();
|
|
2083
|
-
return {
|
|
2084
|
-
contents: [
|
|
2085
|
-
{
|
|
2086
|
-
uri,
|
|
2087
|
-
mimeType: "application/json",
|
|
2088
|
-
text: JSON.stringify(decisions, null, 2)
|
|
2089
|
-
}
|
|
2090
|
-
]
|
|
2091
|
-
};
|
|
2092
|
-
}
|
|
2093
|
-
}
|
|
2094
|
-
const nodeMatch = uri.match(/^mindgraph:\/\/node\/(.+)$/);
|
|
2095
|
-
if (nodeMatch) {
|
|
2096
|
-
const uid = decodeURIComponent(nodeMatch[1]);
|
|
2097
|
-
const node = await client.getNode(uid);
|
|
2098
|
-
const edges = await client.getEdges({ from_uid: uid });
|
|
2099
|
-
const inEdges = await client.getEdges({ to_uid: uid });
|
|
2100
|
-
return {
|
|
2101
|
-
contents: [
|
|
2102
|
-
{
|
|
2103
|
-
uri,
|
|
2104
|
-
mimeType: "application/json",
|
|
2105
|
-
text: JSON.stringify(
|
|
2106
|
-
{ node, outgoing_edges: edges, incoming_edges: inEdges },
|
|
2107
|
-
null,
|
|
2108
|
-
2
|
|
2109
|
-
)
|
|
2110
|
-
}
|
|
2111
|
-
]
|
|
2112
|
-
};
|
|
2113
|
-
}
|
|
2114
|
-
const searchMatch = uri.match(/^mindgraph:\/\/search\/(.+)$/);
|
|
2115
|
-
if (searchMatch) {
|
|
2116
|
-
const query = decodeURIComponent(searchMatch[1]);
|
|
2117
|
-
const results = await client.search(query, { limit: 20 });
|
|
2118
|
-
return {
|
|
2119
|
-
contents: [
|
|
2120
|
-
{
|
|
2121
|
-
uri,
|
|
2122
|
-
mimeType: "application/json",
|
|
2123
|
-
text: JSON.stringify(results, null, 2)
|
|
2124
|
-
}
|
|
2125
|
-
]
|
|
2126
|
-
};
|
|
2127
|
-
}
|
|
2128
|
-
const layerMatch = uri.match(/^mindgraph:\/\/layer\/(.+)$/);
|
|
2129
|
-
if (layerMatch) {
|
|
2130
|
-
const layer = decodeURIComponent(layerMatch[1]);
|
|
2131
|
-
const nodes = await client.getNodes({ layer, limit: 50 });
|
|
2132
|
-
return {
|
|
2133
|
-
contents: [
|
|
2134
|
-
{
|
|
2135
|
-
uri,
|
|
2136
|
-
mimeType: "application/json",
|
|
2137
|
-
text: JSON.stringify(nodes, null, 2)
|
|
2138
|
-
}
|
|
2139
|
-
]
|
|
2140
|
-
};
|
|
2141
|
-
}
|
|
2142
|
-
throw new Error(`Unknown resource: ${uri}`);
|
|
2157
|
+
return readGovernedResource(client, request.params.uri, GOVERNANCE_CONFIG);
|
|
2143
2158
|
});
|
|
2144
2159
|
async function main() {
|
|
2145
2160
|
const transport = new import_stdio.StdioServerTransport();
|