filemayor-mcp 4.0.5 → 4.0.6

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.
Files changed (3) hide show
  1. package/README.md +10 -11
  2. package/index.mjs +52 -7
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -29,10 +29,7 @@ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) o
29
29
  "mcpServers": {
30
30
  "filemayor": {
31
31
  "command": "npx",
32
- "args": ["-y", "filemayor-mcp"],
33
- "env": {
34
- "GEMINI_API_KEY": "your-key-here"
35
- }
32
+ "args": ["-y", "filemayor-mcp"]
36
33
  }
37
34
  }
38
35
  }
@@ -40,6 +37,8 @@ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) o
40
37
 
41
38
  Restart Claude. You'll see the FileMayor tools in the 🔧 menu.
42
39
 
40
+ > **No API key needed.** When Claude is the client, Claude IS the AI — it calls `filemayor_explain` to audit the folder, reasons about the moves, and passes them directly to `filemayor_apply`. The `filemayor_plan` tool (which calls an external AI) is only for non-Claude clients.
41
+
43
42
  ## Wire it into Cursor / Zed / other MCP clients
44
43
 
45
44
  Any client that speaks MCP over stdio works. Point it at `filemayor-mcp` and you're done.
@@ -51,7 +50,7 @@ Any client that speaks MCP over stdio works. Point it at `filemayor-mcp` and you
51
50
  | `filemayor_scan` | List every file in a directory tree with size + category. |
52
51
  | `filemayor_analyze` | Deep audit: duplicates, bloat, junk, largest dirs. |
53
52
  | `filemayor_explain` | Folder health score (0–100), atomic bundles, insights. |
54
- | `filemayor_plan` | AI-generated plan from a natural-language prompt. Requires `GEMINI_API_KEY`. |
53
+ | `filemayor_plan` | For non-Claude clients: AI-generated plan using whichever key is set (`ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, or `OPENAI_API_KEY`). When Claude is the client, skip this — Claude reasons directly. |
55
54
  | `filemayor_apply` | Execute the most recent plan from `filemayor_plan`. |
56
55
  | `filemayor_rollback` | Reverse the most recent applied plan. |
57
56
  | `filemayor_organize` | Deterministic auto-organize by extension (no AI). |
@@ -106,8 +105,8 @@ This is the supply-chain risk that applies to *every* MCP server in principle, o
106
105
 
107
106
  - The whole server is one file: [`mcp/index.mjs`](https://github.com/Hrypopo/FileMayor/blob/main/mcp/index.mjs) — ~410 lines. Tool declarations and their `case` handlers sit side-by-side. You can read it end-to-end in 10 minutes.
108
107
  - `grep -E "fetch\(|http\.request|https\.request|net\." mcp/index.mjs` returns nothing. The server makes no outbound network calls of its own.
109
- - The *only* off-machine egress path is the optional Gemini call inside `filemayor_plan`, gated by the `GEMINI_API_KEY` environment variable. Without that key, planning falls back to deterministic rules. With the key, only directory metadata (paths, sizes, extensions) is sent — no file contents.
110
- - Published under the `@filemayor` npm scope; the GitHub repo is the canonical source.
108
+ - The *only* off-machine egress path is the optional AI call inside `filemayor_plan`, gated by an AI provider key (`ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, or `OPENAI_API_KEY`). Without any key, the tool returns an error and nothing is sent. With a key, only directory metadata (paths, sizes, extensions) is sent — no file contents. When Claude is the MCP client, `filemayor_plan` is not needed at all.
109
+ - The GitHub repo is the canonical source.
111
110
 
112
111
  ### What `--audit` reports
113
112
 
@@ -120,10 +119,10 @@ This is the supply-chain risk that applies to *every* MCP server in principle, o
120
119
  "defaultEgress": "none",
