@astramindapp/mcp-server 0.5.4 → 0.7.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 +44 -6
- package/dist/mind-client.d.ts +173 -0
- package/dist/mind-client.d.ts.map +1 -1
- package/dist/mind-client.js +71 -0
- package/dist/mind-client.js.map +1 -1
- package/dist/server.d.ts +3 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +452 -1
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
package/dist/server.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Exposes the MIND knowledge graph as MCP tools that any LLM agent can use.
|
|
6
6
|
* This is the universal AI memory layer.
|
|
7
7
|
*
|
|
8
|
-
* Tools (
|
|
8
|
+
* Tools (16):
|
|
9
9
|
* mind_query — Semantic search across the knowledge graph
|
|
10
10
|
* mind_remember — Store/manage content in the graph (auto-categorized)
|
|
11
11
|
* mind_context — Get structured always-loaded context (soul/user/rules)
|
|
@@ -21,6 +21,8 @@
|
|
|
21
21
|
* mind_insights — ALE insights and analytics
|
|
22
22
|
* mind_automate — Automations and triggers
|
|
23
23
|
* mind_notify — Notifications management
|
|
24
|
+
* mind_agents — Admin-only Agent Command Center (registry, heartbeat,
|
|
25
|
+
* probe, status — for Anthony's agent fleet)
|
|
24
26
|
*/
|
|
25
27
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
28
|
exports.createMindMcpServer = createMindMcpServer;
|
|
@@ -1808,6 +1810,455 @@ function createMindMcpServer(client) {
|
|
|
1808
1810
|
};
|
|
1809
1811
|
}
|
|
1810
1812
|
});
|
|
1813
|
+
// ─── MIND Front Layer (typed-document taxonomy / "MIND Sense") ─────────────
|
|
1814
|
+
// Three tools that expose the 16 typed-document templates and the typed-save flow.
|
|
1815
|
+
// The same templates power the developer API endpoints under /v1/templates.
|
|
1816
|
+
server.tool("mind_list_templates", "List the 16 MIND Front Layer template types (SOUL, IDENTITY, BELIEFS, USER, AGENTS, TOOLS, SENSES, SKILLS, BEHAVIOR, LESSON, DECISION, POLICY, WORKFLOW, PREFERENCE, GOAL, RELATIONSHIP). Use this first to see what typed documents an agent can fill in. Each entry includes a short description and the source_tag used when storing filled documents.", {}, async () => {
|
|
1817
|
+
try {
|
|
1818
|
+
const result = await client.listFrontLayerTemplates();
|
|
1819
|
+
const lines = [
|
|
1820
|
+
`📋 MIND Front Layer — ${result.count} typed-document templates`,
|
|
1821
|
+
"",
|
|
1822
|
+
];
|
|
1823
|
+
for (const t of result.templates) {
|
|
1824
|
+
lines.push(`• ${t.type.padEnd(13)} — ${t.description}`);
|
|
1825
|
+
}
|
|
1826
|
+
lines.push("");
|
|
1827
|
+
lines.push("Fetch one with mind_get_template(type=\"<TYPE>\")");
|
|
1828
|
+
lines.push("Save a filled doc with mind_save_typed(type=\"<TYPE>\", title=..., content=...)");
|
|
1829
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
1830
|
+
}
|
|
1831
|
+
catch (err) {
|
|
1832
|
+
return {
|
|
1833
|
+
content: [{ type: "text", text: `Error listing templates: ${err}` }],
|
|
1834
|
+
isError: true,
|
|
1835
|
+
};
|
|
1836
|
+
}
|
|
1837
|
+
});
|
|
1838
|
+
server.tool("mind_get_template", "Fetch the full augmented markdown for one MIND Front Layer template. Returns a self-contained spec — when to create a document of this type, what slots to fill, and how to store the filled copy. Always read the template before writing a typed document.", {
|
|
1839
|
+
type: zod_1.z
|
|
1840
|
+
.string()
|
|
1841
|
+
.describe("One of the 16 canonical types, upper-case (e.g. SOUL, BEHAVIOR, LESSON, POLICY, GOAL). Use mind_list_templates to see all valid values."),
|
|
1842
|
+
}, async ({ type }) => {
|
|
1843
|
+
try {
|
|
1844
|
+
const result = await client.getFrontLayerTemplate(type);
|
|
1845
|
+
const lines = [
|
|
1846
|
+
`📄 ${result.type} template`,
|
|
1847
|
+
`Description: ${result.description}`,
|
|
1848
|
+
`Source tag (use this when storing): ${result.source_tag}`,
|
|
1849
|
+
`Default tags: ${result.default_tags.join(", ")}`,
|
|
1850
|
+
"",
|
|
1851
|
+
result.body,
|
|
1852
|
+
"",
|
|
1853
|
+
`--- Store via: ${result.store_via} ---`,
|
|
1854
|
+
];
|
|
1855
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
1856
|
+
}
|
|
1857
|
+
catch (err) {
|
|
1858
|
+
return {
|
|
1859
|
+
content: [{ type: "text", text: `Error fetching template: ${err}` }],
|
|
1860
|
+
isError: true,
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
});
|
|
1864
|
+
server.tool("mind_save_typed", "Save a filled-out Front Layer document with the proper type tag so retrieval can filter by it later. Wraps mind document creation and pre-bakes the source tag (`front-layer-<type>`). Use this — not raw mind_remember — for any SOUL/IDENTITY/BELIEFS/USER/BEHAVIOR/LESSON/POLICY/etc. document. Pass the markdown body (frontmatter + content) as the `content` field.", {
|
|
1865
|
+
type: zod_1.z
|
|
1866
|
+
.string()
|
|
1867
|
+
.describe("The Front Layer type for this document (e.g. BEHAVIOR, LESSON, POLICY). Must match one of the 16 canonical types."),
|
|
1868
|
+
title: zod_1.z
|
|
1869
|
+
.string()
|
|
1870
|
+
.describe("Short, human-readable title for the document — used in retrieval and the documents UI."),
|
|
1871
|
+
content: zod_1.z
|
|
1872
|
+
.string()
|
|
1873
|
+
.describe("Full markdown body of the typed document including the frontmatter block (---type, id, slots, ---) followed by the human-readable sections."),
|
|
1874
|
+
}, async ({ type, title, content }) => {
|
|
1875
|
+
try {
|
|
1876
|
+
const result = await client.saveTypedDocument(type, title, content);
|
|
1877
|
+
const lines = [
|
|
1878
|
+
`✅ Saved as ${type} document`,
|
|
1879
|
+
`id: ${result.id}`,
|
|
1880
|
+
`title: ${result.title ?? title}`,
|
|
1881
|
+
`source: front-layer-${type.toLowerCase()}`,
|
|
1882
|
+
`status: ${result.status ?? "PROCESSED"}`,
|
|
1883
|
+
];
|
|
1884
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
1885
|
+
}
|
|
1886
|
+
catch (err) {
|
|
1887
|
+
return {
|
|
1888
|
+
content: [{ type: "text", text: `Error saving typed document: ${err}` }],
|
|
1889
|
+
isError: true,
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1892
|
+
});
|
|
1893
|
+
server.tool("mind_bootstrap_templates", "Seed all 16 MIND Front Layer templates into this MIND tenant as system documents. After running, the templates become queryable through mind_query so agents can ask 'what should I fill out for SOUL?' and retrieve the spec from their own knowledge graph. Idempotent — re-runs create fresh copies. Run once per new tenant.", {}, async () => {
|
|
1894
|
+
try {
|
|
1895
|
+
const result = await client.bootstrapFrontLayerTemplates();
|
|
1896
|
+
const lines = [
|
|
1897
|
+
`🌱 Bootstrapped ${result.bootstrapped} of ${result.total} Front Layer templates into your MIND.`,
|
|
1898
|
+
"",
|
|
1899
|
+
];
|
|
1900
|
+
for (const r of result.results) {
|
|
1901
|
+
if (r.status === "PROCESSED") {
|
|
1902
|
+
lines.push(` ✅ ${r.type.padEnd(13)} — ${r.title ?? ""}`);
|
|
1903
|
+
}
|
|
1904
|
+
else {
|
|
1905
|
+
lines.push(` ❌ ${r.type.padEnd(13)} — ${r.status}${r.error ? `: ${r.error}` : ""}`);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
1909
|
+
}
|
|
1910
|
+
catch (err) {
|
|
1911
|
+
return {
|
|
1912
|
+
content: [{ type: "text", text: `Error bootstrapping templates: ${err}` }],
|
|
1913
|
+
isError: true,
|
|
1914
|
+
};
|
|
1915
|
+
}
|
|
1916
|
+
});
|
|
1917
|
+
// ─── mind_agents ────────────────────────────────────────
|
|
1918
|
+
// Admin-only registry of every agent across MINDapp + the VPS fleet.
|
|
1919
|
+
// Surface UI: https://m-i-n-d.ai/agents · Backend: /admin/agents/*
|
|
1920
|
+
// Use this BEFORE creating a new agent so you don't collide with an
|
|
1921
|
+
// existing slug, and AFTER any non-trivial work to update status,
|
|
1922
|
+
// current_job, or responsibilities.
|
|
1923
|
+
server.tool("mind_agents", "Admin-only Agent Command Center — canonical registry of every Astra AI agent (running on VPS, planned, archived). Query before scaffolding a new agent. Update status / current_job / responsibilities after non-trivial work. Backed by /admin/agents on the MIND backend; admin API key required.", {
|
|
1924
|
+
action: zod_1.z
|
|
1925
|
+
.enum([
|
|
1926
|
+
"list",
|
|
1927
|
+
"get",
|
|
1928
|
+
"create",
|
|
1929
|
+
"update",
|
|
1930
|
+
"delete",
|
|
1931
|
+
"heartbeat",
|
|
1932
|
+
"probe",
|
|
1933
|
+
"log_activity",
|
|
1934
|
+
"list_activities",
|
|
1935
|
+
"import_from_mind",
|
|
1936
|
+
"seed_known",
|
|
1937
|
+
"set_status",
|
|
1938
|
+
"set_current_job",
|
|
1939
|
+
])
|
|
1940
|
+
.describe("Action: list (filter+stats), get (detail+recent activities), create, update (partial), delete (soft archive; pass hard=true to remove), heartbeat (push from agent runtime), probe (HTTP/OpenClaw liveness probe), log_activity (manual note), list_activities, import_from_mind (enrich from agent-identity docs), seed_known (idempotent upsert of canonical seed), set_status (shortcut update), set_current_job (shortcut update)"),
|
|
1941
|
+
slug: zod_1.z.string().optional().describe("Agent slug (lowercase, dashes). Required for get/update/delete/heartbeat/probe/activities/set_*."),
|
|
1942
|
+
// create / update fields
|
|
1943
|
+
name: zod_1.z.string().optional().describe("Display name."),
|
|
1944
|
+
description: zod_1.z.string().optional().describe("One-paragraph description of the agent."),
|
|
1945
|
+
status: zod_1.z
|
|
1946
|
+
.enum(["running", "paused", "planned", "archived", "error"])
|
|
1947
|
+
.optional()
|
|
1948
|
+
.describe("Lifecycle status."),
|
|
1949
|
+
cadence: zod_1.z
|
|
1950
|
+
.enum(["continuous", "scheduled", "on-demand"])
|
|
1951
|
+
.optional()
|
|
1952
|
+
.describe("How the agent runs."),
|
|
1953
|
+
host: zod_1.z.string().optional().describe("Host: DO1 / DO2-LEO / local / render / vercel / atlas-droplet / other."),
|
|
1954
|
+
host_address: zod_1.z.string().optional().describe("IP or hostname (e.g. 45.55.233.204)."),
|
|
1955
|
+
port: zod_1.z.number().optional().describe("TCP port if applicable."),
|
|
1956
|
+
health_url: zod_1.z.string().optional().describe("Optional HTTP health endpoint for the probe action."),
|
|
1957
|
+
source_path: zod_1.z.string().optional().describe("Local path to the agent directory (e.g. /Users/anthonyjconti/Documents/Agents/Foo)."),
|
|
1958
|
+
source_repo: zod_1.z.string().optional().describe("Git repo URL when applicable."),
|
|
1959
|
+
mind_identity_doc_id: zod_1.z.string().optional().describe("MIND document id for the agent-identity record."),
|
|
1960
|
+
responsibilities: zod_1.z.array(zod_1.z.string()).optional().describe("Bullet list of what the agent does."),
|
|
1961
|
+
triggers: zod_1.z.array(zod_1.z.string()).optional().describe("Canonical phrases that should invoke this agent."),
|
|
1962
|
+
tags: zod_1.z.array(zod_1.z.string()).optional().describe("Domain tags for filtering."),
|
|
1963
|
+
owner_email: zod_1.z.string().optional().describe("Owner contact (defaults to anthony@theastraway.com)."),
|
|
1964
|
+
expected_interval_seconds: zod_1.z
|
|
1965
|
+
.number()
|
|
1966
|
+
.optional()
|
|
1967
|
+
.describe("Expected heartbeat cadence in seconds; live_status thresholds compute against 2× / 4× this value."),
|
|
1968
|
+
authority_can_autonomous: zod_1.z.array(zod_1.z.string()).optional().describe("Things this agent can do without asking."),
|
|
1969
|
+
authority_requires_approval: zod_1.z.array(zod_1.z.string()).optional().describe("Things that need Anthony's sign-off."),
|
|
1970
|
+
// delete options
|
|
1971
|
+
hard: zod_1.z.boolean().optional().describe("If true with action=delete, permanently remove. Default soft-archives."),
|
|
1972
|
+
// heartbeat fields
|
|
1973
|
+
current_job: zod_1.z.string().optional().describe("What the agent is doing right now (set on heartbeat or set_current_job)."),
|
|
1974
|
+
metrics: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe("Arbitrary metrics blob attached to a heartbeat."),
|
|
1975
|
+
note: zod_1.z.string().optional().describe("Free-form note attached to a heartbeat."),
|
|
1976
|
+
source: zod_1.z.string().optional().describe("Source attribution for heartbeats / activities."),
|
|
1977
|
+
// log_activity fields
|
|
1978
|
+
activity_type: zod_1.z.string().optional().describe("Activity type for log_activity (e.g. job_done, job_start, error, note)."),
|
|
1979
|
+
activity_payload: zod_1.z.record(zod_1.z.string(), zod_1.z.any()).optional().describe("Activity payload for log_activity."),
|
|
1980
|
+
// list / list_activities filters
|
|
1981
|
+
list_status: zod_1.z
|
|
1982
|
+
.enum(["running", "paused", "planned", "archived", "error"])
|
|
1983
|
+
.optional()
|
|
1984
|
+
.describe("Filter by status when listing."),
|
|
1985
|
+
list_host: zod_1.z.string().optional().describe("Filter by host when listing."),
|
|
1986
|
+
list_tag: zod_1.z.string().optional().describe("Filter by tag when listing."),
|
|
1987
|
+
include_archived: zod_1.z.boolean().optional().describe("Include archived records when listing (default false)."),
|
|
1988
|
+
limit: zod_1.z.number().optional().describe("Max activities to return for list_activities (default 50)."),
|
|
1989
|
+
// seed_known
|
|
1990
|
+
overwrite: zod_1.z.boolean().optional().describe("If true with action=seed_known, reset existing records to seed defaults."),
|
|
1991
|
+
}, async (args) => {
|
|
1992
|
+
const { action, slug, name, description, status, cadence, host, host_address, port, health_url, source_path, source_repo, mind_identity_doc_id, responsibilities, triggers, tags, owner_email, expected_interval_seconds, authority_can_autonomous, authority_requires_approval, hard, current_job, metrics, note, source, activity_type, activity_payload, list_status, list_host, list_tag, include_archived, limit, overwrite, } = args;
|
|
1993
|
+
const requireSlug = (label) => {
|
|
1994
|
+
if (!slug) {
|
|
1995
|
+
return `Error: 'slug' is required for action=${label}.`;
|
|
1996
|
+
}
|
|
1997
|
+
return null;
|
|
1998
|
+
};
|
|
1999
|
+
const buildPayload = () => {
|
|
2000
|
+
const payload = {};
|
|
2001
|
+
if (name !== undefined)
|
|
2002
|
+
payload.name = name;
|
|
2003
|
+
if (description !== undefined)
|
|
2004
|
+
payload.description = description;
|
|
2005
|
+
if (status !== undefined)
|
|
2006
|
+
payload.status = status;
|
|
2007
|
+
if (cadence !== undefined)
|
|
2008
|
+
payload.cadence = cadence;
|
|
2009
|
+
if (host !== undefined)
|
|
2010
|
+
payload.host = host;
|
|
2011
|
+
if (host_address !== undefined)
|
|
2012
|
+
payload.host_address = host_address;
|
|
2013
|
+
if (port !== undefined)
|
|
2014
|
+
payload.port = port;
|
|
2015
|
+
if (health_url !== undefined)
|
|
2016
|
+
payload.health_url = health_url;
|
|
2017
|
+
if (source_path !== undefined)
|
|
2018
|
+
payload.source_path = source_path;
|
|
2019
|
+
if (source_repo !== undefined)
|
|
2020
|
+
payload.source_repo = source_repo;
|
|
2021
|
+
if (mind_identity_doc_id !== undefined)
|
|
2022
|
+
payload.mind_identity_doc_id = mind_identity_doc_id;
|
|
2023
|
+
if (responsibilities !== undefined)
|
|
2024
|
+
payload.responsibilities = responsibilities;
|
|
2025
|
+
if (triggers !== undefined)
|
|
2026
|
+
payload.triggers = triggers;
|
|
2027
|
+
if (tags !== undefined)
|
|
2028
|
+
payload.tags = tags;
|
|
2029
|
+
if (owner_email !== undefined)
|
|
2030
|
+
payload.owner_email = owner_email;
|
|
2031
|
+
if (expected_interval_seconds !== undefined)
|
|
2032
|
+
payload.expected_interval_seconds = expected_interval_seconds;
|
|
2033
|
+
if (current_job !== undefined)
|
|
2034
|
+
payload.current_job = current_job;
|
|
2035
|
+
if (authority_can_autonomous !== undefined || authority_requires_approval !== undefined) {
|
|
2036
|
+
payload.authority = {
|
|
2037
|
+
can_autonomous: authority_can_autonomous ?? [],
|
|
2038
|
+
requires_approval: authority_requires_approval ?? [],
|
|
2039
|
+
};
|
|
2040
|
+
}
|
|
2041
|
+
return payload;
|
|
2042
|
+
};
|
|
2043
|
+
try {
|
|
2044
|
+
switch (action) {
|
|
2045
|
+
case "list": {
|
|
2046
|
+
const result = await client.listAgents({
|
|
2047
|
+
status: list_status,
|
|
2048
|
+
host: list_host,
|
|
2049
|
+
tag: list_tag,
|
|
2050
|
+
include_archived,
|
|
2051
|
+
});
|
|
2052
|
+
const lines = [];
|
|
2053
|
+
const s = result.stats;
|
|
2054
|
+
lines.push(`Agent fleet: ${s.total} total · ${s.running} running · ${s.planned} planned · ${s.paused} paused · ${s.error} errored`, `Live: ${s.online} online · ${s.stale} stale · ${s.offline} offline`, "");
|
|
2055
|
+
for (const a of result.agents) {
|
|
2056
|
+
const host = a.host ?? "—";
|
|
2057
|
+
lines.push(`• [${a.status.padEnd(8)}] ${a.slug.padEnd(28)} ${a.live_status.padEnd(7)} host=${host} — ${a.name}`);
|
|
2058
|
+
}
|
|
2059
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
2060
|
+
}
|
|
2061
|
+
case "get": {
|
|
2062
|
+
const err = requireSlug("get");
|
|
2063
|
+
if (err)
|
|
2064
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2065
|
+
const detail = await client.getAgent(slug);
|
|
2066
|
+
const lines = [
|
|
2067
|
+
`${detail.name} (${detail.slug})`,
|
|
2068
|
+
` status=${detail.status} · cadence=${detail.cadence} · live=${detail.live_status}`,
|
|
2069
|
+
` host=${detail.host ?? "—"}${detail.host_address ? ` (${detail.host_address})` : ""}`,
|
|
2070
|
+
` last_heartbeat=${detail.last_heartbeat ?? "never"} · current_job=${detail.current_job ?? "—"}`,
|
|
2071
|
+
detail.description ? ` ${detail.description}` : "",
|
|
2072
|
+
detail.responsibilities.length
|
|
2073
|
+
? ` Responsibilities:\n - ${detail.responsibilities.join("\n - ")}`
|
|
2074
|
+
: "",
|
|
2075
|
+
detail.tags.length ? ` Tags: ${detail.tags.join(", ")}` : "",
|
|
2076
|
+
detail.recent_activities?.length
|
|
2077
|
+
? ` Recent activity: ${detail.recent_activities
|
|
2078
|
+
.slice(0, 5)
|
|
2079
|
+
.map((e) => `${e.type}@${e.ts.slice(0, 19)}`)
|
|
2080
|
+
.join(" · ")}`
|
|
2081
|
+
: "",
|
|
2082
|
+
].filter(Boolean);
|
|
2083
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
2084
|
+
}
|
|
2085
|
+
case "create": {
|
|
2086
|
+
if (!slug || !name) {
|
|
2087
|
+
return {
|
|
2088
|
+
content: [
|
|
2089
|
+
{ type: "text", text: "Error: 'slug' and 'name' are required for create." },
|
|
2090
|
+
],
|
|
2091
|
+
isError: true,
|
|
2092
|
+
};
|
|
2093
|
+
}
|
|
2094
|
+
const payload = { slug, name, ...buildPayload() };
|
|
2095
|
+
const created = await client.createAgent(payload);
|
|
2096
|
+
return {
|
|
2097
|
+
content: [
|
|
2098
|
+
{ type: "text", text: `✅ Created agent: ${created.slug} (status=${created.status})` },
|
|
2099
|
+
],
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
case "update": {
|
|
2103
|
+
const err = requireSlug("update");
|
|
2104
|
+
if (err)
|
|
2105
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2106
|
+
const payload = buildPayload();
|
|
2107
|
+
if (Object.keys(payload).length === 0) {
|
|
2108
|
+
return {
|
|
2109
|
+
content: [
|
|
2110
|
+
{ type: "text", text: "Error: provide at least one field to update." },
|
|
2111
|
+
],
|
|
2112
|
+
isError: true,
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
const updated = await client.updateAgent(slug, payload);
|
|
2116
|
+
return {
|
|
2117
|
+
content: [
|
|
2118
|
+
{ type: "text", text: `✅ Updated ${updated.slug} (status=${updated.status}, live=${updated.live_status})` },
|
|
2119
|
+
],
|
|
2120
|
+
};
|
|
2121
|
+
}
|
|
2122
|
+
case "delete": {
|
|
2123
|
+
const err = requireSlug("delete");
|
|
2124
|
+
if (err)
|
|
2125
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2126
|
+
const result = await client.deleteAgent(slug, !!hard);
|
|
2127
|
+
return {
|
|
2128
|
+
content: [
|
|
2129
|
+
{ type: "text", text: `✅ ${result.hard ? "Deleted" : "Archived"} ${result.deleted}` },
|
|
2130
|
+
],
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
2133
|
+
case "heartbeat": {
|
|
2134
|
+
const err = requireSlug("heartbeat");
|
|
2135
|
+
if (err)
|
|
2136
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2137
|
+
const updated = await client.agentHeartbeat(slug, {
|
|
2138
|
+
current_job,
|
|
2139
|
+
metrics,
|
|
2140
|
+
note,
|
|
2141
|
+
source: source ?? "mcp-agent",
|
|
2142
|
+
});
|
|
2143
|
+
return {
|
|
2144
|
+
content: [
|
|
2145
|
+
{
|
|
2146
|
+
type: "text",
|
|
2147
|
+
text: `💓 heartbeat ${updated.slug} → live=${updated.live_status}${updated.current_job ? ` · job="${updated.current_job}"` : ""}`,
|
|
2148
|
+
},
|
|
2149
|
+
],
|
|
2150
|
+
};
|
|
2151
|
+
}
|
|
2152
|
+
case "probe": {
|
|
2153
|
+
const err = requireSlug("probe");
|
|
2154
|
+
if (err)
|
|
2155
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2156
|
+
const result = await client.agentProbe(slug);
|
|
2157
|
+
const p = result.probe;
|
|
2158
|
+
const summary = p.ok
|
|
2159
|
+
? `✅ ${p.probe_kind ?? "probe"} OK · ${p.status_code ?? ""} · ${p.latency_ms ?? "?"}ms${p.endpoint ? ` · ${p.endpoint}` : ""}`
|
|
2160
|
+
: `❌ ${p.probe_kind ?? "probe"} failed: ${p.error ?? "no signal"}`;
|
|
2161
|
+
return { content: [{ type: "text", text: summary }] };
|
|
2162
|
+
}
|
|
2163
|
+
case "log_activity": {
|
|
2164
|
+
const err = requireSlug("log_activity");
|
|
2165
|
+
if (err)
|
|
2166
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2167
|
+
const activity = await client.logAgentActivity(slug, {
|
|
2168
|
+
type: activity_type ?? "note",
|
|
2169
|
+
payload: activity_payload,
|
|
2170
|
+
source: source ?? "mcp-agent",
|
|
2171
|
+
});
|
|
2172
|
+
return {
|
|
2173
|
+
content: [
|
|
2174
|
+
{ type: "text", text: `📝 ${activity.type} logged for ${slug} (${activity.activity_id})` },
|
|
2175
|
+
],
|
|
2176
|
+
};
|
|
2177
|
+
}
|
|
2178
|
+
case "list_activities": {
|
|
2179
|
+
const err = requireSlug("list_activities");
|
|
2180
|
+
if (err)
|
|
2181
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2182
|
+
const result = await client.listAgentActivities(slug, limit ?? 50);
|
|
2183
|
+
if (!result.activities.length) {
|
|
2184
|
+
return { content: [{ type: "text", text: `No activity for ${slug}.` }] };
|
|
2185
|
+
}
|
|
2186
|
+
const lines = result.activities.map((e) => ` ${e.ts} · ${e.type.padEnd(15)} · src=${e.source}`);
|
|
2187
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
2188
|
+
}
|
|
2189
|
+
case "import_from_mind": {
|
|
2190
|
+
const result = await client.importAgentsFromMind();
|
|
2191
|
+
if (result.error) {
|
|
2192
|
+
return {
|
|
2193
|
+
content: [{ type: "text", text: `⚠️ import-from-mind: ${result.error}` }],
|
|
2194
|
+
isError: true,
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2197
|
+
return {
|
|
2198
|
+
content: [
|
|
2199
|
+
{
|
|
2200
|
+
type: "text",
|
|
2201
|
+
text: `✅ Enriched ${result.enriched} agent(s) from MIND identity docs (${result.skipped} skipped). Slugs: ${result.matched_slugs.join(", ") || "—"}`,
|
|
2202
|
+
},
|
|
2203
|
+
],
|
|
2204
|
+
};
|
|
2205
|
+
}
|
|
2206
|
+
case "seed_known": {
|
|
2207
|
+
const result = await client.seedKnownAgents(!!overwrite);
|
|
2208
|
+
return {
|
|
2209
|
+
content: [
|
|
2210
|
+
{
|
|
2211
|
+
type: "text",
|
|
2212
|
+
text: `✅ Seed: +${result.inserted} new · ${result.updated} updated · ${result.skipped} unchanged · ${result.total_known} canonical`,
|
|
2213
|
+
},
|
|
2214
|
+
],
|
|
2215
|
+
};
|
|
2216
|
+
}
|
|
2217
|
+
case "set_status": {
|
|
2218
|
+
const err = requireSlug("set_status");
|
|
2219
|
+
if (err)
|
|
2220
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2221
|
+
if (!status) {
|
|
2222
|
+
return {
|
|
2223
|
+
content: [{ type: "text", text: "Error: 'status' is required for set_status." }],
|
|
2224
|
+
isError: true,
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
const updated = await client.updateAgent(slug, { status });
|
|
2228
|
+
return {
|
|
2229
|
+
content: [
|
|
2230
|
+
{ type: "text", text: `✅ ${updated.slug} → status=${updated.status}` },
|
|
2231
|
+
],
|
|
2232
|
+
};
|
|
2233
|
+
}
|
|
2234
|
+
case "set_current_job": {
|
|
2235
|
+
const err = requireSlug("set_current_job");
|
|
2236
|
+
if (err)
|
|
2237
|
+
return { content: [{ type: "text", text: err }], isError: true };
|
|
2238
|
+
if (current_job === undefined) {
|
|
2239
|
+
return {
|
|
2240
|
+
content: [
|
|
2241
|
+
{ type: "text", text: "Error: 'current_job' is required for set_current_job." },
|
|
2242
|
+
],
|
|
2243
|
+
isError: true,
|
|
2244
|
+
};
|
|
2245
|
+
}
|
|
2246
|
+
const updated = await client.updateAgent(slug, { current_job });
|
|
2247
|
+
return {
|
|
2248
|
+
content: [
|
|
2249
|
+
{ type: "text", text: `✅ ${updated.slug} → current_job="${updated.current_job ?? ""}"` },
|
|
2250
|
+
],
|
|
2251
|
+
};
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
catch (err) {
|
|
2256
|
+
return {
|
|
2257
|
+
content: [{ type: "text", text: `mind_agents error: ${err}` }],
|
|
2258
|
+
isError: true,
|
|
2259
|
+
};
|
|
2260
|
+
}
|
|
2261
|
+
});
|
|
1811
2262
|
return server;
|
|
1812
2263
|
}
|
|
1813
2264
|
//# sourceMappingURL=server.js.map
|