@tpsdev-ai/flair-mcp 0.1.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 ADDED
@@ -0,0 +1,91 @@
1
+ # @tpsdev-ai/flair-mcp
2
+
3
+ MCP server for [Flair](https://tps.dev/#flair) — persistent memory for Claude Code, Cursor, and any MCP client.
4
+
5
+ ## Quick Start
6
+
7
+ ### Claude Code
8
+
9
+ ```bash
10
+ # Add to your project's .mcp.json
11
+ cat > .mcp.json << 'EOF'
12
+ {
13
+ "mcpServers": {
14
+ "flair": {
15
+ "command": "npx",
16
+ "args": ["@tpsdev-ai/flair-mcp"],
17
+ "env": {
18
+ "FLAIR_AGENT_ID": "my-project"
19
+ }
20
+ }
21
+ }
22
+ }
23
+ EOF
24
+ ```
25
+
26
+ Or install globally and configure once in `~/.claude/settings.json`.
27
+
28
+ ### Prerequisites
29
+
30
+ You need a running Flair instance:
31
+
32
+ ```bash
33
+ npm install -g @tpsdev-ai/flair
34
+ flair init
35
+ flair agent add my-project
36
+ ```
37
+
38
+ ## Tools
39
+
40
+ Once configured, Claude Code (or any MCP client) gets these tools:
41
+
42
+ | Tool | Description |
43
+ |------|-------------|
44
+ | `memory_search` | Semantic search across memories. Understands "what happened today". |
45
+ | `memory_store` | Save a memory with type (lesson/decision/fact) and durability. |
46
+ | `memory_get` | Retrieve a specific memory by ID. |
47
+ | `memory_delete` | Delete a memory. |
48
+ | `bootstrap` | Cold-start context — soul + recent memories in one call. |
49
+ | `soul_set` | Set personality or project context (included in every bootstrap). |
50
+ | `soul_get` | Get a personality or project context entry. |
51
+
52
+ ## Environment Variables
53
+
54
+ | Variable | Default | Description |
55
+ |----------|---------|-------------|
56
+ | `FLAIR_AGENT_ID` | *(required)* | Agent identity for memory scoping |
57
+ | `FLAIR_URL` | `http://localhost:9926` | Flair server URL |
58
+ | `FLAIR_KEY_PATH` | auto-resolved | Path to Ed25519 private key |
59
+
60
+ ## How It Works
61
+
62
+ ```
63
+ Claude Code ↔ stdio ↔ flair-mcp ↔ HTTP ↔ Flair (Harper)
64
+ ```
65
+
66
+ The MCP server is a thin wrapper around `@tpsdev-ai/flair-client`. All memory is stored in your local Flair instance with Ed25519 authentication. Nothing leaves your machine unless you point `FLAIR_URL` at a remote server.
67
+
68
+ ## Remote Flair
69
+
70
+ Point to a remote Flair instance:
71
+
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "flair": {
76
+ "command": "npx",
77
+ "args": ["@tpsdev-ai/flair-mcp"],
78
+ "env": {
79
+ "FLAIR_AGENT_ID": "my-project",
80
+ "FLAIR_URL": "http://your-server:9926"
81
+ }
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ Copy your key from the server: `scp server:~/.flair/keys/my-project.key ~/.flair/keys/`
88
+
89
+ ## License
90
+
91
+ [Apache 2.0](../../LICENSE)
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Flair MCP Server — persistent memory for Claude Code and any MCP client.
4
+ *
5
+ * Tools:
6
+ * - memory_search — semantic search across memories
7
+ * - memory_store — save a memory with type + durability
8
+ * - memory_get — retrieve a specific memory by ID
9
+ * - memory_delete — delete a memory
10
+ * - bootstrap — cold-start context (soul + recent memories)
11
+ * - soul_set — set a personality/context entry
12
+ * - soul_get — get a personality/context entry
13
+ *
14
+ * Usage:
15
+ * npx @tpsdev-ai/flair-mcp
16
+ *
17
+ * Claude Code .mcp.json:
18
+ * { "mcpServers": { "flair": { "command": "npx", "args": ["@tpsdev-ai/flair-mcp"] } } }
19
+ */
20
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Flair MCP Server — persistent memory for Claude Code and any MCP client.
4
+ *
5
+ * Tools:
6
+ * - memory_search — semantic search across memories
7
+ * - memory_store — save a memory with type + durability
8
+ * - memory_get — retrieve a specific memory by ID
9
+ * - memory_delete — delete a memory
10
+ * - bootstrap — cold-start context (soul + recent memories)
11
+ * - soul_set — set a personality/context entry
12
+ * - soul_get — get a personality/context entry
13
+ *
14
+ * Usage:
15
+ * npx @tpsdev-ai/flair-mcp
16
+ *
17
+ * Claude Code .mcp.json:
18
+ * { "mcpServers": { "flair": { "command": "npx", "args": ["@tpsdev-ai/flair-mcp"] } } }
19
+ */
20
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
21
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
22
+ import { FlairClient } from "@tpsdev-ai/flair-client";
23
+ import { z } from "zod";
24
+ // ─── Client setup ────────────────────────────────────────────────────────────
25
+ const agentId = process.env.FLAIR_AGENT_ID;
26
+ if (!agentId) {
27
+ console.error("FLAIR_AGENT_ID is required. Set it in your .mcp.json env or shell.");
28
+ process.exit(1);
29
+ }
30
+ const flair = new FlairClient({
31
+ agentId,
32
+ url: process.env.FLAIR_URL,
33
+ keyPath: process.env.FLAIR_KEY_PATH,
34
+ });
35
+ // ─── MCP Server ──────────────────────────────────────────────────────────────
36
+ const server = new McpServer({
37
+ name: "flair",
38
+ version: "0.1.0",
39
+ });
40
+ // ─── Tools ───────────────────────────────────────────────────────────────────
41
+ server.tool("memory_search", "Search memories by meaning. Understands temporal queries like 'what happened today'.", {
42
+ query: z.string().describe("Search query — natural language, semantic matching"),
43
+ limit: z.number().optional().default(5).describe("Max results (default 5)"),
44
+ }, async ({ query, limit }) => {
45
+ const results = await flair.memory.search(query, { limit });
46
+ if (results.length === 0) {
47
+ return { content: [{ type: "text", text: "No relevant memories found." }] };
48
+ }
49
+ const text = results
50
+ .map((r, i) => {
51
+ const date = r.createdAt ? r.createdAt.slice(0, 10) : "";
52
+ const meta = [date, r.type, r.durability].filter(Boolean).join(", ");
53
+ return `${i + 1}. ${r.content}${meta ? ` (${meta})` : ""}`;
54
+ })
55
+ .join("\n");
56
+ return { content: [{ type: "text", text }] };
57
+ });
58
+ server.tool("memory_store", "Save information to persistent memory. Use for lessons, decisions, preferences, facts.", {
59
+ content: z.string().describe("What to remember"),
60
+ type: z.enum(["session", "lesson", "decision", "preference", "fact", "goal"]).optional().default("session"),
61
+ durability: z.enum(["permanent", "persistent", "standard", "ephemeral"]).optional().default("standard")
62
+ .describe("permanent=inviolable, persistent=key decisions, standard=default, ephemeral=auto-expires 72h"),
63
+ tags: z.array(z.string()).optional().describe("Optional tags for categorization"),
64
+ }, async ({ content, type, durability, tags }) => {
65
+ const result = await flair.memory.write(content, {
66
+ type: type,
67
+ durability: durability,
68
+ tags,
69
+ dedup: true,
70
+ dedupThreshold: 0.7,
71
+ });
72
+ const wasDeduped = !result.id?.startsWith(`${agentId}-`);
73
+ if (wasDeduped) {
74
+ return { content: [{ type: "text", text: `Similar memory already exists (id: ${result.id}): ${result.content?.slice(0, 200)}` }] };
75
+ }
76
+ return { content: [{ type: "text", text: `Memory stored (id: ${result.id})` }] };
77
+ });
78
+ server.tool("memory_get", "Retrieve a specific memory by ID.", {
79
+ id: z.string().describe("Memory ID"),
80
+ }, async ({ id }) => {
81
+ const mem = await flair.memory.get(id);
82
+ if (!mem)
83
+ return { content: [{ type: "text", text: `Memory ${id} not found.` }] };
84
+ return { content: [{ type: "text", text: `${mem.content}\n\n(type: ${mem.type}, durability: ${mem.durability}, created: ${mem.createdAt})` }] };
85
+ });
86
+ server.tool("memory_delete", "Delete a memory by ID.", {
87
+ id: z.string().describe("Memory ID to delete"),
88
+ }, async ({ id }) => {
89
+ await flair.memory.delete(id);
90
+ return { content: [{ type: "text", text: `Memory ${id} deleted.` }] };
91
+ });
92
+ server.tool("bootstrap", "Get cold-start context: soul + recent memories. Run this at the start of every session.", {
93
+ maxTokens: z.number().optional().default(4000).describe("Max tokens in output"),
94
+ }, async ({ maxTokens }) => {
95
+ const result = await flair.bootstrap({ maxTokens });
96
+ if (!result.context) {
97
+ return { content: [{ type: "text", text: "No context available." }] };
98
+ }
99
+ return { content: [{ type: "text", text: result.context }] };
100
+ });
101
+ server.tool("soul_set", "Set a personality or project context entry. Included in every bootstrap.", {
102
+ key: z.string().describe("Entry key (e.g., 'role', 'standards', 'project')"),
103
+ value: z.string().describe("Entry value — personality trait, project context, coding standards, etc."),
104
+ }, async ({ key, value }) => {
105
+ await flair.soul.set(key, value);
106
+ return { content: [{ type: "text", text: `Soul entry '${key}' set.` }] };
107
+ });
108
+ server.tool("soul_get", "Get a personality or project context entry.", {
109
+ key: z.string().describe("Entry key"),
110
+ }, async ({ key }) => {
111
+ const entry = await flair.soul.get(key);
112
+ if (!entry)
113
+ return { content: [{ type: "text", text: `No soul entry for '${key}'.` }] };
114
+ return { content: [{ type: "text", text: entry.value }] };
115
+ });
116
+ // ─── Start ───────────────────────────────────────────────────────────────────
117
+ const transport = new StdioServerTransport();
118
+ await server.connect(transport);
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@tpsdev-ai/flair-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Flair — persistent memory for Claude Code, Cursor, and any MCP client.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "flair-mcp": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist/",
12
+ "LICENSE",
13
+ "README.md"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc --noCheck",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "engines": {
23
+ "node": ">=18"
24
+ },
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.12.1",
27
+ "@tpsdev-ai/flair-client": "^0.2.0",
28
+ "zod": "^4.3.6"
29
+ },
30
+ "license": "Apache-2.0",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/tpsdev-ai/flair.git",
34
+ "directory": "packages/flair-mcp"
35
+ },
36
+ "homepage": "https://tps.dev/#flair",
37
+ "keywords": [
38
+ "flair",
39
+ "mcp",
40
+ "claude",
41
+ "claude-code",
42
+ "cursor",
43
+ "memory",
44
+ "ai",
45
+ "agent"
46
+ ],
47
+ "devDependencies": {
48
+ "@types/node": "^24.11.0"
49
+ }
50
+ }