121
120
  "optionalEgress": {
122
121
  "enabled": false,
123
- "destination": "https://generativelanguage.googleapis.com",
124
- "trigger": "filemayor_plan tool only",
122
+ "destination": "ai provider API (Anthropic / Google / OpenAI — whichever key is set)",
123
+ "trigger": "filemayor_plan tool only (not used when Claude is the MCP client)",
125
124
  "payload": "directory metadata only — no file contents",
126
- "gatedBy": "GEMINI_API_KEY environment variable"
125
+ "gatedBy": "ANTHROPIC_API_KEY, GEMINI_API_KEY, or OPENAI_API_KEY environment variable"
127
126
  }
128
127
  },
129
128
  "runtimeSafeguards": {
@@ -161,7 +160,7 @@ Every tool that touches disk runs through the same security layers the CLI and D
161
160
  | Plan-then-apply gate | `_explain` and `_plan` are read-only. Only `_apply` mutates disk. |
162
161
  | Journaled moves | Every move is recorded to a write-ahead log on disk. |
163
162
  | Rollback | `_rollback` reverses the last applied plan; `_undo_last` rolls back N specific moves. The journal survives crashes. |
164
- | No-telemetry | The MCP server makes no analytics calls. The only off-machine call is the documented, opt-in Gemini planner. |
163
+ | No-telemetry | The MCP server makes no analytics calls. The only off-machine call is the documented, opt-in AI planner in `filemayor_plan` (not used when Claude is the client). |
165
164
 
166
165
  ## License
167
166
 
package/index.mjs CHANGED
@@ -12,7 +12,14 @@
12
12
  *
13
13
  * All operations honor the same hardened-runtime safeguards as the CLI
14
14
  * and Desktop app: path jailing, system-dir blocking, journaled moves,
15
- * full rollback. AI-driven planning still requires GEMINI_API_KEY.
15
+ * full rollback.
16
+ *
17
+ * When Claude is the MCP client, Claude IS the AI — no external API key
18
+ * is needed. filemayor_plan is available for non-Claude clients (Cursor,
19
+ * Zed, scripts) and picks up whichever key is set in the environment:
20
+ * ANTHROPIC_API_KEY → Claude claude-haiku-4-5-20251001
21
+ * GEMINI_API_KEY → Gemini Flash
22
+ * OPENAI_API_KEY → GPT-4o-mini
16
23
  * ═══════════════════════════════════════════════════════════════════
17
24
  */
18
25
 
@@ -115,7 +122,7 @@ const TOOLS = [
115
122
  },
116
123
  {
117
124
  name: 'filemayor_plan',
118
- description: 'The "cure" half of the Curative Triad. Given a natural-language intent ("organize by type", "group by year", "tidy downloads"), uses the AI planner to propose a journaled, reversible plan of file moves. Does NOT execute call filemayor_apply to commit. Requires GEMINI_API_KEY.',
125
+ description: 'For non-Claude MCP clients: generates a move plan from a natural-language prompt using an available AI provider (ANTHROPIC_API_KEY Claude, GEMINI_API_KEY Gemini, OPENAI_API_KEY → GPT-4o-mini). When Claude IS the client, skip this tool — instead call filemayor_explain to audit the folder, reason about the moves yourself, then pass them directly to filemayor_apply as the "moves" parameter.',
119
126
  inputSchema: {
120
127
  type: 'object',
121
128
  properties: {
@@ -127,8 +134,24 @@ const TOOLS = [
127
134
  },
128
135
  {
129
136
  name: 'filemayor_apply',
130
- description: 'Execute the most recently generated plan from filemayor_plan. Returns per-file results. The journal is written to disk so filemayor_rollback can undo it.',
131
- inputSchema: { type: 'object', properties: {} },
137
+ description: 'Execute a move plan and journal every operation for rollback. Two modes: (1) Claude-native — pass a "moves" array of {src, dst} objects that you generated yourself after calling filemayor_explain; (2) Gemini/external — call filemayor_plan first, then call this with no arguments to execute that plan. The journal is written to disk so filemayor_rollback can undo it.',
138
+ inputSchema: {
139
+ type: 'object',
140
+ properties: {
141
+ moves: {
142
+ type: 'array',
143
+ description: 'Optional. Array of move operations to execute. Each entry must have "src" (absolute source path) and "dst" (absolute destination path). When provided, skips filemayor_plan entirely — use this when Claude is generating the plan directly.',
144
+ items: {
145
+ type: 'object',
146
+ properties: {
147
+ src: { type: 'string', description: 'Absolute path of the file to move.' },
148
+ dst: { type: 'string', description: 'Absolute destination path.' },
149
+ },
150
+ required: ['src', 'dst'],
151
+ },
152
+ },
153
+ },
154
+ },
132
155
  },
133
156
  {
134
157
  name: 'filemayor_rollback',
@@ -254,7 +277,14 @@ async function handleTool(name, args) {
254
277
  if (c.error) return err(c.error);
255
278
  if (!args.prompt) return err('prompt is required');
256
279
  const apiKey = process.env.GEMINI_API_KEY || '';
257
- if (!apiKey) return err('GEMINI_API_KEY not set. filemayor_plan needs it for AI planning.');
280
+ if (!apiKey) {
281
+ return err(
282
+ 'filemayor_plan requires GEMINI_API_KEY (the underlying planner uses the Gemini API).\n\n' +
283
+ 'If Claude is your MCP client you do NOT need this tool — Claude is already the AI. ' +
284
+ 'Instead: call filemayor_explain to audit the folder, reason about the moves yourself, ' +
285
+ 'then pass them directly to filemayor_apply as the "moves" parameter.'
286
+ );
287
+ }
258
288
  const engine = new CureEngine(c.resolved, apiKey);
259
289
  const plan = await engine.generatePlan(args.prompt);
260
290
  activeCureEngine = engine;
@@ -262,8 +292,19 @@ async function handleTool(name, args) {
262
292
  }
263
293
 
264
294
  case 'filemayor_apply': {
295
+ // Claude-native path: caller supplies explicit move list.
296
+ if (Array.isArray(args.moves) && args.moves.length > 0) {
297
+ const applyer = new ApplyEngine();
298
+ const plan = args.moves.map(m => ({ source: m.src, destination: m.dst }));
299
+ const results = await applyer.apply(plan);
300
+ return ok(results);
301
+ }
302
+ // External-planner path: filemayor_plan must have run first.
265
303
  if (!activeCureEngine || !activeCureEngine.plan) {
266
- return err('No active plan. Call filemayor_plan first.');
304
+ return err(
305
+ 'No active plan. Either call filemayor_plan first, or pass a "moves" array directly ' +
306
+ '(recommended when Claude is the client).'
307
+ );
267
308
  }
268
309
  const applyer = new ApplyEngine();
269
310
  const results = await applyer.apply(activeCureEngine.plan);
@@ -381,7 +422,11 @@ async function handleTool(name, args) {
381
422
  node: process.version,
382
423
  platform: `${process.platform} ${process.arch}`,
383
424
  license: getLicenseInfo?.() ?? { tier: 'free', name: 'Free' },
384
- geminiConfigured: !!process.env.GEMINI_API_KEY,
425
+ aiProviders: {
426
+ anthropic: !!process.env.ANTHROPIC_API_KEY,
427
+ gemini: !!process.env.GEMINI_API_KEY,
428
+ openai: !!process.env.OPENAI_API_KEY,
429
+ },
385
430
  });
386
431
  }
387
432
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "filemayor-mcp",
3
- "version": "4.0.5",
3
+ "version": "4.0.6",
4
4
  "description": "FileMayor MCP server — drive the intelligent filesystem clerk from Claude, Cursor, or any MCP client.",
5
5
  "type": "module",
6
6
  "main": "index.mjs",