@macula-io/mcp 0.4.1 → 0.5.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.
@@ -1 +1 @@
1
- {"version":3,"file":"macula_cli.js","sourceRoot":"","sources":["../src/macula_cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"macula_cli.js","sourceRoot":"","sources":["../src/macula_cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerMeshAgents(server: McpServer): void;
@@ -0,0 +1,47 @@
1
+ // Tool: mesh_agents — a paged list of agents seen via agent.hello.
2
+ //
3
+ // Reads purely from the local roster (roster.ts) built by presence.ts's
4
+ // subscription -- no mesh round-trip, so this only ever reflects
5
+ // whoever has said hello (and this process has been running long
6
+ // enough to hear it) via mesh_hello, not "every agent on the mesh"
7
+ // universally.
8
+ import { z } from "zod";
9
+ import { identity } from "./macula_cli.js";
10
+ import { errorContent, jsonContent } from "./reply.js";
11
+ import { listAgents, pruneStale } from "./roster.js";
12
+ const DEFAULT_PAGE_SIZE = 20;
13
+ const MAX_PAGE_SIZE = 100;
14
+ /** Drop agents not heard from in this long -- generous relative to the default 60s heartbeat. */
15
+ const STALE_AFTER_SECONDS = 15 * 60;
16
+ export function registerMeshAgents(server) {
17
+ server.tool("mesh_agents", "List agents seen on the mesh via their agent.hello heartbeats (started with mesh_hello). " +
18
+ "Reads a local cache, not a live mesh query -- only reflects agents heard from while this " +
19
+ "process has been running. Sorted most-recently-seen first.", {
20
+ page: z.number().int().positive().default(1).describe("1-based page number."),
21
+ page_size: z.number().int().positive().max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),
22
+ }, async ({ page, page_size }) => {
23
+ try {
24
+ pruneStale(STALE_AFTER_SECONDS);
25
+ const { node_id: selfNodeId } = await identity();
26
+ const { total, agents } = listAgents(page, page_size);
27
+ return jsonContent({
28
+ total,
29
+ page,
30
+ page_size,
31
+ agents: agents.map((a) => ({
32
+ node_id: a.node_id,
33
+ operator_name: a.operator_name ?? undefined,
34
+ message: a.message ?? undefined,
35
+ first_seen: a.first_seen_at,
36
+ last_seen: a.last_seen_at,
37
+ seconds_since_seen: Math.round((Date.now() - Date.parse(a.last_seen_at)) / 1000),
38
+ is_self: a.node_id === selfNodeId,
39
+ })),
40
+ });
41
+ }
42
+ catch (e) {
43
+ return errorContent(e instanceof Error ? e.message : String(e));
44
+ }
45
+ });
46
+ }
47
+ //# sourceMappingURL=mesh_agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh_agents.js","sourceRoot":"","sources":["../src/mesh_agents.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,wEAAwE;AACxE,iEAAiE;AACjE,iEAAiE;AACjE,mEAAmE;AACnE,eAAe;AAGf,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,iGAAiG;AACjG,MAAM,mBAAmB,GAAG,EAAE,GAAG,EAAE,CAAC;AAEpC,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,IAAI,CACT,aAAa,EACb,2FAA2F;QACzF,2FAA2F;QAC3F,4DAA4D,EAC9D;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QAC7E,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC;KACrF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;QAC5B,IAAI,CAAC;YACH,UAAU,CAAC,mBAAmB,CAAC,CAAC;YAChC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,QAAQ,EAAE,CAAC;YACjD,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACtD,OAAO,WAAW,CAAC;gBACjB,KAAK;gBACL,IAAI;gBACJ,SAAS;gBACT,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBACzB,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,aAAa,EAAE,CAAC,CAAC,aAAa,IAAI,SAAS;oBAC3C,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,SAAS;oBAC/B,UAAU,EAAE,CAAC,CAAC,aAAa;oBAC3B,SAAS,EAAE,CAAC,CAAC,YAAY;oBACzB,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,GAAG,IAAI,CAAC;oBAChF,OAAO,EAAE,CAAC,CAAC,OAAO,KAAK,UAAU;iBAClC,CAAC,CAAC;aACJ,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,YAAY,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -59,17 +59,46 @@ commons infrastructure, not a platform you're renting.
59
59
  - Read \`mesh://identity\` before you publish or call anything, so you know
60
60
  which node ID you're acting as -- it's minted fresh per macula-mcp server
61
61
  process (not the same as running \`macula-cli\` by hand on the same
62
- machine, and not the same as mesh_watch's own separate identity).
62
+ machine, and not the same as mesh_watch's own separate identity, or
63
+ presence's own third one -- see below).
63
64
  - Don't assume continuity: a fresh Claude Code session, or a subagent with
64
- its own macula-mcp connection, is a different identity from this one.
65
+ its own macula-mcp connection, is a different identity from this one --
66
+ and by default so is the SAME session after a restart, unless
67
+ \`MACULA_MCP_IDENTITY\` pins a fixed path. This matters for presence:
68
+ \`mesh_agents\`' roster is keyed by node ID, so an unpinned identity looks
69
+ like a brand-new agent to everyone else on every restart. \`operator_name\`
70
+ is the stable, human-facing label over an identity that's often
71
+ ephemeral by design -- set it if you want to be recognizable across
72
+ restarts, don't rely on node ID for that.
73
+
74
+ ## Presence -- mesh_hello / mesh_agents / mesh_goodbye
75
+
76
+ This is the ONE deliberate exception to "one-shot subprocess, no standing
77
+ state" below. Announcing yourself on a shared mesh is a decision, not a
78
+ default:
79
+
80
+ - **Don't call \`mesh_hello\` reflexively on every connection.** It starts a
81
+ recurring heartbeat that keeps running (and keeps a station connection
82
+ open) until \`mesh_goodbye\` is called or this process exits -- call it
83
+ because you actually want to be discoverable, not as a habit.
84
+ - **Say goodbye.** \`mesh_goodbye\` removes you from other agents' rosters
85
+ immediately; without it, you just age out of their view after several
86
+ missed heartbeats. Both work, but an explicit goodbye is the polite one
87
+ when you know you're done.
88
+ - **The heartbeat interval has a floor (10s) enforced in code, not just a
89
+ suggestion** -- a wire-level guard against hammering a shared demo
90
+ station, the same spirit as the no-bool rule above.
91
+ - \`mesh_agents\` reflects who has said hello and how recently, not "every
92
+ agent on the mesh" -- treat an empty or short list as "nobody's
93
+ announced themselves yet," not "the mesh is empty."
65
94
 
66
95
  ## What this server deliberately does not do
67
96
 
68
- No standing subscriptions, no local audit log or inbox, no peer listing, no
69
- persistent state of its own beyond two throwaway identity files that die with
70
- the process. Every tool call is exactly one \`macula-cli\` subprocess: connect,
71
- do the one thing, exit. If something isn't in the tool list, it's not a gap
72
- you're missing context on -- it genuinely isn't there, on purpose.
97
+ Beyond presence's own narrow exception above: no local audit log or inbox,
98
+ no peer listing beyond \`mesh_agents\`' own hello-based roster, and every
99
+ OTHER tool call is exactly one \`macula-cli\` subprocess: connect, do the one
100
+ thing, exit. If something isn't in the tool list, it's not a gap you're
101
+ missing context on -- it genuinely isn't there, on purpose.
73
102
  `;
74
103
  export function registerEtiquette(server) {
75
104
  server.resource("mesh-etiquette", "mesh://etiquette", {
@@ -1 +1 @@
1
- {"version":3,"file":"mesh_etiquette.js","sourceRoot":"","sources":["../src/mesh_etiquette.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,wCAAwC;AACxC,EAAE;AACF,qEAAqE;AACrE,wEAAwE;AACxE,uEAAuE;AACvE,wEAAwE;AACxE,qEAAqE;AACrE,uEAAuE;AACvE,+CAA+C;AAC/C,EAAE;AACF,uEAAuE;AACvE,wEAAwE;AACxE,wEAAwE;AACxE,oEAAoE;AACpE,kDAAkD;AAIlD,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDjB,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,QAAQ,CACb,gBAAgB,EAChB,kBAAkB,EAClB;QACE,WAAW,EACT,iQAAiQ;QACnQ,QAAQ,EAAE,eAAe;KAC1B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;KAC1E,CAAC,CACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"mesh_etiquette.js","sourceRoot":"","sources":["../src/mesh_etiquette.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,wCAAwC;AACxC,EAAE;AACF,qEAAqE;AACrE,wEAAwE;AACxE,uEAAuE;AACvE,wEAAwE;AACxE,qEAAqE;AACrE,uEAAuE;AACvE,+CAA+C;AAC/C,EAAE;AACF,uEAAuE;AACvE,wEAAwE;AACxE,wEAAwE;AACxE,oEAAoE;AACpE,kDAAkD;AAIlD,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqFjB,CAAC;AAEF,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,QAAQ,CACb,gBAAgB,EAChB,kBAAkB,EAClB;QACE,WAAW,EACT,iQAAiQ;QACnQ,QAAQ,EAAE,eAAe;KAC1B,EACD,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;QACd,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;KAC1E,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerMeshGoodbye(server: McpServer): void;
@@ -0,0 +1,24 @@
1
+ // Tool: mesh_goodbye — the deliberate counterpart to mesh_hello.
2
+ //
3
+ // Publishes one agent.goodbye fact (so anyone else's roster drops this
4
+ // node immediately rather than waiting for its heartbeat to simply go
5
+ // stale), then stops the heartbeat and the durable subscriptions. A
6
+ // no-op if mesh_hello was never called.
7
+ import { describeCliError, errorContent, jsonContent } from "./reply.js";
8
+ import * as presence from "./presence.js";
9
+ export function registerMeshGoodbye(server) {
10
+ server.tool("mesh_goodbye", "Leave the mesh deliberately: publishes one agent.goodbye fact, then stops the agent.hello " +
11
+ "heartbeat and the roster subscription started by mesh_hello. No-op if mesh_hello was never called.", {}, async () => {
12
+ try {
13
+ if (!presence.isActive()) {
14
+ return jsonContent({ was_active: false, said_goodbye: false });
15
+ }
16
+ const result = await presence.stop();
17
+ return jsonContent({ was_active: true, ...result });
18
+ }
19
+ catch (e) {
20
+ return errorContent(describeCliError("mesh_goodbye failed", e));
21
+ }
22
+ });
23
+ }
24
+ //# sourceMappingURL=mesh_goodbye.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh_goodbye.js","sourceRoot":"","sources":["../src/mesh_goodbye.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,oEAAoE;AACpE,wCAAwC;AAGxC,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,cAAc,EACd,4FAA4F;QAC1F,oGAAoG,EACtG,EAAE,EACF,KAAK,IAAI,EAAE;QACT,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACzB,OAAO,WAAW,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC;YACjE,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACrC,OAAO,WAAW,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,YAAY,CAAC,gBAAgB,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerMeshHello(server: McpServer): void;
@@ -0,0 +1,73 @@
1
+ // Tool: mesh_hello — announce this agent's presence on the mesh.
2
+ //
3
+ // Deliberately explicit rather than automatic on every macula-mcp
4
+ // startup: broadcasting onto a real shared mesh (the default station
5
+ // is macula.io's public demo fleet, not a sandbox) should be something
6
+ // an agent decides to do, not a side effect of merely connecting.
7
+ //
8
+ // First call: prints a welcome banner, publishes one agent.hello
9
+ // immediately, and starts a periodic heartbeat (see presence.ts) that
10
+ // keeps republishing it -- plus a durable subscription to everyone
11
+ // else's agent.hello/agent.goodbye, feeding mesh_agents' roster. A
12
+ // later call while already active just updates operator_name/message
13
+ // for future heartbeats, without restarting anything.
14
+ import { readFileSync } from "node:fs";
15
+ import { z } from "zod";
16
+ import { defaultStation } from "./macula_cli.js";
17
+ import { describeCliError, errorContent, jsonContent } from "./reply.js";
18
+ import * as presence from "./presence.js";
19
+ const DEFAULT_BANNER = `
20
+ __ __ _____ ___ _ _ _ _
21
+ | \\/ ||_ _| / __|| | | || | /_\\
22
+ | |\\/| | | | | (__ | |_| || |__ / _ \\
23
+ |_| |_| |_| \\___| \\___/ |____/_/ \\_\\
24
+ macula mesh -- an agent just said hello
25
+ `;
26
+ function banner() {
27
+ const path = process.env.MACULA_MCP_BANNER_FILE;
28
+ if (!path)
29
+ return DEFAULT_BANNER;
30
+ try {
31
+ return readFileSync(path, "utf8");
32
+ }
33
+ catch {
34
+ return DEFAULT_BANNER; // a missing/unreadable custom banner falls back quietly, same spirit as identity's load-or-generate
35
+ }
36
+ }
37
+ export function registerMeshHello(server) {
38
+ server.tool("mesh_hello", "Announce this agent's presence on the mesh: prints a welcome banner and starts a periodic " +
39
+ "agent.hello heartbeat (default every 60s) plus a durable subscription to other agents' " +
40
+ "hellos, feeding mesh_agents' roster. Calling this again while already active just updates " +
41
+ "operator_name/message for future heartbeats. Pair with mesh_goodbye to leave deliberately.", {
42
+ operator_name: z.string().optional().describe("Customizable human-readable name for whoever's behind this agent."),
43
+ message: z.string().optional().describe("A short greeting or status, sent with every heartbeat."),
44
+ interval_seconds: z
45
+ .number()
46
+ .int()
47
+ .positive()
48
+ .optional()
49
+ .describe("Heartbeat interval in seconds (default 60, minimum 10)."),
50
+ host: z
51
+ .string()
52
+ .optional()
53
+ .describe(`Station to connect through, "host[:port]". Defaults to ${defaultStation()}.`),
54
+ }, async ({ operator_name, message, interval_seconds, host }) => {
55
+ try {
56
+ const result = await presence.start({
57
+ host,
58
+ // Explicit args win; MACULA_MCP_OPERATOR_NAME/HELLO_MESSAGE are
59
+ // an operator's standing default so an agent doesn't have to
60
+ // type them on every call, same spirit as MACULA_MCP_IDENTITY
61
+ // pinning a default elsewhere in this server.
62
+ operatorName: operator_name ?? process.env.MACULA_MCP_OPERATOR_NAME,
63
+ message: message ?? process.env.MACULA_MCP_HELLO_MESSAGE,
64
+ intervalSeconds: interval_seconds,
65
+ });
66
+ return jsonContent({ banner: banner(), ...result });
67
+ }
68
+ catch (e) {
69
+ return errorContent(describeCliError("mesh_hello failed", e));
70
+ }
71
+ });
72
+ }
73
+ //# sourceMappingURL=mesh_hello.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mesh_hello.js","sourceRoot":"","sources":["../src/mesh_hello.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,kEAAkE;AAClE,qEAAqE;AACrE,uEAAuE;AACvE,kEAAkE;AAClE,EAAE;AACF,iEAAiE;AACjE,sEAAsE;AACtE,mEAAmE;AACnE,mEAAmE;AACnE,qEAAqE;AACrE,sDAAsD;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzE,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,MAAM,cAAc,GAAG;;;;;;CAMtB,CAAC;AAEF,SAAS,MAAM;IACb,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAChD,IAAI,CAAC,IAAI;QAAE,OAAO,cAAc,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC,CAAC,oGAAoG;IAC7H,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,4FAA4F;QAC1F,yFAAyF;QACzF,4FAA4F;QAC5F,4FAA4F,EAC9F;QACE,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;QAClH,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;QACjG,gBAAgB,EAAE,CAAC;aAChB,MAAM,EAAE;aACR,GAAG,EAAE;aACL,QAAQ,EAAE;aACV,QAAQ,EAAE;aACV,QAAQ,CAAC,yDAAyD,CAAC;QACtE,IAAI,EAAE,CAAC;aACJ,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,0DAA0D,cAAc,EAAE,GAAG,CAAC;KAC3F,EACD,KAAK,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,EAAE,EAAE;QAC3D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC;gBAClC,IAAI;gBACJ,gEAAgE;gBAChE,6DAA6D;gBAC7D,8DAA8D;gBAC9D,8CAA8C;gBAC9C,YAAY,EAAE,aAAa,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB;gBACnE,OAAO,EAAE,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,wBAAwB;gBACxD,eAAe,EAAE,gBAAgB;aAClC,CAAC,CAAC;YACH,OAAO,WAAW,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,YAAY,CAAC,gBAAgB,CAAC,mBAAmB,EAAE,CAAC,CAAC,CAAC,CAAC;QAChE,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
package/dist/mesh_help.js CHANGED
@@ -10,7 +10,7 @@
10
10
  // what it already has loaded (tool descriptions, instructions,
11
11
  // mesh://etiquette), tailored to whichever topic was picked.
12
12
  //
13
- // Five separate zero-argument prompts, not one `help` prompt with an
13
+ // Six separate zero-argument prompts, not one `help` prompt with an
14
14
  // optional `topic` argument -- found live: @modelcontextprotocol/sdk
15
15
  // 1.30.0 (the latest at the time) throws "Invalid arguments ... Required"
16
16
  // on getPrompt when a prompt's args are ALL optional and the caller
@@ -28,17 +28,19 @@ const TOPICS = [
28
28
  name: "help",
29
29
  description: "Quick-start help for the Macula mesh tools in this conversation -- overview, examples, gotchas.",
30
30
  ask: "Give me a quick, example-driven overview of the Macula mesh tools available in this " +
31
- "conversation: mesh_call, mesh_put, mesh_get, mesh_publish, mesh_watch, plus the " +
32
- "mesh://identity and mesh://etiquette resources. Show one realistic example call per " +
33
- "tool and the top 3 gotchas to avoid.",
31
+ "conversation: mesh_call, mesh_put, mesh_get, mesh_publish, mesh_watch, mesh_hello, " +
32
+ "mesh_agents, mesh_goodbye, plus the mesh://identity and mesh://etiquette resources. Show " +
33
+ "one realistic example call per tool and the top 3 gotchas to avoid.",
34
34
  },
35
35
  {
36
36
  name: "help_identity",
37
37
  description: "Explain how mesh identity works in this conversation (mesh_watch vs. every other tool).",
38
38
  ask: "Explain how identity works for the Macula mesh tools in this conversation: what " +
39
- "mesh://identity shows, why mesh_watch uses a separate identity from the other tools, " +
40
- "and how to pin either one to a fixed path with MACULA_MCP_IDENTITY / " +
41
- "MACULA_MCP_WATCH_IDENTITY if a stable node ID across restarts is needed.",
39
+ "mesh://identity shows, why mesh_watch (and separately, presence -- mesh_hello/" +
40
+ "mesh_agents/mesh_goodbye) each use their own identity distinct from the other tools, " +
41
+ "and how to pin any of them to a fixed path with MACULA_MCP_IDENTITY / " +
42
+ "MACULA_MCP_WATCH_IDENTITY / MACULA_MCP_PRESENCE_IDENTITY if a stable node ID across " +
43
+ "restarts is needed.",
42
44
  },
43
45
  {
44
46
  name: "help_wire_format",
@@ -55,6 +57,19 @@ const TOPICS = [
55
57
  "issued as a second call in the same turn, and what it's actually good for (catching " +
56
58
  "facts already in flight from someone else, not synchronizing with your own send).",
57
59
  },
60
+ {
61
+ name: "help_presence",
62
+ description: "Explain mesh_hello/mesh_agents/mesh_goodbye -- what presence is for and how it persists.",
63
+ ask: "Explain the presence tools in this conversation: what mesh_hello actually starts (a " +
64
+ "periodic agent.hello heartbeat plus a durable subscription to other agents' hellos, " +
65
+ "backed by a daemon this server manages internally, not a one-shot call like every other " +
66
+ "tool here), what mesh_agents shows (a persistent SQLite roster, not an in-memory list, " +
67
+ "so it survives a restart) and how staleness/pruning works, and why mesh_goodbye matters " +
68
+ "(removes you from others' rosters immediately instead of waiting for your heartbeat to " +
69
+ "simply stop). Mention operator_name as the stable human-facing label over what's often " +
70
+ "an ephemeral node ID, and that mesh_hello shouldn't be called reflexively -- it's a " +
71
+ "deliberate decision to be discoverable, not a connection side effect.",
72
+ },
58
73
  {
59
74
  name: "help_install",
60
75
  description: "Explain how to install macula-mcp, register it, and verify it's actually working.",
@@ -1 +1 @@
1
- {"version":3,"file":"mesh_help.js","sourceRoot":"","sources":["../src/mesh_help.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,sEAAsE;AACtE,wEAAwE;AACxE,sEAAsE;AACtE,yEAAyE;AACzE,yEAAyE;AACzE,wEAAwE;AACxE,yEAAyE;AACzE,+DAA+D;AAC/D,6DAA6D;AAC7D,EAAE;AACF,qEAAqE;AACrE,qEAAqE;AACrE,0EAA0E;AAC1E,oEAAoE;AACpE,0DAA0D;AAC1D,uEAAuE;AACvE,wEAAwE;AACxE,oEAAoE;AACpE,sEAAsE;AACtE,yEAAyE;AACzE,kEAAkE;AAClE,mEAAmE;AACnE,yEAAyE;AAUzE,MAAM,MAAM,GAAgB;IAC1B;QACE,IAAI,EAAE,MAAM;QACZ,WAAW,EACT,iGAAiG;QACnG,GAAG,EACD,sFAAsF;YACtF,kFAAkF;YAClF,sFAAsF;YACtF,sCAAsC;KACzC;IACD;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,yFAAyF;QACtG,GAAG,EACD,kFAAkF;YAClF,uFAAuF;YACvF,uEAAuE;YACvE,0EAA0E;KAC7E;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,uFAAuF;QACpG,GAAG,EACD,yFAAyF;YACzF,uFAAuF;YACvF,yFAAyF;YACzF,0FAA0F;KAC7F;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,gFAAgF;QAC7F,GAAG,EACD,uFAAuF;YACvF,sFAAsF;YACtF,mFAAmF;KACtF;IACD;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,mFAAmF;QAChG,GAAG,EACD,mFAAmF;YACnF,sFAAsF;YACtF,oDAAoD;KACvD;CACF,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC5C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;YAClD,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC;SACzE,CAAC,CAAC,CAAC;IACN,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"mesh_help.js","sourceRoot":"","sources":["../src/mesh_help.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,EAAE;AACF,sEAAsE;AACtE,wEAAwE;AACxE,sEAAsE;AACtE,yEAAyE;AACzE,yEAAyE;AACzE,wEAAwE;AACxE,yEAAyE;AACzE,+DAA+D;AAC/D,6DAA6D;AAC7D,EAAE;AACF,oEAAoE;AACpE,qEAAqE;AACrE,0EAA0E;AAC1E,oEAAoE;AACpE,0DAA0D;AAC1D,uEAAuE;AACvE,wEAAwE;AACxE,oEAAoE;AACpE,sEAAsE;AACtE,yEAAyE;AACzE,kEAAkE;AAClE,mEAAmE;AACnE,yEAAyE;AAUzE,MAAM,MAAM,GAAgB;IAC1B;QACE,IAAI,EAAE,MAAM;QACZ,WAAW,EACT,iGAAiG;QACnG,GAAG,EACD,sFAAsF;YACtF,qFAAqF;YACrF,2FAA2F;YAC3F,qEAAqE;KACxE;IACD;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,yFAAyF;QACtG,GAAG,EACD,kFAAkF;YAClF,gFAAgF;YAChF,uFAAuF;YACvF,wEAAwE;YACxE,sFAAsF;YACtF,qBAAqB;KACxB;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,uFAAuF;QACpG,GAAG,EACD,yFAAyF;YACzF,uFAAuF;YACvF,yFAAyF;YACzF,0FAA0F;KAC7F;IACD;QACE,IAAI,EAAE,YAAY;QAClB,WAAW,EAAE,gFAAgF;QAC7F,GAAG,EACD,uFAAuF;YACvF,sFAAsF;YACtF,mFAAmF;KACtF;IACD;QACE,IAAI,EAAE,eAAe;QACrB,WAAW,EAAE,0FAA0F;QACvG,GAAG,EACD,sFAAsF;YACtF,sFAAsF;YACtF,0FAA0F;YAC1F,yFAAyF;YACzF,0FAA0F;YAC1F,yFAAyF;YACzF,yFAAyF;YACzF,sFAAsF;YACtF,uEAAuE;KAC1E;IACD;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EAAE,mFAAmF;QAChG,GAAG,EACD,mFAAmF;YACnF,sFAAsF;YACtF,oDAAoD;KACvD;CACF,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,MAAiB;IAC5C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC;YAClD,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC;SACzE,CAAC,CAAC,CAAC;IACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ export declare const HELLO_TOPIC = "agent.hello";
2
+ export declare const GOODBYE_TOPIC = "agent.goodbye";
3
+ export declare function isActive(): boolean;
4
+ export interface StartArgs {
5
+ host?: string;
6
+ operatorName?: string;
7
+ message?: string;
8
+ intervalSeconds?: number;
9
+ }
10
+ export interface StartResult {
11
+ node_id: string;
12
+ connected_to: string;
13
+ interval_seconds: number;
14
+ already_active: boolean;
15
+ }
16
+ /** Idempotent: a second call just updates operatorName/message for future heartbeats. */
17
+ export declare function start(args: StartArgs): Promise<StartResult>;
18
+ export interface StopResult {
19
+ said_goodbye: boolean;
20
+ }
21
+ /** Publishes agent.goodbye, then tears everything down. No-op if not active. */
22
+ export declare function stop(): Promise<StopResult>;
@@ -0,0 +1,217 @@
1
+ // Presence: this macula-mcp process's own "being on the mesh" state --
2
+ // a periodic agent.hello heartbeat, and durable subscriptions to
3
+ // agent.hello/agent.goodbye from everyone else, feeding the local
4
+ // roster (roster.ts). mesh_hello.ts/mesh_goodbye.ts/mesh_agents.ts are
5
+ // thin tool wrappers around start()/stop()/roster reads; this module
6
+ // owns the actual lifecycle.
7
+ //
8
+ // mesh_watch.ts's own doc comment explains why a standing subscription
9
+ // was deliberately NOT built before: macula-cli had no daemon, so
10
+ // "macula-mcp itself becoming a stateful daemon" was a real fork not
11
+ // taken. macula-cli has a real daemon now (serve/call/pubsub over a
12
+ // persistent connection, see its own README's Daemon mode section) --
13
+ // this module is macula-mcp finally taking that fork, scoped narrowly
14
+ // to what presence needs: one internally-managed macula-cli daemon,
15
+ // used ONLY to hold two durable subscriptions alive. The periodic
16
+ // PUBLISH side does NOT need it -- macula-cli's daemon protocol has no
17
+ // publish-via-daemon method (only call/serve/subscribe), so each
18
+ // heartbeat is an ordinary one-shot `pubsub publish`, exactly like
19
+ // mesh_publish already does.
20
+ import { randomBytes } from "node:crypto";
21
+ import { spawn } from "node:child_process";
22
+ import { binPath, defaultStation, identity, onShutdown, parseWatchLine, presenceIdentityPath, publish, MaculaCliError, } from "./macula_cli.js";
23
+ import { removeAgent, upsertAgent } from "./roster.js";
24
+ export const HELLO_TOPIC = "agent.hello";
25
+ export const GOODBYE_TOPIC = "agent.goodbye";
26
+ const DEFAULT_INTERVAL_SECONDS = 60;
27
+ /** Never let a misconfigured caller hammer a shared demo station. */
28
+ const MIN_INTERVAL_SECONDS = 10;
29
+ let state;
30
+ export function isActive() {
31
+ return state !== undefined;
32
+ }
33
+ /** Idempotent: a second call just updates operatorName/message for future heartbeats. */
34
+ export async function start(args) {
35
+ const host = args.host ?? defaultStation();
36
+ const intervalSeconds = Math.max(MIN_INTERVAL_SECONDS, args.intervalSeconds ?? DEFAULT_INTERVAL_SECONDS);
37
+ if (state) {
38
+ state.operatorName = args.operatorName ?? state.operatorName;
39
+ state.message = args.message ?? state.message;
40
+ return {
41
+ node_id: state.nodeId,
42
+ connected_to: state.host,
43
+ interval_seconds: intervalSeconds,
44
+ already_active: true,
45
+ };
46
+ }
47
+ const { node_id: nodeId } = await identity();
48
+ const socketName = `presence-${process.pid}-${randomBytes(4).toString("hex")}`;
49
+ const daemon = await startDaemon(host, socketName);
50
+ const watchers = [
51
+ watchTopic(socketName, HELLO_TOPIC, (evt) => {
52
+ const payload = evt;
53
+ const seenNodeId = typeof payload.node_id === "string" ? payload.node_id : undefined;
54
+ if (!seenNodeId)
55
+ return;
56
+ upsertAgent({
57
+ node_id: seenNodeId,
58
+ operator_name: typeof payload.operator_name === "string" ? payload.operator_name : undefined,
59
+ message: typeof payload.message === "string" ? payload.message : undefined,
60
+ at: new Date().toISOString(),
61
+ });
62
+ }),
63
+ watchTopic(socketName, GOODBYE_TOPIC, (evt) => {
64
+ const payload = evt;
65
+ if (typeof payload.node_id === "string")
66
+ removeAgent(payload.node_id);
67
+ }),
68
+ ];
69
+ const heartbeatTimer = setInterval(() => void beat(), intervalSeconds * 1000);
70
+ heartbeatTimer.unref(); // a pending heartbeat alone shouldn't keep the process alive
71
+ state = { nodeId, operatorName: args.operatorName, message: args.message, host, socketName, daemon, watchers, heartbeatTimer };
72
+ onShutdown(stopSync);
73
+ await beat(); // announce immediately rather than waiting a full interval
74
+ return { node_id: nodeId, connected_to: host, interval_seconds: intervalSeconds, already_active: false };
75
+ }
76
+ async function beat() {
77
+ if (!state)
78
+ return;
79
+ await publish({
80
+ host: state.host,
81
+ topic: HELLO_TOPIC,
82
+ fact: {
83
+ node_id: state.nodeId,
84
+ ...(state.operatorName ? { operator_name: state.operatorName } : {}),
85
+ ...(state.message ? { message: state.message } : {}),
86
+ at: new Date().toISOString(),
87
+ },
88
+ });
89
+ }
90
+ /** Publishes agent.goodbye, then tears everything down. No-op if not active. */
91
+ export async function stop() {
92
+ if (!state)
93
+ return { said_goodbye: false };
94
+ const { nodeId, host } = state;
95
+ let saidGoodbye = false;
96
+ try {
97
+ await publish({ host, topic: GOODBYE_TOPIC, fact: { node_id: nodeId, at: new Date().toISOString() } });
98
+ saidGoodbye = true;
99
+ }
100
+ catch {
101
+ // best effort -- still tear down locally even if the mesh is unreachable
102
+ }
103
+ stopSync();
104
+ return { said_goodbye: saidGoodbye };
105
+ }
106
+ /**
107
+ * Synchronous teardown only (kill child processes, clear the timer) --
108
+ * this is what onShutdown registers, since a SIGINT/SIGTERM handler
109
+ * cannot reliably wait on the async goodbye-publish above. The
110
+ * explicit stop() (mesh_goodbye) is the reliable way to leave
111
+ * gracefully; an abrupt process kill just stops heartbeating, and
112
+ * everyone else's roster ages this node out on its own via
113
+ * last_seen_at once the ordinary heartbeat stops arriving.
114
+ */
115
+ function stopSync() {
116
+ if (!state)
117
+ return;
118
+ clearInterval(state.heartbeatTimer);
119
+ state.daemon.kill();
120
+ for (const w of state.watchers)
121
+ w.kill();
122
+ state = undefined;
123
+ }
124
+ function startDaemon(host, socketName) {
125
+ return new Promise((resolve, reject) => {
126
+ const child = spawn(binPath(), [
127
+ "daemon",
128
+ "start",
129
+ "--json",
130
+ "--identity",
131
+ presenceIdentityPath(),
132
+ "-socket-name",
133
+ socketName,
134
+ host,
135
+ ]);
136
+ // daemon start --json pretty-prints its readiness envelope across
137
+ // multiple lines (report.emit's indented encoder -- the SAME shape
138
+ // every other one-shot --json command uses, unlike pubsub watch's
139
+ // deliberately single-line-per-event NDJSON). So this can't look
140
+ // for a first newline the way watchTopic does; it has to keep
141
+ // accumulating and re-attempt a parse of the WHOLE buffer until one
142
+ // succeeds, since there's no framing signal cheaper than "is this
143
+ // valid JSON yet" for a pretty-printed value of unknown length.
144
+ let buf = "";
145
+ let settled = false;
146
+ const onData = (chunk) => {
147
+ buf += chunk.toString("utf8");
148
+ let parsed;
149
+ try {
150
+ parsed = JSON.parse(buf.trim());
151
+ }
152
+ catch {
153
+ return; // not a complete JSON value yet -- wait for more chunks
154
+ }
155
+ child.stdout.off("data", onData);
156
+ settled = true;
157
+ if (parsed.ok) {
158
+ child.unref(); // see watchTopic's own comment on why
159
+ resolve(child);
160
+ }
161
+ else {
162
+ reject(new MaculaCliError(parsed.error?.message ?? "daemon start failed"));
163
+ }
164
+ };
165
+ child.stdout.on("data", onData);
166
+ child.on("error", (e) => {
167
+ if (!settled) {
168
+ settled = true;
169
+ reject(e);
170
+ }
171
+ });
172
+ child.on("exit", (code) => {
173
+ if (!settled) {
174
+ settled = true;
175
+ reject(new MaculaCliError(`daemon start exited before announcing readiness (code ${code})`));
176
+ }
177
+ });
178
+ });
179
+ }
180
+ function watchTopic(socketName, topic, onEvent) {
181
+ const child = spawn(binPath(), [
182
+ "pubsub",
183
+ "watch",
184
+ "-daemon",
185
+ "--json",
186
+ "-socket-name",
187
+ socketName,
188
+ topic,
189
+ ]);
190
+ // A held-open child process is ref'd by default and would keep this
191
+ // MCP server's Node process alive on its own even after the MCP
192
+ // client disconnects and there's nothing else left to do -- unref so
193
+ // presence is background infrastructure, not a reason to stay up.
194
+ // onShutdown's stopSync() still explicitly kills it either way.
195
+ child.unref();
196
+ let buf = "";
197
+ child.stdout.on("data", (chunk) => {
198
+ buf += chunk.toString("utf8");
199
+ let nl;
200
+ while ((nl = buf.indexOf("\n")) !== -1) {
201
+ const line = buf.slice(0, nl);
202
+ buf = buf.slice(nl + 1);
203
+ try {
204
+ const evt = parseWatchLine(line);
205
+ if (evt)
206
+ onEvent(evt.payload);
207
+ }
208
+ catch {
209
+ // a trailing failure envelope on this line -- the connection is
210
+ // presumably gone; nothing more will arrive on it, so just stop
211
+ // trying to parse further lines from this child.
212
+ }
213
+ }
214
+ });
215
+ return child;
216
+ }
217
+ //# sourceMappingURL=presence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.js","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export interface AgentRecord {
2
+ node_id: string;
3
+ operator_name: string | null;
4
+ message: string | null;
5
+ first_seen_at: string;
6
+ last_seen_at: string;
7
+ }
8
+ /** Records (or refreshes) one agent.hello sighting. Idempotent per node_id. */
9
+ export declare function upsertAgent(rec: {
10
+ node_id: string;
11
+ operator_name?: string;
12
+ message?: string;
13
+ at: string;
14
+ }): void;
15
+ /** Removes one agent immediately -- called on receiving its agent.goodbye. */
16
+ export declare function removeAgent(nodeId: string): void;
17
+ export interface RosterPage {
18
+ total: number;
19
+ agents: AgentRecord[];
20
+ }
21
+ /** Most-recently-seen first. page is 1-based. */
22
+ export declare function listAgents(page: number, pageSize: number): RosterPage;
23
+ /** Drops agents not seen in maxAgeSeconds -- lazy cleanup, not a background timer. Returns rows removed. */
24
+ export declare function pruneStale(maxAgeSeconds: number): number;
25
+ /** Test/shutdown hook -- releases the file handle. Re-opens lazily on next use. */
26
+ export declare function closeRoster(): void;