mindgraph-mcp 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/cli.js +307 -79
- package/dist/index.js +302 -75
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -777,13 +777,13 @@ function codeRefIdentityKey(ref) {
|
|
|
777
777
|
|
|
778
778
|
// src/code-tool.ts
|
|
779
779
|
var ok = (data) => ({
|
|
780
|
-
content: [{ type: "text", text: JSON.stringify(data
|
|
780
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
781
781
|
});
|
|
782
782
|
var err = (code, message, details) => ({
|
|
783
783
|
content: [
|
|
784
784
|
{
|
|
785
785
|
type: "text",
|
|
786
|
-
text: JSON.stringify({ error: message, code, details }
|
|
786
|
+
text: JSON.stringify({ error: message, code, details })
|
|
787
787
|
}
|
|
788
788
|
],
|
|
789
789
|
isError: true
|
|
@@ -1272,7 +1272,7 @@ var import_node_crypto3 = __toESM(require("crypto"));
|
|
|
1272
1272
|
var import_node_fs3 = __toESM(require("fs"));
|
|
1273
1273
|
var import_node_path3 = __toESM(require("path"));
|
|
1274
1274
|
var ok2 = (data) => ({
|
|
1275
|
-
content: [{ type: "text", text: JSON.stringify(data
|
|
1275
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
1276
1276
|
});
|
|
1277
1277
|
var err2 = (code, message) => ({
|
|
1278
1278
|
content: [{ type: "text", text: JSON.stringify({ code, error: message }) }],
|
|
@@ -1502,12 +1502,23 @@ function clip(value, max, state) {
|
|
|
1502
1502
|
}
|
|
1503
1503
|
function isNodeShaped(value) {
|
|
1504
1504
|
const node = obj(value);
|
|
1505
|
-
return Boolean(
|
|
1505
|
+
return Boolean(
|
|
1506
|
+
node && str(node.uid) && (str(node.label) || str(node.node_type) || obj(node.node_type))
|
|
1507
|
+
);
|
|
1508
|
+
}
|
|
1509
|
+
function nodeDisplayType(node) {
|
|
1510
|
+
const props = obj(node.props);
|
|
1511
|
+
const plain = str(node.node_type);
|
|
1512
|
+
return (plain && plain !== "Custom" ? plain : void 0) ?? str(obj(node.node_type)?.Custom) ?? str(props?.object_type) ?? str(props?.type_name) ?? str(obj(props?.data)?.domain_type) ?? plain ?? "Node";
|
|
1513
|
+
}
|
|
1514
|
+
function nodeFields(node) {
|
|
1515
|
+
const props = obj(node.props);
|
|
1516
|
+
return obj(props?.fields) ?? obj(obj(props?.data)?.fields);
|
|
1506
1517
|
}
|
|
1507
1518
|
function unwrapSearchResult(value) {
|
|
1508
1519
|
if (isNodeShaped(value)) return value;
|
|
1509
1520
|
const wrapper = obj(value);
|
|
1510
|
-
const inner = obj(wrapper?.node);
|
|
1521
|
+
const inner = obj(wrapper?.node) ?? obj(wrapper?.object);
|
|
1511
1522
|
if (inner && isNodeShaped(inner)) {
|
|
1512
1523
|
const score = num(wrapper.score);
|
|
1513
1524
|
return score !== void 0 ? { ...inner, retrieval_score: score } : inner;
|
|
@@ -1545,7 +1556,7 @@ function sourceTag(node) {
|
|
|
1545
1556
|
return `from: ${title}${extra}`;
|
|
1546
1557
|
}
|
|
1547
1558
|
function layer7Fields(node, state) {
|
|
1548
|
-
const fields =
|
|
1559
|
+
const fields = nodeFields(node);
|
|
1549
1560
|
if (!fields) return void 0;
|
|
1550
1561
|
const pairs = Object.entries(fields).filter(([, value]) => value !== null && value !== void 0 && value !== "").map(([key, value]) => `${key}: ${Array.isArray(value) ? value.join(", ") : String(value)}`);
|
|
1551
1562
|
if (pairs.length === 0) return void 0;
|
|
@@ -1557,7 +1568,7 @@ function nodeSummaryText(node, state) {
|
|
|
1557
1568
|
}
|
|
1558
1569
|
function nodeLines(node, state) {
|
|
1559
1570
|
const label = clip(node.label, LABEL_MAX, state) || "(unlabeled)";
|
|
1560
|
-
const type =
|
|
1571
|
+
const type = nodeDisplayType(node);
|
|
1561
1572
|
const confidence = num(node.confidence);
|
|
1562
1573
|
const score = num(node.retrieval_score);
|
|
1563
1574
|
const parenthetical = [
|
|
@@ -1576,19 +1587,19 @@ function nodeLines(node, state) {
|
|
|
1576
1587
|
if (source) lines.push(` - ${source}`);
|
|
1577
1588
|
const believers = Array.isArray(node.believed_by) ? node.believed_by : [];
|
|
1578
1589
|
if (believers.length > 0) {
|
|
1579
|
-
const
|
|
1590
|
+
const rendered2 = believers.slice(0, 3).map((raw) => {
|
|
1580
1591
|
const believer = obj(raw);
|
|
1581
1592
|
const conf = num(believer?.confidence);
|
|
1582
1593
|
return `${str(believer?.agent_label) || "?"}${conf !== void 0 ? ` (${conf})` : ""}`;
|
|
1583
1594
|
}).join(", ");
|
|
1584
|
-
lines.push(` - believed by: ${
|
|
1595
|
+
lines.push(` - believed by: ${rendered2}`);
|
|
1585
1596
|
}
|
|
1586
1597
|
return lines.join("\n");
|
|
1587
1598
|
}
|
|
1588
1599
|
function groupedNodeSections(nodes, state, headingPrefix = "") {
|
|
1589
1600
|
const groups = /* @__PURE__ */ new Map();
|
|
1590
1601
|
for (const node of nodes) {
|
|
1591
|
-
const type =
|
|
1602
|
+
const type = nodeDisplayType(node);
|
|
1592
1603
|
const group = groups.get(type) ?? [];
|
|
1593
1604
|
group.push(node);
|
|
1594
1605
|
groups.set(type, group);
|
|
@@ -1604,7 +1615,7 @@ function groupedNodeSections(nodes, state, headingPrefix = "") {
|
|
|
1604
1615
|
}
|
|
1605
1616
|
return sections;
|
|
1606
1617
|
}
|
|
1607
|
-
function relationshipItems(edges, labelByUid, state) {
|
|
1618
|
+
function relationshipItems(edges, labelByUid, state, options) {
|
|
1608
1619
|
const lines = [];
|
|
1609
1620
|
for (const raw of edges) {
|
|
1610
1621
|
const edge = obj(raw);
|
|
@@ -1614,8 +1625,8 @@ function relationshipItems(edges, labelByUid, state) {
|
|
|
1614
1625
|
const to = str(edge.to_uid);
|
|
1615
1626
|
if (CURATION_EDGE_TYPES.has(type)) continue;
|
|
1616
1627
|
if (!from || !to || from === to) continue;
|
|
1617
|
-
const fromLabel = labelByUid.get(from);
|
|
1618
|
-
const toLabel = labelByUid.get(to);
|
|
1628
|
+
const fromLabel = labelByUid.get(from) ?? (options?.fallbackToUid ? `[${from}]` : void 0);
|
|
1629
|
+
const toLabel = labelByUid.get(to) ?? (options?.fallbackToUid ? `[${to}]` : void 0);
|
|
1619
1630
|
if (!fromLabel || !toLabel) continue;
|
|
1620
1631
|
lines.push(`- ${fromLabel} \u2014${type}\u2192 ${toLabel}`);
|
|
1621
1632
|
}
|
|
@@ -1658,8 +1669,8 @@ function assemble(header, sections, state) {
|
|
|
1658
1669
|
sectionUsed += marker.length + 1;
|
|
1659
1670
|
}
|
|
1660
1671
|
lines.push(
|
|
1661
|
-
section.items.length === 0 ? section.heading : `${section.heading}
|
|
1662
|
-
${kept.join("\n")}`
|
|
1672
|
+
section.items.length === 0 ? section.heading : section.heading ? `${section.heading}
|
|
1673
|
+
${kept.join("\n")}` : kept.join("\n")
|
|
1663
1674
|
);
|
|
1664
1675
|
used += headingCost + sectionUsed;
|
|
1665
1676
|
}
|
|
@@ -1822,6 +1833,157 @@ function renderTraversal(response) {
|
|
|
1822
1833
|
}
|
|
1823
1834
|
return assemble("# Graph traversal", sections, state);
|
|
1824
1835
|
}
|
|
1836
|
+
function neighborLine(value) {
|
|
1837
|
+
const node = obj(value);
|
|
1838
|
+
if (!node) return void 0;
|
|
1839
|
+
const label = str(node.label) || "(unlabeled)";
|
|
1840
|
+
const uid = str(node.uid);
|
|
1841
|
+
const type = str(node.node_type);
|
|
1842
|
+
return `- ${label}${uid ? ` [${uid}]` : ""}${type ? ` (${type})` : ""}`;
|
|
1843
|
+
}
|
|
1844
|
+
function renderOntologyAnswer(response) {
|
|
1845
|
+
const payload = obj(response);
|
|
1846
|
+
if (!payload) return void 0;
|
|
1847
|
+
const objects = Array.isArray(payload.objects) ? payload.objects.filter(isNodeShaped) : isNodeShaped(payload.object) ? [payload.object] : [];
|
|
1848
|
+
const cognitive = obj(payload.cognitive_context);
|
|
1849
|
+
const provenance = Array.isArray(payload.provenance) ? payload.provenance : [];
|
|
1850
|
+
const hasQuerySignature = Array.isArray(payload.objects) || obj(payload.confidence) !== void 0;
|
|
1851
|
+
const cognitiveEmpty = !cognitive || Object.values(cognitive).every((v) => !Array.isArray(v) || v.length === 0);
|
|
1852
|
+
if (objects.length === 0 && cognitiveEmpty && provenance.length === 0) {
|
|
1853
|
+
return hasQuerySignature ? "No matching domain objects." : void 0;
|
|
1854
|
+
}
|
|
1855
|
+
const state = { bounded: false };
|
|
1856
|
+
const sections = [];
|
|
1857
|
+
if (objects.length > 0) {
|
|
1858
|
+
sections.push(...groupedNodeSections(objects, state));
|
|
1859
|
+
}
|
|
1860
|
+
const labelByUid = /* @__PURE__ */ new Map();
|
|
1861
|
+
for (const node of objects) labelByUid.set(str(node.uid), str(node.label) || "?");
|
|
1862
|
+
const graph = obj(payload.graph);
|
|
1863
|
+
for (const raw of Array.isArray(graph?.nodes) ? graph.nodes : []) {
|
|
1864
|
+
const node = obj(raw);
|
|
1865
|
+
const uid = str(node?.uid);
|
|
1866
|
+
if (uid && !labelByUid.has(uid)) labelByUid.set(uid, str(node?.label) || "?");
|
|
1867
|
+
}
|
|
1868
|
+
if (cognitive) {
|
|
1869
|
+
for (const rawNodes of Object.values(cognitive)) {
|
|
1870
|
+
if (!Array.isArray(rawNodes)) continue;
|
|
1871
|
+
for (const raw of rawNodes) {
|
|
1872
|
+
const node = obj(raw);
|
|
1873
|
+
const uid = str(node?.uid);
|
|
1874
|
+
if (uid && !labelByUid.has(uid)) labelByUid.set(uid, str(node?.label) || "?");
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
const relations = Array.isArray(payload.relations) ? payload.relations : [];
|
|
1879
|
+
const relationLines = relationshipItems(relations, labelByUid, state, { fallbackToUid: true });
|
|
1880
|
+
if (relationLines.length > 0) {
|
|
1881
|
+
sections.push({ heading: "## Relations", items: relationLines });
|
|
1882
|
+
}
|
|
1883
|
+
if (cognitive) {
|
|
1884
|
+
for (const [category, rawNodes] of Object.entries(cognitive)) {
|
|
1885
|
+
if (!Array.isArray(rawNodes) || rawNodes.length === 0) continue;
|
|
1886
|
+
const items = rawNodes.map(neighborLine).filter((line) => Boolean(line));
|
|
1887
|
+
if (items.length > 0) {
|
|
1888
|
+
sections.push({ heading: `### Cognitive context \u2014 ${category}`, items });
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
if (provenance.length > 0) {
|
|
1893
|
+
const items = provenance.map((raw) => obj(raw)).filter((entry) => Boolean(entry)).map((entry) => {
|
|
1894
|
+
const span = clip(entry.text_span, QUOTE_MAX, state) || "";
|
|
1895
|
+
const by = str(entry.ingested_by_name);
|
|
1896
|
+
const suffix = `${by ? ` (ingested by ${by})` : ""} [source ${str(entry.source_uid) || "?"}]`;
|
|
1897
|
+
return str(entry.span_kind) === "anchor" ? `- "${span}"${suffix}` : `- context: ${span}${suffix}`;
|
|
1898
|
+
});
|
|
1899
|
+
sections.push({ heading: "## Sources", items });
|
|
1900
|
+
}
|
|
1901
|
+
const confidence = num(obj(payload.confidence)?.overall);
|
|
1902
|
+
const notes = [];
|
|
1903
|
+
if (confidence !== void 0) notes.push(`overall confidence ${confidence}`);
|
|
1904
|
+
if (payload.has_more === true) notes.push("more results exist (has_more)");
|
|
1905
|
+
if (payload.seed_cap_hit === true) notes.push("seed cap hit \u2014 narrow the query for a complete set");
|
|
1906
|
+
if (notes.length > 0) sections.push({ heading: `Note: ${notes.join("; ")}.`, items: [] });
|
|
1907
|
+
return assemble(
|
|
1908
|
+
`# Ontology results (${objects.length} object${objects.length === 1 ? "" : "s"})`,
|
|
1909
|
+
sections,
|
|
1910
|
+
state
|
|
1911
|
+
);
|
|
1912
|
+
}
|
|
1913
|
+
function renderObjectList(response, title) {
|
|
1914
|
+
const payload = obj(response);
|
|
1915
|
+
if (!payload) return void 0;
|
|
1916
|
+
const rawItems = Array.isArray(payload.items) ? payload.items : Array.isArray(payload.rows) && payload.rows.some((row) => unwrapSearchResult(row)) ? payload.rows : void 0;
|
|
1917
|
+
const items = (rawItems ?? []).map(unwrapSearchResult).filter((node) => Boolean(node));
|
|
1918
|
+
if (items.length === 0) {
|
|
1919
|
+
return rawItems ? `# ${title} (0 results)` : void 0;
|
|
1920
|
+
}
|
|
1921
|
+
const state = { bounded: false };
|
|
1922
|
+
const sections = groupedNodeSections(items, state);
|
|
1923
|
+
const total = num(payload.total_count);
|
|
1924
|
+
const truncations = Array.isArray(payload.truncation_reasons) ? payload.truncation_reasons.filter((reason) => typeof reason === "string") : [];
|
|
1925
|
+
const notes = [];
|
|
1926
|
+
if (payload.has_more === true) notes.push("more results exist");
|
|
1927
|
+
if (truncations.length > 0) notes.push(`truncated: ${truncations.join(", ")}`);
|
|
1928
|
+
if (notes.length > 0) sections.push({ heading: `Note: ${notes.join("; ")}.`, items: [] });
|
|
1929
|
+
const count = total !== void 0 && total !== items.length ? `${items.length} of ${total}` : `${items.length}`;
|
|
1930
|
+
return assemble(`# ${title} (${count})`, sections, state);
|
|
1931
|
+
}
|
|
1932
|
+
var JOBS_RENDER_MAX = 20;
|
|
1933
|
+
function renderJobs(response) {
|
|
1934
|
+
const jobs = Array.isArray(response) ? response : obj(response)?.jobs;
|
|
1935
|
+
if (!Array.isArray(jobs)) return void 0;
|
|
1936
|
+
if (jobs.length === 0) return "No ingestion jobs.";
|
|
1937
|
+
const state = { bounded: false };
|
|
1938
|
+
const sorted = jobs.map((raw) => obj(raw)).filter((job) => Boolean(job)).sort((a, b) => (num(b.created_at) ?? 0) - (num(a.created_at) ?? 0));
|
|
1939
|
+
const shown = sorted.slice(0, JOBS_RENDER_MAX);
|
|
1940
|
+
if (shown.length < sorted.length) state.bounded = true;
|
|
1941
|
+
const items = shown.map((job) => {
|
|
1942
|
+
const progress = obj(job.progress);
|
|
1943
|
+
const done = num(progress?.processed_chunks);
|
|
1944
|
+
const totalChunks = num(progress?.total_chunks);
|
|
1945
|
+
const bits = [
|
|
1946
|
+
str(job.status) || "?",
|
|
1947
|
+
done !== void 0 && totalChunks !== void 0 ? `${done}/${totalChunks} chunks` : void 0,
|
|
1948
|
+
num(progress?.nodes_created) !== void 0 ? `${num(progress?.nodes_created)} nodes` : void 0,
|
|
1949
|
+
num(job.queue_position) !== void 0 ? `queue #${num(job.queue_position)}` : void 0,
|
|
1950
|
+
str(job.error) ? `error: ${clip(job.error, 160, state)}` : void 0
|
|
1951
|
+
].filter(Boolean);
|
|
1952
|
+
return `- [${str(job.id) || "?"}] ${clip(job.title, 120, state) || "(untitled)"} \u2014 ${bits.join(", ")}`;
|
|
1953
|
+
});
|
|
1954
|
+
return assemble(
|
|
1955
|
+
`# Ingestion jobs (${shown.length}${shown.length < sorted.length ? ` of ${sorted.length}` : ""})`,
|
|
1956
|
+
[{ heading: "", items }],
|
|
1957
|
+
state
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
function renderSignals(response) {
|
|
1961
|
+
const payload = obj(response);
|
|
1962
|
+
if (!payload) return void 0;
|
|
1963
|
+
const state = { bounded: false };
|
|
1964
|
+
const sections = [];
|
|
1965
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
1966
|
+
if (!Array.isArray(value) || value.length === 0) continue;
|
|
1967
|
+
const items = value.map((raw) => obj(raw)).filter((item) => Boolean(item)).map((item) => {
|
|
1968
|
+
const fromLabel = str(item.from_label);
|
|
1969
|
+
const toLabel = str(item.to_label);
|
|
1970
|
+
const anyLabelKey = Object.keys(item).find(
|
|
1971
|
+
(k) => k.endsWith("_label") && str(item[k])
|
|
1972
|
+
);
|
|
1973
|
+
const label = str(item.label) ?? str(item.title) ?? str(item.name) ?? (fromLabel && toLabel ? `${fromLabel} \u2194 ${toLabel}` : void 0) ?? (anyLabelKey ? str(item[anyLabelKey]) : void 0) ?? str(item.uid) ?? str(item.target_uid) ?? "(item)";
|
|
1974
|
+
const uid = str(item.uid) ?? str(item.target_uid);
|
|
1975
|
+
const numbers = Object.entries(item).filter(([, v]) => typeof v === "number").slice(0, 4).map(([k, v]) => `${k} ${Math.round(v * 100) / 100}`);
|
|
1976
|
+
const lists = Object.entries(item).filter(([, v]) => Array.isArray(v) && v.length > 0).slice(0, 2).map(([k, v]) => `${k}: ${v.length}`);
|
|
1977
|
+
const meta = [...numbers, ...lists].join(", ");
|
|
1978
|
+
return `- ${clip(label, 160, state)}${uid && uid !== label ? ` [${uid}]` : ""}${meta ? ` (${meta})` : ""}`;
|
|
1979
|
+
});
|
|
1980
|
+
if (items.length > 0) {
|
|
1981
|
+
sections.push({ heading: `## ${key.replace(/_/g, " ")}`, items });
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
if (sections.length === 0) return void 0;
|
|
1985
|
+
return assemble("# Synthesis signals", sections, state);
|
|
1986
|
+
}
|
|
1825
1987
|
|
|
1826
1988
|
// src/tools.ts
|
|
1827
1989
|
var TOOLS = [
|
|
@@ -2631,6 +2793,11 @@ var TOOLS = [
|
|
|
2631
2793
|
type: "string",
|
|
2632
2794
|
description: "Job ID to check status (for job_status action)"
|
|
2633
2795
|
},
|
|
2796
|
+
format: {
|
|
2797
|
+
type: "string",
|
|
2798
|
+
enum: ["text", "json"],
|
|
2799
|
+
description: "job_status without job_id: 'text' (default) renders the 20 most recent jobs; 'json' returns the full raw list."
|
|
2800
|
+
},
|
|
2634
2801
|
agent_id: {
|
|
2635
2802
|
type: "string",
|
|
2636
2803
|
description: "Agent identity"
|
|
@@ -2666,6 +2833,11 @@ var TOOLS = [
|
|
|
2666
2833
|
type: "string",
|
|
2667
2834
|
description: "Job ID to poll (for action='job_status')"
|
|
2668
2835
|
},
|
|
2836
|
+
format: {
|
|
2837
|
+
type: "string",
|
|
2838
|
+
enum: ["text", "json"],
|
|
2839
|
+
description: "signals action: 'text' (default) renders signal sections; 'json' returns the raw payload."
|
|
2840
|
+
},
|
|
2669
2841
|
agent_id: {
|
|
2670
2842
|
type: "string",
|
|
2671
2843
|
description: "Agent identity"
|
|
@@ -2774,6 +2946,11 @@ var TOOLS = [
|
|
|
2774
2946
|
items: { type: "string" },
|
|
2775
2947
|
description: "Chunk/document UIDs to extract from (for action=extract)"
|
|
2776
2948
|
},
|
|
2949
|
+
format: {
|
|
2950
|
+
type: "string",
|
|
2951
|
+
enum: ["text", "json"],
|
|
2952
|
+
description: "Output format for the read actions query/search/objects/object/object_context (default 'text'): a compact rendered block. Pass 'json' for the raw server response."
|
|
2953
|
+
},
|
|
2777
2954
|
agent_id: {
|
|
2778
2955
|
type: "string",
|
|
2779
2956
|
description: "Agent identity"
|
|
@@ -2816,9 +2993,14 @@ function toolsForProfile(profile = process.env.MINDGRAPH_PROFILE || "general") {
|
|
|
2816
2993
|
}
|
|
2817
2994
|
function ok3(data) {
|
|
2818
2995
|
return {
|
|
2819
|
-
content: [{ type: "text", text: JSON.stringify(data
|
|
2996
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
2820
2997
|
};
|
|
2821
2998
|
}
|
|
2999
|
+
function renderedResult(format, raw, render) {
|
|
3000
|
+
if (format === "json") return ok3(raw);
|
|
3001
|
+
const text = render(raw);
|
|
3002
|
+
return text !== void 0 ? { content: [{ type: "text", text }] } : ok3(raw);
|
|
3003
|
+
}
|
|
2822
3004
|
function err3(message) {
|
|
2823
3005
|
return {
|
|
2824
3006
|
content: [{ type: "text", text: JSON.stringify({ error: message }) }],
|
|
@@ -3430,15 +3612,11 @@ async function handleRetrieve(client2, args) {
|
|
|
3430
3612
|
max_cost,
|
|
3431
3613
|
agent_id
|
|
3432
3614
|
} = args;
|
|
3433
|
-
const
|
|
3434
|
-
if (format === "json") return ok3(raw);
|
|
3435
|
-
const text = render(raw);
|
|
3436
|
-
return text !== void 0 ? { content: [{ type: "text", text }] } : ok3(raw);
|
|
3437
|
-
};
|
|
3615
|
+
const rendered2 = (raw, render) => renderedResult(format, raw, render);
|
|
3438
3616
|
switch (action) {
|
|
3439
3617
|
case "context":
|
|
3440
3618
|
if (!query) return err3("query is required for context retrieval");
|
|
3441
|
-
return
|
|
3619
|
+
return rendered2(
|
|
3442
3620
|
await client2.retrieveContext({
|
|
3443
3621
|
query,
|
|
3444
3622
|
node_limit: limit,
|
|
@@ -3463,7 +3641,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3463
3641
|
);
|
|
3464
3642
|
case "text":
|
|
3465
3643
|
if (!query) return err3("query is required for text search");
|
|
3466
|
-
return
|
|
3644
|
+
return rendered2(
|
|
3467
3645
|
await client2.retrieve({
|
|
3468
3646
|
action: "text",
|
|
3469
3647
|
query,
|
|
@@ -3477,7 +3655,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3477
3655
|
);
|
|
3478
3656
|
case "semantic":
|
|
3479
3657
|
if (!query) return err3("query is required for semantic search");
|
|
3480
|
-
return
|
|
3658
|
+
return rendered2(
|
|
3481
3659
|
await client2.retrieve({
|
|
3482
3660
|
action: "semantic",
|
|
3483
3661
|
query,
|
|
@@ -3491,7 +3669,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3491
3669
|
);
|
|
3492
3670
|
case "hybrid":
|
|
3493
3671
|
if (!query) return err3("query is required for hybrid search");
|
|
3494
|
-
return
|
|
3672
|
+
return rendered2(
|
|
3495
3673
|
await client2.retrieve({
|
|
3496
3674
|
action: "hybrid",
|
|
3497
3675
|
query,
|
|
@@ -3513,7 +3691,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3513
3691
|
case "weak_claims":
|
|
3514
3692
|
case "pending_approvals":
|
|
3515
3693
|
case "unresolved_contradictions":
|
|
3516
|
-
return
|
|
3694
|
+
return rendered2(
|
|
3517
3695
|
await client2.retrieve({
|
|
3518
3696
|
action,
|
|
3519
3697
|
limit,
|
|
@@ -3523,7 +3701,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3523
3701
|
(raw) => renderNodeList(raw, action.replace(/_/g, " "), limit)
|
|
3524
3702
|
);
|
|
3525
3703
|
case "stale_derivations":
|
|
3526
|
-
return
|
|
3704
|
+
return rendered2(
|
|
3527
3705
|
await client2.retrieve({
|
|
3528
3706
|
action: "stale_derivations",
|
|
3529
3707
|
limit,
|
|
@@ -3532,7 +3710,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3532
3710
|
(raw) => renderNodeList(raw, "stale derivations", limit)
|
|
3533
3711
|
);
|
|
3534
3712
|
case "preferences":
|
|
3535
|
-
return
|
|
3713
|
+
return rendered2(
|
|
3536
3714
|
await client2.retrieve({
|
|
3537
3715
|
action: "preferences",
|
|
3538
3716
|
...query ? { query, k: limit } : {},
|
|
@@ -3543,7 +3721,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3543
3721
|
);
|
|
3544
3722
|
case "layer":
|
|
3545
3723
|
if (!layer) return err3("layer is required for layer retrieval");
|
|
3546
|
-
return
|
|
3724
|
+
return rendered2(
|
|
3547
3725
|
await client2.retrieve({
|
|
3548
3726
|
action: "layer",
|
|
3549
3727
|
layer,
|
|
@@ -3554,7 +3732,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3554
3732
|
(raw) => renderNodeList(raw, `Layer: ${layer}`, limit)
|
|
3555
3733
|
);
|
|
3556
3734
|
case "recent":
|
|
3557
|
-
return
|
|
3735
|
+
return rendered2(
|
|
3558
3736
|
await client2.retrieve({
|
|
3559
3737
|
action: "recent",
|
|
3560
3738
|
limit,
|
|
@@ -3569,7 +3747,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3569
3747
|
);
|
|
3570
3748
|
// Document inventory
|
|
3571
3749
|
case "document_index":
|
|
3572
|
-
return
|
|
3750
|
+
return rendered2(
|
|
3573
3751
|
await client2.getNodes({
|
|
3574
3752
|
node_type: "Document",
|
|
3575
3753
|
limit: limit ?? 100
|
|
@@ -3579,7 +3757,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3579
3757
|
// Graph traversal
|
|
3580
3758
|
case "chain":
|
|
3581
3759
|
if (!start_uid) return err3("start_uid is required for chain traversal");
|
|
3582
|
-
return
|
|
3760
|
+
return rendered2(
|
|
3583
3761
|
await client2.traverse({
|
|
3584
3762
|
action: "chain",
|
|
3585
3763
|
start_uid,
|
|
@@ -3592,7 +3770,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3592
3770
|
);
|
|
3593
3771
|
case "neighborhood":
|
|
3594
3772
|
if (!start_uid) return err3("start_uid is required for neighborhood traversal");
|
|
3595
|
-
return
|
|
3773
|
+
return rendered2(
|
|
3596
3774
|
await client2.traverse({
|
|
3597
3775
|
action: "neighborhood",
|
|
3598
3776
|
start_uid,
|
|
@@ -3608,7 +3786,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3608
3786
|
case "path":
|
|
3609
3787
|
if (!start_uid) return err3("start_uid is required for path traversal");
|
|
3610
3788
|
if (!end_uid) return err3("end_uid is required for path traversal");
|
|
3611
|
-
return
|
|
3789
|
+
return rendered2(
|
|
3612
3790
|
await client2.traverse({
|
|
3613
3791
|
action: "path",
|
|
3614
3792
|
start_uid,
|
|
@@ -3624,7 +3802,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3624
3802
|
);
|
|
3625
3803
|
case "subgraph":
|
|
3626
3804
|
if (!start_uid) return err3("start_uid is required for subgraph traversal");
|
|
3627
|
-
return
|
|
3805
|
+
return rendered2(
|
|
3628
3806
|
await client2.traverse({
|
|
3629
3807
|
action: "subgraph",
|
|
3630
3808
|
start_uid,
|
|
@@ -3640,7 +3818,7 @@ async function handleRetrieve(client2, args) {
|
|
|
3640
3818
|
case "top_k_paths":
|
|
3641
3819
|
if (!start_uid) return err3("start_uid is required for top_k_paths");
|
|
3642
3820
|
if (!end_uid) return err3("end_uid is required for top_k_paths");
|
|
3643
|
-
return
|
|
3821
|
+
return rendered2(
|
|
3644
3822
|
await client2.traverse({
|
|
3645
3823
|
action: "top_k_paths",
|
|
3646
3824
|
start_uid,
|
|
@@ -3677,6 +3855,7 @@ async function handleIngest(client2, args) {
|
|
|
3677
3855
|
chunk_size,
|
|
3678
3856
|
chunk_overlap,
|
|
3679
3857
|
job_id,
|
|
3858
|
+
format,
|
|
3680
3859
|
agent_id
|
|
3681
3860
|
} = args;
|
|
3682
3861
|
const src = source_uri ?? source;
|
|
@@ -3746,19 +3925,21 @@ async function handleIngest(client2, args) {
|
|
|
3746
3925
|
if (job_id) {
|
|
3747
3926
|
return ok3(await client2.getJob(job_id));
|
|
3748
3927
|
}
|
|
3749
|
-
return
|
|
3928
|
+
return renderedResult(format, await client2.listJobs(), renderJobs);
|
|
3750
3929
|
default:
|
|
3751
3930
|
return err3(`Unknown ingest action: ${action}`);
|
|
3752
3931
|
}
|
|
3753
3932
|
}
|
|
3754
3933
|
async function handleSynthesize(client2, args) {
|
|
3755
|
-
const { action, project_uid, signals, target_types, job_id } = args;
|
|
3934
|
+
const { action, project_uid, signals, target_types, job_id, format } = args;
|
|
3756
3935
|
switch (action) {
|
|
3757
3936
|
case "signals":
|
|
3758
3937
|
if (!project_uid)
|
|
3759
3938
|
return err3("project_uid is required for action='signals'");
|
|
3760
|
-
return
|
|
3761
|
-
|
|
3939
|
+
return renderedResult(
|
|
3940
|
+
format,
|
|
3941
|
+
await client2.signals(project_uid, { signals, target_types }),
|
|
3942
|
+
renderSignals
|
|
3762
3943
|
);
|
|
3763
3944
|
case "run":
|
|
3764
3945
|
if (!project_uid)
|
|
@@ -3792,6 +3973,7 @@ async function handleOntology(client2, args) {
|
|
|
3792
3973
|
relation_type,
|
|
3793
3974
|
fields,
|
|
3794
3975
|
source_uids,
|
|
3976
|
+
format,
|
|
3795
3977
|
agent_id
|
|
3796
3978
|
} = args;
|
|
3797
3979
|
switch (action) {
|
|
@@ -3807,7 +3989,8 @@ async function handleOntology(client2, args) {
|
|
|
3807
3989
|
"schema_id is required for action='query' (use action='schemas' to find the active schema)"
|
|
3808
3990
|
);
|
|
3809
3991
|
}
|
|
3810
|
-
return
|
|
3992
|
+
return renderedResult(
|
|
3993
|
+
format,
|
|
3811
3994
|
await client2.queryOntology({
|
|
3812
3995
|
query,
|
|
3813
3996
|
schema_id,
|
|
@@ -3816,29 +3999,42 @@ async function handleOntology(client2, args) {
|
|
|
3816
3999
|
include_sources: include_sources ?? true,
|
|
3817
4000
|
depth,
|
|
3818
4001
|
limit
|
|
3819
|
-
})
|
|
4002
|
+
}),
|
|
4003
|
+
renderOntologyAnswer
|
|
3820
4004
|
);
|
|
3821
4005
|
}
|
|
3822
4006
|
case "search":
|
|
3823
4007
|
if (!query) return err3("query is required for action='search'");
|
|
3824
|
-
return
|
|
4008
|
+
return renderedResult(
|
|
4009
|
+
format,
|
|
3825
4010
|
await client2.searchDomainObjects(query, {
|
|
3826
4011
|
schema_id,
|
|
3827
4012
|
object_types,
|
|
3828
4013
|
limit
|
|
3829
|
-
})
|
|
4014
|
+
}),
|
|
4015
|
+
(raw) => renderObjectList(raw, `Domain search: ${query}`)
|
|
3830
4016
|
);
|
|
3831
4017
|
case "objects":
|
|
3832
4018
|
if (!schema_id) return err3("schema_id is required for action='objects'");
|
|
3833
|
-
return
|
|
3834
|
-
|
|
4019
|
+
return renderedResult(
|
|
4020
|
+
format,
|
|
4021
|
+
await client2.listDomainObjects({ schema_id, object_type, limit }),
|
|
4022
|
+
(raw) => renderObjectList(raw, `Domain objects${object_type ? `: ${object_type}` : ""}`)
|
|
3835
4023
|
);
|
|
3836
4024
|
case "object":
|
|
3837
4025
|
if (!uid) return err3("uid is required for action='object'");
|
|
3838
|
-
return
|
|
4026
|
+
return renderedResult(
|
|
4027
|
+
format,
|
|
4028
|
+
await client2.getDomainObject(uid),
|
|
4029
|
+
(raw) => renderNodeList([raw], "Domain object")
|
|
4030
|
+
);
|
|
3839
4031
|
case "object_context":
|
|
3840
4032
|
if (!uid) return err3("uid is required for action='object_context'");
|
|
3841
|
-
return
|
|
4033
|
+
return renderedResult(
|
|
4034
|
+
format,
|
|
4035
|
+
await client2.getDomainObjectContext(uid, depth),
|
|
4036
|
+
renderOntologyAnswer
|
|
4037
|
+
);
|
|
3842
4038
|
case "proposals":
|
|
3843
4039
|
return ok3(
|
|
3844
4040
|
await client2.listOntologyProposals({
|
|
@@ -3892,8 +4088,14 @@ async function handleOntology(client2, args) {
|
|
|
3892
4088
|
|
|
3893
4089
|
// src/generated-tools.ts
|
|
3894
4090
|
var ok4 = (data) => ({
|
|
3895
|
-
|
|
4091
|
+
// Compact on purpose — pretty-printing doubled the token cost.
|
|
4092
|
+
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
3896
4093
|
});
|
|
4094
|
+
var rendered = (format, raw, render) => {
|
|
4095
|
+
if (format === "json") return ok4(raw);
|
|
4096
|
+
const text = render(raw);
|
|
4097
|
+
return text !== void 0 ? { content: [{ type: "text", text }] } : ok4(raw);
|
|
4098
|
+
};
|
|
3897
4099
|
var err4 = (message) => ({
|
|
3898
4100
|
content: [{ type: "text", text: JSON.stringify({ error: message }) }],
|
|
3899
4101
|
isError: true
|
|
@@ -3932,10 +4134,21 @@ async function getGeneratedTools(client2) {
|
|
|
3932
4134
|
);
|
|
3933
4135
|
}
|
|
3934
4136
|
byName.set(d.name, d);
|
|
4137
|
+
const inputSchema = d.maps_to === "structured_query" ? d.input_schema : {
|
|
4138
|
+
...d.input_schema,
|
|
4139
|
+
properties: {
|
|
4140
|
+
...d.input_schema.properties,
|
|
4141
|
+
format: {
|
|
4142
|
+
type: "string",
|
|
4143
|
+
enum: ["text", "json"],
|
|
4144
|
+
description: "Output format (default 'text': compact rendered block). Pass 'json' for the raw server response."
|
|
4145
|
+
}
|
|
4146
|
+
}
|
|
4147
|
+
};
|
|
3935
4148
|
tools.push({
|
|
3936
4149
|
name: d.name,
|
|
3937
4150
|
description: d.description,
|
|
3938
|
-
inputSchema
|
|
4151
|
+
inputSchema
|
|
3939
4152
|
});
|
|
3940
4153
|
}
|
|
3941
4154
|
cache = { tools, byName, fetchedAt: Date.now() };
|
|
@@ -3964,31 +4177,41 @@ async function handleGeneratedTool(client2, desc, args) {
|
|
|
3964
4177
|
if (!query) return err4(`query is required for ${desc.name}`);
|
|
3965
4178
|
const limit = typeof args.limit === "number" ? args.limit : void 0;
|
|
3966
4179
|
const filters = Array.isArray(args.filters) ? args.filters : void 0;
|
|
3967
|
-
return
|
|
4180
|
+
return rendered(
|
|
4181
|
+
args.format,
|
|
3968
4182
|
await ontologyClient.searchDomainObjects(query, {
|
|
3969
4183
|
schema_id: desc.schema_id,
|
|
3970
4184
|
object_types: [desc.object_type],
|
|
3971
4185
|
filters,
|
|
3972
4186
|
limit
|
|
3973
|
-
})
|
|
4187
|
+
}),
|
|
4188
|
+
(raw) => renderObjectList(raw, `${desc.object_type} search: ${query}`)
|
|
3974
4189
|
);
|
|
3975
4190
|
}
|
|
3976
4191
|
case "object": {
|
|
3977
4192
|
const uid = args.uid;
|
|
3978
4193
|
if (!uid) return err4(`uid is required for ${desc.name}`);
|
|
3979
|
-
return
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
4194
|
+
return rendered(
|
|
4195
|
+
args.format,
|
|
4196
|
+
await ontologyClient.getDomainObject(uid, {
|
|
4197
|
+
schema_id: desc.schema_id,
|
|
4198
|
+
object_type: desc.object_type
|
|
4199
|
+
}),
|
|
4200
|
+
(raw) => renderNodeList([raw], desc.object_type)
|
|
4201
|
+
);
|
|
3983
4202
|
}
|
|
3984
4203
|
case "object_context": {
|
|
3985
4204
|
const uid = args.uid;
|
|
3986
4205
|
if (!uid) return err4(`uid is required for ${desc.name}`);
|
|
3987
4206
|
const depth = typeof args.depth === "number" ? args.depth : void 0;
|
|
3988
|
-
return
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
4207
|
+
return rendered(
|
|
4208
|
+
args.format,
|
|
4209
|
+
await ontologyClient.getDomainObjectContext(uid, depth, {
|
|
4210
|
+
schema_id: desc.schema_id,
|
|
4211
|
+
object_type: desc.object_type
|
|
4212
|
+
}),
|
|
4213
|
+
renderOntologyAnswer
|
|
4214
|
+
);
|
|
3992
4215
|
}
|
|
3993
4216
|
case "related": {
|
|
3994
4217
|
const uid = args.uid;
|
|
@@ -4001,18 +4224,22 @@ async function handleGeneratedTool(client2, desc, args) {
|
|
|
4001
4224
|
"related ontology tools require a graph-aware version of the mindgraph SDK"
|
|
4002
4225
|
);
|
|
4003
4226
|
}
|
|
4004
|
-
return
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
|
|
4011
|
-
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4227
|
+
return rendered(
|
|
4228
|
+
args.format,
|
|
4229
|
+
await ontologyClient.queryRelatedDomainObjects({
|
|
4230
|
+
schema_id: desc.schema_id,
|
|
4231
|
+
entry_type: desc.object_type,
|
|
4232
|
+
uid,
|
|
4233
|
+
relation: desc.relation,
|
|
4234
|
+
entry_role: desc.entry_role,
|
|
4235
|
+
far_type: desc.far_type,
|
|
4236
|
+
where: Array.isArray(args.where) ? args.where : void 0,
|
|
4237
|
+
include_provenance: args.include_provenance === true,
|
|
4238
|
+
limit: typeof args.limit === "number" ? args.limit : void 0,
|
|
4239
|
+
offset: typeof args.offset === "number" ? args.offset : void 0
|
|
4240
|
+
}),
|
|
4241
|
+
(raw) => renderObjectList(raw, `${desc.far_type} related via ${desc.relation}`)
|
|
4242
|
+
);
|
|
4016
4243
|
}
|
|
4017
4244
|
case "structured_query": {
|
|
4018
4245
|
const select = args.select;
|
|
@@ -4331,7 +4558,7 @@ var RESOURCE_TEMPLATES = [
|
|
|
4331
4558
|
var RESOURCE_GOVERNANCE_TOOL = "mindgraph_retrieve";
|
|
4332
4559
|
function json(uri, data) {
|
|
4333
4560
|
return {
|
|
4334
|
-
contents: [{ uri, mimeType: "application/json", text: JSON.stringify(data
|
|
4561
|
+
contents: [{ uri, mimeType: "application/json", text: JSON.stringify(data) }]
|
|
4335
4562
|
};
|
|
4336
4563
|
}
|
|
4337
4564
|
async function readResource(client2, uri) {
|
|
@@ -4504,7 +4731,7 @@ if (PROFILE === "coding") {
|
|
|
4504
4731
|
var server = new import_server.Server(
|
|
4505
4732
|
{
|
|
4506
4733
|
name: "mindgraph",
|
|
4507
|
-
version: "0.
|
|
4734
|
+
version: "0.17.0"
|
|
4508
4735
|
},
|
|
4509
4736
|
{
|
|
4510
4737
|
capabilities: {
|
|
@@ -4718,7 +4945,7 @@ async function main() {
|
|
|
4718
4945
|
const transport = new import_stdio.StdioServerTransport();
|
|
4719
4946
|
await server.connect(transport);
|
|
4720
4947
|
console.error(
|
|
4721
|
-
`MindGraph MCP server v${"0.
|
|
4948
|
+
`MindGraph MCP server v${"0.17.0"} running on stdio (${BASE_URL})`
|
|
4722
4949
|
);
|
|
4723
4950
|
}
|
|
4724
4951
|
main().catch((error) => {
|