fathom-mcp 0.6.4 → 2.0.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/index.js +154 -0
- package/package.json +10 -42
- package/CHANGELOG.md +0 -39
- package/LICENSE +0 -21
- package/README.md +0 -133
- package/fathom-agents.md +0 -45
- package/scripts/fathom-instructions.sh +0 -84
- package/scripts/fathom-precompact.sh +0 -80
- package/scripts/fathom-recall.sh +0 -194
- package/scripts/fathom-sessionstart.sh +0 -72
- package/scripts/fathom-start.sh +0 -366
- package/scripts/fathom-vsearch-background.sh +0 -46
- package/scripts/hook-toast.sh +0 -139
- package/scripts/kokoro-bridge.py +0 -196
- package/scripts/kokoro-speak.py +0 -107
- package/scripts/setup-kokoro.sh +0 -29
- package/scripts/vault-frontmatter-lint.js +0 -65
- package/src/cli.js +0 -873
- package/src/config.js +0 -137
- package/src/frontmatter.js +0 -77
- package/src/index.js +0 -552
- package/src/server-client.js +0 -303
- package/src/ws-connection.js +0 -156
package/index.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Fathom MCP server — generic adapter that reads tools from the API.
|
|
4
|
+
*
|
|
5
|
+
* Connects to any Fathom instance (self-hosted or cloud). Discovers
|
|
6
|
+
* available tools from GET /v1/tools, filtered by the token's scopes.
|
|
7
|
+
*
|
|
8
|
+
* Environment:
|
|
9
|
+
* FATHOM_API_URL — base URL (default: http://localhost:8201)
|
|
10
|
+
* FATHOM_API_KEY — bearer token from Settings → API Keys
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* npx fathom-mcp
|
|
14
|
+
* FATHOM_API_URL=https://api.hifathom.com FATHOM_API_KEY=fth_... npx fathom-mcp
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
18
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
19
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
20
|
+
|
|
21
|
+
const API_URL = (process.env.FATHOM_API_URL || "http://localhost:8201").replace(/\/$/, "");
|
|
22
|
+
const API_KEY = process.env.FATHOM_API_KEY || "";
|
|
23
|
+
|
|
24
|
+
// ── HTTP helpers ─────────────────────────────────
|
|
25
|
+
|
|
26
|
+
function authHeaders(json = true) {
|
|
27
|
+
const h = {};
|
|
28
|
+
if (json) h["Content-Type"] = "application/json";
|
|
29
|
+
if (API_KEY) h["Authorization"] = `Bearer ${API_KEY}`;
|
|
30
|
+
return h;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ── Result formatting ────────────────────────────
|
|
34
|
+
|
|
35
|
+
function formatResults(data) {
|
|
36
|
+
const items = data.results || data.deltas || (Array.isArray(data) ? data : []);
|
|
37
|
+
if (!items.length) return "No results.";
|
|
38
|
+
|
|
39
|
+
const lines = [`${items.length} results:\n`];
|
|
40
|
+
for (const raw of items) {
|
|
41
|
+
const d = raw.delta || raw;
|
|
42
|
+
const ts = (d.timestamp || "").slice(0, 16);
|
|
43
|
+
const tags = (d.tags || []).slice(0, 4).join(", ");
|
|
44
|
+
const src = d.source || "";
|
|
45
|
+
const content = (d.content || "").slice(0, 400);
|
|
46
|
+
const media = d.media_hash ? ` [image: ${d.media_hash}]` : "";
|
|
47
|
+
lines.push(`[${ts} · ${src} · ${tags}]${media}\n${content}\n`);
|
|
48
|
+
}
|
|
49
|
+
return lines.join("\n");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function formatResponse(path, method, data) {
|
|
53
|
+
if (path === "/v1/search") return formatResults(data);
|
|
54
|
+
if (path === "/v1/deltas" && method === "POST") return `Written. ID: ${data.id || "?"}`;
|
|
55
|
+
if (path === "/v1/deltas" && method === "GET") return formatResults(data);
|
|
56
|
+
if (path === "/v1/stats") {
|
|
57
|
+
return `Lake: ${data.total ?? "?"} deltas, ${data.embedded ?? "?"} embedded (${data.percent ?? "?"}% coverage)`;
|
|
58
|
+
}
|
|
59
|
+
if (path === "/v1/chat/completions") {
|
|
60
|
+
const choices = data.choices || [];
|
|
61
|
+
return choices.length ? choices[0].message?.content || "" : JSON.stringify(data).slice(0, 2000);
|
|
62
|
+
}
|
|
63
|
+
return JSON.stringify(data, null, 2).slice(0, 2000);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Tool execution ───────────────────────────────
|
|
67
|
+
|
|
68
|
+
async function executeTool(toolDef, args) {
|
|
69
|
+
const { method, path } = toolDef.endpoint;
|
|
70
|
+
const requestMap = toolDef.request_map || {};
|
|
71
|
+
|
|
72
|
+
const mapped = {};
|
|
73
|
+
for (const [k, v] of Object.entries(args)) {
|
|
74
|
+
if (v == null) continue;
|
|
75
|
+
mapped[requestMap[k] || k] = v;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let data;
|
|
79
|
+
if (method === "POST") {
|
|
80
|
+
const r = await fetch(`${API_URL}${path}`, {
|
|
81
|
+
method: "POST",
|
|
82
|
+
headers: authHeaders(true),
|
|
83
|
+
body: JSON.stringify(mapped),
|
|
84
|
+
});
|
|
85
|
+
if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
|
|
86
|
+
data = await r.json();
|
|
87
|
+
} else {
|
|
88
|
+
const params = {};
|
|
89
|
+
for (const [k, v] of Object.entries(mapped)) {
|
|
90
|
+
params[k] = Array.isArray(v) ? v.join(",") : String(v);
|
|
91
|
+
}
|
|
92
|
+
const qs = Object.keys(params).length ? "?" + new URLSearchParams(params) : "";
|
|
93
|
+
const r = await fetch(`${API_URL}${path}${qs}`, { headers: authHeaders(false) });
|
|
94
|
+
if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
|
|
95
|
+
data = await r.json();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return formatResponse(path, method, data);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ── MCP server ───────────────────────────────────
|
|
102
|
+
|
|
103
|
+
async function main() {
|
|
104
|
+
// Load tool definitions from the API
|
|
105
|
+
let tools = [];
|
|
106
|
+
try {
|
|
107
|
+
const r = await fetch(`${API_URL}/v1/tools`, { headers: authHeaders(false) });
|
|
108
|
+
if (!r.ok) throw new Error(`${r.status} ${r.statusText}`);
|
|
109
|
+
const data = await r.json();
|
|
110
|
+
tools = data.tools || [];
|
|
111
|
+
} catch (e) {
|
|
112
|
+
console.error(`Could not load tools from ${API_URL}: ${e.message}`);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Build lookup
|
|
117
|
+
const toolMap = {};
|
|
118
|
+
for (const t of tools) toolMap[t.name] = t;
|
|
119
|
+
|
|
120
|
+
const server = new Server(
|
|
121
|
+
{ name: "Fathom", version: "0.1.0" },
|
|
122
|
+
{ capabilities: { tools: {} } },
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
126
|
+
tools: tools.map(t => ({
|
|
127
|
+
name: t.name,
|
|
128
|
+
description: t.description,
|
|
129
|
+
inputSchema: t.parameters || { type: "object", properties: {} },
|
|
130
|
+
})),
|
|
131
|
+
}));
|
|
132
|
+
|
|
133
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
134
|
+
const { name, arguments: args } = request.params;
|
|
135
|
+
const toolDef = toolMap[name];
|
|
136
|
+
if (!toolDef) {
|
|
137
|
+
return { content: [{ type: "text", text: `Unknown tool: ${name}` }] };
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
const text = await executeTool(toolDef, args || {});
|
|
141
|
+
return { content: [{ type: "text", text }] };
|
|
142
|
+
} catch (e) {
|
|
143
|
+
return { content: [{ type: "text", text: `Error: ${e.message}` }] };
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const transport = new StdioServerTransport();
|
|
148
|
+
await server.connect(transport);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
main().catch(e => {
|
|
152
|
+
console.error(e);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
});
|
package/package.json
CHANGED
|
@@ -1,50 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fathom-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"type": "module",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Connect any MCP host to your Fathom memory lake",
|
|
6
5
|
"bin": {
|
|
7
|
-
"fathom-mcp": "
|
|
8
|
-
},
|
|
9
|
-
"main": "src/index.js",
|
|
10
|
-
"files": [
|
|
11
|
-
"src/",
|
|
12
|
-
"scripts/*.sh",
|
|
13
|
-
"scripts/*.py",
|
|
14
|
-
"scripts/*.js",
|
|
15
|
-
"fathom-agents.md",
|
|
16
|
-
"README.md",
|
|
17
|
-
"CHANGELOG.md",
|
|
18
|
-
"LICENSE"
|
|
19
|
-
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"start": "node src/index.js",
|
|
22
|
-
"test": "node --test 'test/*.test.js'",
|
|
23
|
-
"lint": "eslint src/ test/",
|
|
24
|
-
"lint:fix": "eslint --fix src/ test/"
|
|
6
|
+
"fathom-mcp": "./index.js"
|
|
25
7
|
},
|
|
8
|
+
"type": "module",
|
|
26
9
|
"dependencies": {
|
|
27
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
28
|
-
"js-yaml": "^4.1.0",
|
|
29
|
-
"ws": "^8.18.0"
|
|
30
|
-
},
|
|
31
|
-
"devDependencies": {
|
|
32
|
-
"@eslint/js": "^9.39.3",
|
|
33
|
-
"eslint": "^9.0.0"
|
|
34
|
-
},
|
|
35
|
-
"engines": {
|
|
36
|
-
"node": ">=18.0.0"
|
|
10
|
+
"@modelcontextprotocol/sdk": "^1.12.0"
|
|
37
11
|
},
|
|
12
|
+
"keywords": ["mcp", "fathom", "memory", "delta-lake", "claude"],
|
|
38
13
|
"license": "MIT",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
"claude",
|
|
44
|
-
"codex",
|
|
45
|
-
"gemini",
|
|
46
|
-
"opencode",
|
|
47
|
-
"ai-agent",
|
|
48
|
-
"memory"
|
|
49
|
-
]
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/fathom-ai/fathom-mcp"
|
|
17
|
+
}
|
|
50
18
|
}
|
package/CHANGELOG.md
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.5.11 (2026-03-05)
|
|
4
|
-
|
|
5
|
-
- Remove legacy `mcp/` directory (replaced by `fathom-mcp/`)
|
|
6
|
-
- Rename config dir `~/.config/fathom` → `~/.config/fathom-mcp`
|
|
7
|
-
- Update CLI installer, agents registry, start script, all path references
|
|
8
|
-
|
|
9
|
-
## 0.4.0 (2026-02-26)
|
|
10
|
-
|
|
11
|
-
- **Breaking:** removed `architecture` field everywhere — `agents` array is the only field
|
|
12
|
-
- Cleaned up all backward compatibility shims across config, server, API, and frontend
|
|
13
|
-
- Renamed `_get_architecture` → `_get_agent` in persistent session manager
|
|
14
|
-
|
|
15
|
-
## 0.3.0 (2026-02-26)
|
|
16
|
-
|
|
17
|
-
Multi-agent support.
|
|
18
|
-
|
|
19
|
-
- **Multi-agent init wizard** — auto-detects installed agents and generates per-agent MCP configs
|
|
20
|
-
- **Supported agents:** Claude Code, OpenAI Codex, Gemini CLI, OpenCode
|
|
21
|
-
- **Per-agent config writers** — `.mcp.json`, `.codex/config.toml`, `.gemini/settings.json`, `opencode.json`
|
|
22
|
-
- **Agent instructions boilerplate** — `fathom-agents.md` template for memory discipline, vault conventions, cross-workspace communication
|
|
23
|
-
- **Conditional hooks** — hook setup only for Claude Code (other agents don't support hooks)
|
|
24
|
-
- **`agents` array** in `.fathom.json` — workspace config stores which agents are configured
|
|
25
|
-
- **Server-side agent dispatch** — persistent sessions launch the correct agent CLI per workspace
|
|
26
|
-
- **Agent type registration** — init wizard sends primary agent type when registering workspace
|
|
27
|
-
- **Status command** — shows configured agents per workspace
|
|
28
|
-
|
|
29
|
-
## 0.1.0 (2026-02-25)
|
|
30
|
-
|
|
31
|
-
Initial release.
|
|
32
|
-
|
|
33
|
-
- 16 MCP tools: vault read/write/append, image ops, search (BM25/vector/hybrid), rooms, workspaces
|
|
34
|
-
- CLI: `npx fathom-mcp init` setup wizard, `npx fathom-mcp status`
|
|
35
|
-
- Config resolution: `.fathom.json` → env vars → defaults
|
|
36
|
-
- Hook scripts: SessionStart context injection, PreCompact vault snapshot
|
|
37
|
-
- Direct file I/O for vault operations (no server needed for reads/writes)
|
|
38
|
-
- HTTP client for fathom-server API (search, rooms, workspaces)
|
|
39
|
-
- API key auth support (Bearer token)
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Myra Krusemark
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
# fathom-mcp
|
|
2
|
-
|
|
3
|
-
```
|
|
4
|
-
▐▘ ▗ ▌
|
|
5
|
-
▜▘▀▌▜▘▛▌▛▌▛▛▌▄▖▛▛▌▛▘▛▌
|
|
6
|
-
▐ █▌▐▖▌▌▙▌▌▌▌ ▌▌▌▙▖▙▌
|
|
7
|
-
▌
|
|
8
|
-
|
|
9
|
-
hifathom.com · fathom@myrakrusemark.com
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
MCP server for [Fathom](https://hifathom.com) — vault operations, search, rooms, and cross-workspace communication. Works with any MCP-compatible agent.
|
|
13
|
-
|
|
14
|
-
## Supported Agents
|
|
15
|
-
|
|
16
|
-
| Agent | Config file | Auto-detected by |
|
|
17
|
-
|-------|------------|------------------|
|
|
18
|
-
| **Claude Code** | `.mcp.json` | `.claude/` directory |
|
|
19
|
-
| **OpenAI Codex** | `.codex/config.toml` | `.codex/` directory |
|
|
20
|
-
| **Gemini CLI** | `.gemini/settings.json` | `.gemini/` directory |
|
|
21
|
-
| **OpenCode** | `opencode.json` | `opencode.json` file |
|
|
22
|
-
|
|
23
|
-
The init wizard auto-detects which agents you have and generates the right config for each.
|
|
24
|
-
|
|
25
|
-
## Quick Start
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
npx fathom-mcp init
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
The wizard will:
|
|
32
|
-
1. Detect installed agents (Claude Code, Codex, Gemini, etc.)
|
|
33
|
-
2. Let you pick which ones to configure
|
|
34
|
-
3. Write per-agent MCP config files
|
|
35
|
-
4. Set up hooks (Claude Code only)
|
|
36
|
-
5. Register the workspace with your fathom-server
|
|
37
|
-
|
|
38
|
-
Restart your agent and fathom tools will be available.
|
|
39
|
-
|
|
40
|
-
## Prerequisites
|
|
41
|
-
|
|
42
|
-
- **Node.js 18+**
|
|
43
|
-
- **[fathom-server](https://github.com/myrakrusemark/fathom-vault)** running (for search, rooms, and workspace features)
|
|
44
|
-
|
|
45
|
-
## Commands
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
npx fathom-mcp # Start MCP server (stdio — used by agent configs)
|
|
49
|
-
npx fathom-mcp init # Interactive setup wizard
|
|
50
|
-
npx fathom-mcp status # Check server connection + workspace status
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Tools
|
|
54
|
-
|
|
55
|
-
### Local (direct file I/O)
|
|
56
|
-
| Tool | Description |
|
|
57
|
-
|------|-------------|
|
|
58
|
-
| `fathom_vault_read` | Read a vault file with parsed frontmatter |
|
|
59
|
-
| `fathom_vault_write` | Create or overwrite a vault file (validates frontmatter) |
|
|
60
|
-
| `fathom_vault_append` | Append to a vault file (auto-creates with frontmatter if new) |
|
|
61
|
-
| `fathom_vault_image` | Read a vault image as base64 |
|
|
62
|
-
| `fathom_vault_write_asset` | Save a base64 image to a vault folder's assets/ |
|
|
63
|
-
|
|
64
|
-
### Server (via fathom-server API)
|
|
65
|
-
| Tool | Description |
|
|
66
|
-
|------|-------------|
|
|
67
|
-
| `fathom_vault_list` | List vault folders with activity signals |
|
|
68
|
-
| `fathom_vault_folder` | List files in a folder with metadata and previews |
|
|
69
|
-
| `fathom_vault_search` | BM25 keyword search |
|
|
70
|
-
| `fathom_vault_vsearch` | Semantic/vector search |
|
|
71
|
-
| `fathom_vault_query` | Hybrid search (BM25 + vectors + reranking) |
|
|
72
|
-
| `fathom_room_post` | Post to a shared room (supports @mentions) |
|
|
73
|
-
| `fathom_room_read` | Read room messages (windowed, anchored to latest; `minutes`/`start` for pagination) |
|
|
74
|
-
| `fathom_room_list` | List all rooms |
|
|
75
|
-
| `fathom_room_describe` | Set a room's description/topic |
|
|
76
|
-
| `fathom_workspaces` | List all configured workspaces |
|
|
77
|
-
| `fathom_send` | Send a message to another workspace's agent instance |
|
|
78
|
-
|
|
79
|
-
## Configuration
|
|
80
|
-
|
|
81
|
-
### `.fathom.json`
|
|
82
|
-
|
|
83
|
-
```json
|
|
84
|
-
{
|
|
85
|
-
"workspace": "my-project",
|
|
86
|
-
"vault": "vault",
|
|
87
|
-
"server": "http://localhost:4243",
|
|
88
|
-
"apiKey": "fv_abc123...",
|
|
89
|
-
"agents": ["claude-code", "gemini"],
|
|
90
|
-
"hooks": {
|
|
91
|
-
"vault-recall": { "enabled": true },
|
|
92
|
-
"precompact-snapshot": { "enabled": true }
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Resolution order (highest priority first)
|
|
98
|
-
|
|
99
|
-
1. Environment variables: `FATHOM_SERVER_URL`, `FATHOM_API_KEY`, `FATHOM_WORKSPACE`, `FATHOM_VAULT_DIR`
|
|
100
|
-
2. `.fathom.json` (walked up from cwd to filesystem root)
|
|
101
|
-
3. Built-in defaults
|
|
102
|
-
|
|
103
|
-
## Hooks (Claude Code only)
|
|
104
|
-
|
|
105
|
-
Hooks are only available in Claude Code and are configured in `.claude/settings.local.json`.
|
|
106
|
-
|
|
107
|
-
**UserPromptSubmit** (`fathom-recall.sh`): Runs vault recall on every message — injects relevant context.
|
|
108
|
-
|
|
109
|
-
**PreCompact** (`fathom-precompact.sh`): Records which vault files were active before context compaction.
|
|
110
|
-
|
|
111
|
-
Other agents don't support hooks — they get the same MCP tools but without automatic context injection.
|
|
112
|
-
|
|
113
|
-
## Vault Frontmatter Schema
|
|
114
|
-
|
|
115
|
-
Files can optionally include YAML frontmatter:
|
|
116
|
-
|
|
117
|
-
```yaml
|
|
118
|
-
---
|
|
119
|
-
title: My Note # required (string)
|
|
120
|
-
date: 2026-02-25 # required (string, YYYY-MM-DD)
|
|
121
|
-
tags: # optional (list)
|
|
122
|
-
- research
|
|
123
|
-
- identity
|
|
124
|
-
status: draft # optional: draft | published | archived
|
|
125
|
-
project: my-project # optional (string)
|
|
126
|
-
aliases: # optional (list)
|
|
127
|
-
- alt-name
|
|
128
|
-
---
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
## License
|
|
132
|
-
|
|
133
|
-
MIT
|
package/fathom-agents.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# {{WORKSPACE_NAME}}
|
|
2
|
-
|
|
3
|
-
{{DESCRIPTION}}
|
|
4
|
-
|
|
5
|
-
## Vault
|
|
6
|
-
|
|
7
|
-
Local files live in `{{VAULT_DIR}}/`. Read, write, and edit vault files using your native file tools (`Read`, `Write`, `Edit`, `Glob`). A PostToolUse hook validates frontmatter automatically on every write.
|
|
8
|
-
|
|
9
|
-
**Folder conventions:**
|
|
10
|
-
- `research/` — reading notes, paper annotations, deep dives
|
|
11
|
-
- `thinking/` — speculative connections, insights, one file per idea
|
|
12
|
-
- `daily/` — session heartbeats and progress logs
|
|
13
|
-
|
|
14
|
-
**Frontmatter required** on `.md` files in the vault:
|
|
15
|
-
```yaml
|
|
16
|
-
---
|
|
17
|
-
title: My Note # required (string)
|
|
18
|
-
date: 2026-02-26 # required (YYYY-MM-DD)
|
|
19
|
-
tags: [research, topic] # optional
|
|
20
|
-
status: draft # optional: draft | published | archived
|
|
21
|
-
---
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
**Search** across vault files using MCP tools:
|
|
25
|
-
- `fathom_vault_search` — keyword/BM25 (fast, exact match)
|
|
26
|
-
- `fathom_vault_vsearch` — semantic/vector (conceptual similarity)
|
|
27
|
-
- `fathom_vault_query` — hybrid (most thorough, slowest)
|
|
28
|
-
|
|
29
|
-
## Cross-Workspace Communication
|
|
30
|
-
|
|
31
|
-
This workspace is part of a multi-workspace system. Other workspaces exist — you can talk to them.
|
|
32
|
-
|
|
33
|
-
- **Send a direct message:** `fathom_send workspace="other-ws" message="..."`
|
|
34
|
-
- **Post to a shared room:** `fathom_room_post room="general" message="..."`
|
|
35
|
-
- **Read room history:** `fathom_room_read room="general"`
|
|
36
|
-
- **Discover workspaces:** `fathom_workspaces`
|
|
37
|
-
|
|
38
|
-
Your sender identity is automatic — messages are tagged with `{{WORKSPACE_NAME}}`.
|
|
39
|
-
|
|
40
|
-
## Workflow
|
|
41
|
-
|
|
42
|
-
1. Research and reading notes → `vault/research/`
|
|
43
|
-
2. Speculative connections and insights → `vault/thinking/`
|
|
44
|
-
3. Session heartbeats → `vault/daily/`
|
|
45
|
-
4. When done — write what you found and what questions remain
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# SessionStart hook (Fathom) — inject MCP tool reference + notification instructions.
|
|
3
|
-
# Independent of version check — always runs.
|
|
4
|
-
# Output: JSON with hookSpecificOutput.additionalContext.
|
|
5
|
-
|
|
6
|
-
# Consume stdin (SessionStart sends JSON we don't need)
|
|
7
|
-
cat > /dev/null
|
|
8
|
-
|
|
9
|
-
read -r -d '' INSTRUCTIONS << 'FATHOM_EOF'
|
|
10
|
-
# Fathom MCP (`mcp__fathom__*` + `mcp__fathom-vault__*`)
|
|
11
|
-
|
|
12
|
-
**Load tools:** `ToolSearch query="+fathom" max_results=20`
|
|
13
|
-
|
|
14
|
-
One MCP server: `fathom-vault`. Handles search, rooms, workspaces, TTS, and routines. Vault file I/O uses Claude Code's native tools (`Read`, `Write`, `Edit`, `Glob`) — a PostToolUse hook validates frontmatter automatically.
|
|
15
|
-
|
|
16
|
-
**`mcp__fathom-vault__*` tools:**
|
|
17
|
-
|
|
18
|
-
| Tool | What it does |
|
|
19
|
-
|------|-------------|
|
|
20
|
-
| **Search** | |
|
|
21
|
-
| `fathom_vault_search` | Keyword search (BM25) across vault files — fast, start here |
|
|
22
|
-
| `fathom_vault_vsearch` | Semantic/vector search — conceptual similarity, slower |
|
|
23
|
-
| `fathom_vault_query` | Hybrid search (BM25 + vector + reranking) — most thorough |
|
|
24
|
-
| **Rooms** | |
|
|
25
|
-
| `fathom_room_post` | Post to a shared room (created on first post). Multilateral — all participants see it. Supports `@workspace` mentions and `@all`. |
|
|
26
|
-
| `fathom_room_read` | Read recent room messages (default 60min window anchored to latest). Supports `minutes`/`start` for pagination. |
|
|
27
|
-
| `fathom_room_list` | List all rooms with message count, last activity, unread counts. |
|
|
28
|
-
| `fathom_room_describe` | Set or clear a room's description/topic. |
|
|
29
|
-
| **Workspaces** | |
|
|
30
|
-
| `fathom_workspaces` | List all workspaces with running status, model, and role. |
|
|
31
|
-
| `fathom_send` | DM another workspace — stored in a shared `dm:a+b` room visible to both participants. |
|
|
32
|
-
| **Voice & TTS** | |
|
|
33
|
-
| `fathom_speak` | Generate speech (Kokoro TTS — am_echo 70% + bf_alice 30%). Returns WAV path. Optional `play=true`. |
|
|
34
|
-
| `fathom_send_voice` | Generate speech and send as a voice bubble to Myra via the app. |
|
|
35
|
-
| **Routines** | |
|
|
36
|
-
| `fathom_routine_list` | List routines with merged runtime state (next_ping_at, last_fire_at). Works cross-workspace. |
|
|
37
|
-
| `fathom_routine_fire` | Fire a routine immediately, bypassing conditions. Non-blocking. Works cross-workspace. |
|
|
38
|
-
| **Admin** | |
|
|
39
|
-
| `fathom_key_rotate` | Rotate this agent's API key. Revokes current key, issues new one, reconnects. |
|
|
40
|
-
| `policy_evaluate` | Evaluate a permission request for a tool call (called automatically by --permission-prompt-tool). |
|
|
41
|
-
|
|
42
|
-
**Image Generation (fal.ai):** Use `mcp__fal-ai__*` tools. Default model: `fal-ai/fast-sdxl/image-to-image` for img2img, `fal-ai/nano-banana-pro` for text-to-image. **Always use nano-banana-pro unless another model is specifically requested.**
|
|
43
|
-
|
|
44
|
-
**Browser:** Use `mcp__chrome-devtools__*` tools. The MCP manages Chrome automatically — just call tools directly. **Always close your pages when done** (`close_page`) so other agents can use Chrome. Only one agent can drive Chrome at a time.
|
|
45
|
-
|
|
46
|
-
**Vault structure:** See `vault/CLAUDE.md` for full folder map and what goes where.
|
|
47
|
-
|
|
48
|
-
### App Notifications (#notification room)
|
|
49
|
-
|
|
50
|
-
After posting to #general, also post a structured JSON message to `#notification` for the dashboard feed:
|
|
51
|
-
`fathom_room_post room="notification" message='{"type":"post","title":"...","body":"..."}'`
|
|
52
|
-
Types: `"post"` (findings/content), `"status"` (operational), `"content"` (linked content with `content_id`). Plain text fallback works too.
|
|
53
|
-
|
|
54
|
-
**The body field supports full HTML with inline CSS.** This is a rich rendering surface — use it. Capabilities:
|
|
55
|
-
- **Layout:** `display:flex`, `gap`, `padding`, `margin`, tables — all work. Flexbox is preferred.
|
|
56
|
-
- **Styling:** `border-radius`, `background`, `color`, `font-size`, `font-weight`, `object-fit` — all inline CSS works.
|
|
57
|
-
- **Images:** `<img src="...">` renders inline. Wrap in `<a href="..." target="_blank">` for clickable links to source. Use real CDN image URLs (grab via Chrome `evaluate_script` from product pages, paper figures, screenshots, etc.).
|
|
58
|
-
- **Links:** `<a href="..." target="_blank">` for clickable links. Link images, titles, and add explicit text links — multiple touchpoints per item.
|
|
59
|
-
- **Badges/chips:** Use inline `<span>` with background color, padding, border-radius for sale tags, status pills, warning chips.
|
|
60
|
-
- **Markdown** also works in the body for simpler notifications.
|
|
61
|
-
|
|
62
|
-
**Design your notifications to be visually rich and scannable.** Myra reads these on a dashboard — think product cards, not log entries. Each workspace should develop templates appropriate to its content (e.g., wardrobe uses product cards with images, NS uses equation summaries with paper links).
|
|
63
|
-
|
|
64
|
-
**Attachments:** To attach vault files (images, docs, audio) to a notification, add an `attachments` array. Each entry has `path` (relative to your vault) and optional `label`. The dashboard resolves types from extensions and renders images inline, audio as players, and other files as clickable chips.
|
|
65
|
-
```json
|
|
66
|
-
{"type":"content","content_id":"unique-id","title":"Title","body":"<div style=\"font-family:system-ui\">HTML here</div>","attachments":[
|
|
67
|
-
{"path":"photos/olive-top.jpg","label":"Olive button-up"},
|
|
68
|
-
{"path":"research/note-96.md","label":"Note 96: Seregin Analysis"}
|
|
69
|
-
]}
|
|
70
|
-
```
|
|
71
|
-
Supported: images (.png/.jpg/.gif/.webp), audio (.mp3/.wav/.webm), video (.mp4), documents (.pdf/.md/.txt/.csv/.json/.svg). Old `images` format still works (backward compat).
|
|
72
|
-
FATHOM_EOF
|
|
73
|
-
|
|
74
|
-
python3 -c "
|
|
75
|
-
import json, sys
|
|
76
|
-
print(json.dumps({
|
|
77
|
-
'hookSpecificOutput': {
|
|
78
|
-
'hookEventName': 'SessionStart',
|
|
79
|
-
'additionalContext': sys.argv[1]
|
|
80
|
-
}
|
|
81
|
-
}))
|
|
82
|
-
" "$INSTRUCTIONS"
|
|
83
|
-
|
|
84
|
-
exit 0
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env bash
|
|
2
|
-
# Fathom PreCompact hook — snapshots vault state before context compaction.
|
|
3
|
-
#
|
|
4
|
-
# Reads the transcript, extracts any vault file paths mentioned,
|
|
5
|
-
# and records which files were active in this session for continuity.
|
|
6
|
-
|
|
7
|
-
set -euo pipefail
|
|
8
|
-
|
|
9
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
10
|
-
TOAST="$HOOK_DIR/hook-toast.sh"
|
|
11
|
-
|
|
12
|
-
# Walk up to find .fathom.json
|
|
13
|
-
find_config() {
|
|
14
|
-
local dir="$PWD"
|
|
15
|
-
while [ "$dir" != "/" ]; do
|
|
16
|
-
if [ -f "$dir/.fathom.json" ]; then
|
|
17
|
-
echo "$dir/.fathom.json"
|
|
18
|
-
return 0
|
|
19
|
-
fi
|
|
20
|
-
dir="$(dirname "$dir")"
|
|
21
|
-
done
|
|
22
|
-
return 1
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
CONFIG_FILE=$(find_config 2>/dev/null) || exit 0
|
|
26
|
-
|
|
27
|
-
WORKSPACE=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE')).get('workspace',''))" 2>/dev/null || echo "")
|
|
28
|
-
SERVER=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE')).get('server','http://localhost:4243'))" 2>/dev/null || echo "http://localhost:4243")
|
|
29
|
-
API_KEY=$(python3 -c "import json; print(json.load(open('$CONFIG_FILE')).get('apiKey',''))" 2>/dev/null || echo "")
|
|
30
|
-
HOOK_ENABLED=$(python3 -c "import json; c=json.load(open('$CONFIG_FILE')); print(c.get('hooks',{}).get('precompact-snapshot',{}).get('enabled','true'))" 2>/dev/null || echo "true")
|
|
31
|
-
|
|
32
|
-
if [ "$HOOK_ENABLED" != "True" ] && [ "$HOOK_ENABLED" != "true" ]; then
|
|
33
|
-
exit 0
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# Toast: progress via queue (one-shot)
|
|
37
|
-
"$TOAST" fathom "⏳ Snapshotting vault..." &>/dev/null
|
|
38
|
-
|
|
39
|
-
# Read PreCompact input (contains transcript_path)
|
|
40
|
-
INPUT=$(cat)
|
|
41
|
-
TRANSCRIPT_PATH=$(echo "$INPUT" | python3 -c "import json,sys; print(json.load(sys.stdin).get('transcript_path',''))" 2>/dev/null || echo "")
|
|
42
|
-
|
|
43
|
-
if [ -z "$TRANSCRIPT_PATH" ] || [ ! -f "$TRANSCRIPT_PATH" ]; then
|
|
44
|
-
"$TOAST" fathom "✗ No transcript found" &>/dev/null
|
|
45
|
-
exit 0
|
|
46
|
-
fi
|
|
47
|
-
|
|
48
|
-
# Extract vault file paths from transcript
|
|
49
|
-
VAULT_FILES=$(grep -oP 'vault/[a-zA-Z0-9_/.-]+\.md' "$TRANSCRIPT_PATH" 2>/dev/null | sort -u || echo "")
|
|
50
|
-
|
|
51
|
-
if [ -z "$VAULT_FILES" ]; then
|
|
52
|
-
"$TOAST" fathom "✓ No vault files to record" &>/dev/null
|
|
53
|
-
exit 0
|
|
54
|
-
fi
|
|
55
|
-
|
|
56
|
-
# Notify server about accessed files (best-effort)
|
|
57
|
-
AUTH_HEADER=""
|
|
58
|
-
if [ -n "$API_KEY" ]; then
|
|
59
|
-
AUTH_HEADER="Authorization: Bearer $API_KEY"
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
for FILE in $VAULT_FILES; do
|
|
63
|
-
curl -sf -X POST -H "Content-Type: application/json" -H "$AUTH_HEADER" \
|
|
64
|
-
-d "{\"path\": \"$FILE\"}" \
|
|
65
|
-
"${SERVER}/api/vault/access?workspace=${WORKSPACE}" >/dev/null 2>&1 || true
|
|
66
|
-
done
|
|
67
|
-
|
|
68
|
-
# Output summary
|
|
69
|
-
FILE_COUNT=$(echo "$VAULT_FILES" | wc -l)
|
|
70
|
-
|
|
71
|
-
# Toast: done
|
|
72
|
-
"$TOAST" fathom "✓ Stored ${FILE_COUNT} vault file(s)" &>/dev/null
|
|
73
|
-
|
|
74
|
-
python3 -c "
|
|
75
|
-
import json, sys
|
|
76
|
-
result = {
|
|
77
|
-
'systemMessage': 'Fathom: Recorded ${FILE_COUNT} vault file(s) from this session.'
|
|
78
|
-
}
|
|
79
|
-
json.dump(result, sys.stdout)
|
|
80
|
-
"
|