@tpsdev-ai/flair-mcp 0.13.0 → 0.15.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/dist/index.d.ts CHANGED
@@ -10,6 +10,8 @@
10
10
  * - bootstrap — cold-start context (soul + recent memories)
11
11
  * - soul_set — set a personality/context entry
12
12
  * - soul_get — get a personality/context entry
13
+ * - flair_workspace_set — write own WorkspaceState (Office Space coordination)
14
+ * - flair_orgevent — publish an OrgEvent attributed to self (no forging)
13
15
  *
14
16
  * Usage:
15
17
  * npx @tpsdev-ai/flair-mcp
package/dist/index.js CHANGED
@@ -10,6 +10,8 @@
10
10
  * - bootstrap — cold-start context (soul + recent memories)
11
11
  * - soul_set — set a personality/context entry
12
12
  * - soul_get — get a personality/context entry
13
+ * - flair_workspace_set — write own WorkspaceState (Office Space coordination)
14
+ * - flair_orgevent — publish an OrgEvent attributed to self (no forging)
13
15
  *
14
16
  * Usage:
15
17
  * npx @tpsdev-ai/flair-mcp
@@ -268,6 +270,71 @@ server.tool("soul_get", "Get a personality or project context entry.", {
268
270
  return errorResult(err, flair.url);
269
271
  }
270
272
  });
273
+ // ─── Coordination write surface ──────────────────────────────────────────────
274
+ //
275
+ // flair_workspace_set + flair_orgevent let an agent write the Office Space
276
+ // coordination layer without hand-rolling signed HTTP. Both go through
277
+ // flair.request(), which signs with the agent's Ed25519 key — so identity
278
+ // (WorkspaceState.agentId / OrgEvent.authorId) is taken from the SIGNATURE on
279
+ // the server side, NEVER the body. We deliberately do NOT send agentId/authorId
280
+ // in the body; the handlers attribute the write to the authenticated agent, so
281
+ // an agent can only write AS itself (no forging).
282
+ server.tool("flair_workspace_set", "Set your agent's current workspace state in the Office Space coordination layer (ref/branch, phase, task). Attributed to you from your signed identity — you can only write your own state.", {
283
+ ref: z.string().describe("Workspace ref — branch, worktree, or task ref"),
284
+ label: z.string().optional().describe("Human-readable label for this workspace"),
285
+ provider: z.string().optional().default("mcp").describe("Provider/runtime (e.g. claude-code, openclaw)"),
286
+ task: z.string().optional().describe("Task/issue id this workspace is attached to"),
287
+ phase: z.string().optional().describe("Current phase (e.g. design, implement, review)"),
288
+ summary: z.string().optional().describe("Short summary of current workspace state"),
289
+ }, async ({ ref, label, provider, task, phase, summary }) => {
290
+ try {
291
+ // No agentId in body — the server attributes from the signed identity.
292
+ const body = {
293
+ id: `${agentId}:${ref}`,
294
+ ref,
295
+ provider: provider ?? "mcp",
296
+ timestamp: new Date().toISOString(),
297
+ };
298
+ if (label)
299
+ body.label = label;
300
+ if (task)
301
+ body.taskId = task;
302
+ if (phase)
303
+ body.phase = phase;
304
+ if (summary)
305
+ body.summary = summary;
306
+ await flair.request("POST", "/WorkspaceState", body);
307
+ return { content: [{ type: "text", text: `Workspace state set: ref=${ref}${phase ? `, phase=${phase}` : ""} (attributed to ${agentId}).` }] };
308
+ }
309
+ catch (err) {
310
+ return errorResult(err, flair.url);
311
+ }
312
+ });
313
+ server.tool("flair_orgevent", "Publish an org-wide coordination event (claim/release/status) to the Office Space. Attributed to you from your signed identity — you cannot publish as another agent.", {
314
+ kind: z.string().describe("Event kind (e.g. coord.claim, coord.release, status)"),
315
+ summary: z.string().describe("Short summary of the event"),
316
+ detail: z.string().optional().describe("Longer detail payload"),
317
+ scope: z.string().optional().describe("Scope of the event (e.g. an agent id, repo, or 'org')"),
318
+ targets: z.array(z.string()).optional().describe("Recipient agent ids"),
319
+ }, async ({ kind, summary, detail, scope, targets }) => {
320
+ try {
321
+ // No authorId in body — the server attributes from the signed identity.
322
+ const body = { kind, summary };
323
+ if (detail)
324
+ body.detail = detail;
325
+ if (scope)
326
+ body.scope = scope;
327
+ if (targets && targets.length > 0)
328
+ body.targetIds = targets;
329
+ const result = await flair.request("POST", "/OrgEvent", body);
330
+ const targetStr = targets && targets.length > 0 ? ` → ${targets.join(", ")}` : "";
331
+ const idStr = result?.id ? ` (id: ${result.id})` : "";
332
+ return { content: [{ type: "text", text: `OrgEvent published: kind=${kind}${targetStr} (attributed to ${agentId})${idStr}.` }] };
333
+ }
334
+ catch (err) {
335
+ return errorResult(err, flair.url);
336
+ }
337
+ });
271
338
  // ─── Start ───────────────────────────────────────────────────────────────────
272
339
  const transport = new StdioServerTransport();
273
340
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tpsdev-ai/flair-mcp",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "MCP server for Flair — persistent memory for Claude Code, Cursor, and any MCP client.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@modelcontextprotocol/sdk": "1.27.1",
30
- "@tpsdev-ai/flair-client": "0.13.0",
30
+ "@tpsdev-ai/flair-client": "0.15.0",
31
31
  "zod": "4.3.6"
32
32
  },
33
33
  "license": "Apache-2.0",