faf-mcp 2.2.1 → 2.3.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.
@@ -57,6 +57,28 @@ const path_resolver_1 = require("../utils/path-resolver");
57
57
  // rationale and the linked tracked issue.
58
58
  const faf_cli_bridge_js_1 = require("../utils/faf-cli-bridge.js");
59
59
  const turbocat_bridge_js_1 = require("../faf-core/extract/turbocat-bridge.js");
60
+ /**
61
+ * The Core tier — the 15 distinct, well-described tools advertised by default.
62
+ * Everything else is Extended: still callable by name (the dispatch in callTool
63
+ * is unchanged), but advertised only when FAF_TOOLS=all (or FAF_EXTENDED=1).
64
+ * Glama (and any client) runs the server and scores the default tools/list, so a
65
+ * tight, non-overlapping, craft-grade Core is what earns the quality grade —
66
+ * the 40%-MIN rule means one weak tool on the surface caps the whole server.
67
+ *
68
+ * Spine mirrors claude-faf-mcp's proven-A Core; the interop quad
69
+ * (faf_bi_sync + faf_agents/faf_cursor/faf_gemini) is this edition's identity —
70
+ * the Cursor / IDE multi-format sync — where CFM carries memory tools instead.
71
+ * See PLANET-FAF/strategy/claude-faf-mcp-core-tier-glama-a-2026-06-17.md.
72
+ */
73
+ const CORE_TOOLS = new Set([
74
+ // Spine — mirrors CFM
75
+ 'faf_init', 'faf_auto', 'faf_go', 'faf_score', 'faf_doctor',
76
+ 'faf_sync', 'faf_context', 'faf_trust', 'faf_about',
77
+ // IDE-edition interop — the differentiator
78
+ 'faf_bi_sync', 'faf_agents', 'faf_cursor', 'faf_gemini',
79
+ // Craft-grade utility
80
+ 'faf_check', 'faf_git',
81
+ ]);
60
82
  class FafToolHandler {
61
83
  engineAdapter;
62
84
  constructor(engineAdapter) {
@@ -85,609 +107,572 @@ class FafToolHandler {
85
107
  return this.engineAdapter.getWorkingDirectory();
86
108
  }
87
109
  async listTools() {
88
- return {
89
- tools: [
90
- {
91
- name: 'faf_about',
92
- description: 'Learn what .faf format is - project DNA for AI 🧡⚡️',
93
- annotations: {
94
- title: 'About FAF',
95
- readOnlyHint: true,
96
- openWorldHint: false
97
- },
98
- inputSchema: {
99
- type: 'object',
100
- properties: {},
101
- additionalProperties: false
102
- }
110
+ const allTools = [
111
+ {
112
+ name: 'faf_about',
113
+ description: 'Explain what the .faf format is — the IANA-registered, portable context file (application/vnd.faf+yaml) that gives any AI instant project understanding. Returns a plain-language overview of the format and its purpose. Use this when you or the user are new to FAF and want the concept before running other tools.',
114
+ annotations: {
115
+ title: 'About FAF',
116
+ readOnlyHint: true,
117
+ openWorldHint: false
103
118
  },
104
- {
105
- name: 'faf_what',
106
- description: 'What is .faf format? Quick explanation of project DNA for AI 🧡⚡️',
107
- annotations: {
108
- title: 'What is FAF',
109
- readOnlyHint: true,
110
- openWorldHint: false
111
- },
112
- inputSchema: {
113
- type: 'object',
114
- properties: {},
115
- additionalProperties: false
116
- }
119
+ inputSchema: {
120
+ type: 'object',
121
+ properties: {},
122
+ additionalProperties: false
123
+ }
124
+ },
125
+ {
126
+ name: 'faf_what',
127
+ description: 'What is .faf format? Quick explanation of project DNA for AI',
128
+ annotations: {
129
+ title: 'What is FAF',
130
+ readOnlyHint: true,
131
+ openWorldHint: false
117
132
  },
118
- {
119
- name: 'faf_status',
120
- description: 'Check if your project has project.faf (project DNA for AI) - Shows AI-readability status 🧡⚡️',
121
- annotations: {
122
- title: 'Project Status',
123
- readOnlyHint: true,
124
- openWorldHint: false
125
- },
126
- inputSchema: {
127
- type: 'object',
128
- properties: {
129
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
130
- },
131
- additionalProperties: false
132
- }
133
+ inputSchema: {
134
+ type: 'object',
135
+ properties: {},
136
+ additionalProperties: false
137
+ }
138
+ },
139
+ {
140
+ name: 'faf_status',
141
+ description: 'Check if your project has project.faf (project DNA for AI) - Shows AI-readability status',
142
+ annotations: {
143
+ title: 'Project Status',
144
+ readOnlyHint: true,
145
+ openWorldHint: false
133
146
  },
134
- {
135
- name: 'faf_score',
136
- description: 'Calculate your project\'s AI-readability from project.faf (project DNA for AI) - F1-inspired metrics! 🧡⚡️',
137
- annotations: {
138
- title: 'AI-Readiness Score',
139
- readOnlyHint: true,
140
- openWorldHint: false
147
+ inputSchema: {
148
+ type: 'object',
149
+ properties: {
150
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
141
151
  },
142
- inputSchema: {
143
- type: 'object',
144
- properties: {
145
- details: { type: 'boolean', description: 'Include detailed breakdown and improvement suggestions' },
146
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
147
- },
148
- additionalProperties: false
149
- }
152
+ additionalProperties: false
153
+ }
154
+ },
155
+ {
156
+ name: 'faf_score',
157
+ description: 'Calculate a project.faf AI-readiness score (0-100%) from the populated context slots. Returns the percentage and tier, and with details a slot-by-slot breakdown with improvement suggestions. Use this to measure how complete the AI context is and what to fill next.',
158
+ annotations: {
159
+ title: 'AI-Readiness Score',
160
+ readOnlyHint: true,
161
+ openWorldHint: false
150
162
  },
151
- {
152
- name: 'faf_init',
153
- description: 'Create project.faf (project DNA for AI) - Makes your project instantly AI-readable 🧡⚡️. Just enter path or project name. Examples: ~/Projects/my-app, my-app, /full/path/to/project',
154
- annotations: {
155
- title: 'Initialize .faf',
156
- readOnlyHint: false,
157
- destructiveHint: false,
158
- openWorldHint: false
163
+ inputSchema: {
164
+ type: 'object',
165
+ properties: {
166
+ details: { type: 'boolean', description: 'Include detailed breakdown and improvement suggestions' },
167
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
159
168
  },
160
- inputSchema: {
161
- type: 'object',
162
- properties: {
163
- path: {
164
- type: 'string',
165
- description: 'Project path or name. Smart resolution: "my-app" finds ~/Projects/my-app OR ~/Code/my-app. Full paths like ~/Projects/app or /Users/me/code/app work too. Omit to use current directory.'
166
- },
167
- force: { type: 'boolean', description: 'Overwrite existing project.faf if it exists' }
168
- },
169
- additionalProperties: false
170
- }
169
+ additionalProperties: false
170
+ }
171
+ },
172
+ {
173
+ name: 'faf_init',
174
+ description: 'Create a project.faf for a project, making it instantly AI-readable. Returns the new file location and starting score. Accepts a path or bare project name (e.g. ~/Projects/my-app, my-app) and omitting it uses the current directory.',
175
+ annotations: {
176
+ title: 'Initialize .faf',
177
+ readOnlyHint: false,
178
+ destructiveHint: false,
179
+ openWorldHint: false
171
180
  },
172
- {
173
- name: 'faf_trust',
174
- description: 'Validate project.faf integrity - Trust metrics for project DNA for AI 🧡⚡️',
175
- annotations: {
176
- title: 'Trust Score',
177
- readOnlyHint: true,
178
- openWorldHint: false
181
+ inputSchema: {
182
+ type: 'object',
183
+ properties: {
184
+ path: {
185
+ type: 'string',
186
+ description: 'Project path or name. Smart resolution: "my-app" finds ~/Projects/my-app OR ~/Code/my-app. Full paths like ~/Projects/app or /Users/me/code/app work too. Omit to use current directory.'
187
+ },
188
+ force: { type: 'boolean', description: 'Overwrite existing project.faf if it exists' }
179
189
  },
180
- inputSchema: {
181
- type: 'object',
182
- properties: {},
183
- additionalProperties: false
184
- }
190
+ additionalProperties: false
191
+ }
192
+ },
193
+ {
194
+ name: 'faf_trust',
195
+ description: 'Validate a project.faf for structural integrity and field consistency. Returns trust metrics flagging malformed, missing, or contradictory data. Use this to confirm the context is sound before relying on it or syncing it to other formats.',
196
+ annotations: {
197
+ title: 'Trust Score',
198
+ readOnlyHint: true,
199
+ openWorldHint: false
185
200
  },
186
- {
187
- name: 'faf_sync',
188
- description: 'Sync project.faf (project DNA for AI) with CLAUDE.md - Bi-directional context 🧡⚡️',
189
- annotations: {
190
- title: 'Sync .faf to CLAUDE.md',
191
- readOnlyHint: false,
192
- destructiveHint: false,
193
- openWorldHint: false
194
- },
195
- inputSchema: {
196
- type: 'object',
197
- properties: {
198
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
199
- },
200
- additionalProperties: false
201
- }
201
+ inputSchema: {
202
+ type: 'object',
203
+ properties: {},
204
+ additionalProperties: false
205
+ }
206
+ },
207
+ {
208
+ name: 'faf_sync',
209
+ description: 'Sync a project.faf with CLAUDE.md so the two stay aligned. Returns what was written. Use this for the single CLAUDE.md target; use faf_bi_sync to fan out to AGENTS.md, .cursorrules, and GEMINI.md as well.',
210
+ annotations: {
211
+ title: 'Sync .faf to CLAUDE.md',
212
+ readOnlyHint: false,
213
+ destructiveHint: false,
214
+ openWorldHint: false
202
215
  },
203
- {
204
- name: 'faf_enhance',
205
- description: 'Enhance project.faf (project DNA for AI) with AI optimization - SPEEDY AI you can TRUST! 🧡⚡️',
206
- annotations: {
207
- title: 'Enhance .faf',
208
- readOnlyHint: false,
209
- destructiveHint: false,
210
- openWorldHint: false
216
+ inputSchema: {
217
+ type: 'object',
218
+ properties: {
219
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
211
220
  },
212
- inputSchema: {
213
- type: 'object',
214
- properties: {
215
- model: { type: 'string', description: 'Target AI model: claude|chatgpt|gemini|universal (default: claude)' },
216
- focus: { type: 'string', description: 'Enhancement focus: claude-optimal|human-context|ai-instructions|completeness' },
217
- consensus: { type: 'boolean', description: 'Build consensus from multiple AI models' },
218
- dryRun: { type: 'boolean', description: 'Preview enhancement without applying changes' },
219
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
220
- },
221
- additionalProperties: false
222
- }
221
+ additionalProperties: false
222
+ }
223
+ },
224
+ {
225
+ name: 'faf_bi_sync',
226
+ description: 'Bi-directionally sync a project.faf with CLAUDE.md and, with the format flags or all, also AGENTS.md, .cursorrules, and GEMINI.md. Returns the formats written and any conflicts. Use this to keep every AI tool context file aligned from the single .faf source.',
227
+ annotations: {
228
+ title: 'Bi-directional Sync',
229
+ readOnlyHint: false,
230
+ destructiveHint: false,
231
+ openWorldHint: false
223
232
  },
224
- {
225
- name: 'faf_bi_sync',
226
- description: 'Bi-directional sync between project.faf and CLAUDE.md. v4.5.0: Also sync to AGENTS.md, .cursorrules, GEMINI.md!',
227
- annotations: {
228
- title: 'Bi-directional Sync',
229
- readOnlyHint: false,
230
- destructiveHint: false,
231
- openWorldHint: false
233
+ inputSchema: {
234
+ type: 'object',
235
+ properties: {
236
+ auto: { type: 'boolean', description: 'Enable automatic synchronization' },
237
+ watch: { type: 'boolean', description: 'Start real-time file watching for changes' },
238
+ force: { type: 'boolean', description: 'Force overwrite conflicting changes' },
239
+ agents: { type: 'boolean', description: 'Also sync to AGENTS.md (OpenAI/Codex format)' },
240
+ cursor: { type: 'boolean', description: 'Also sync to .cursorrules (Cursor IDE format)' },
241
+ gemini: { type: 'boolean', description: 'Also sync to GEMINI.md (Google Gemini format)' },
242
+ all: { type: 'boolean', description: 'Sync to ALL formats: CLAUDE.md + AGENTS.md + .cursorrules + GEMINI.md' },
243
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
232
244
  },
233
- inputSchema: {
234
- type: 'object',
235
- properties: {
236
- auto: { type: 'boolean', description: 'Enable automatic synchronization' },
237
- watch: { type: 'boolean', description: 'Start real-time file watching for changes' },
238
- force: { type: 'boolean', description: 'Force overwrite conflicting changes' },
239
- agents: { type: 'boolean', description: 'Also sync to AGENTS.md (OpenAI/Codex format)' },
240
- cursor: { type: 'boolean', description: 'Also sync to .cursorrules (Cursor IDE format)' },
241
- gemini: { type: 'boolean', description: 'Also sync to GEMINI.md (Google Gemini format)' },
242
- all: { type: 'boolean', description: 'Sync to ALL formats: CLAUDE.md + AGENTS.md + .cursorrules + GEMINI.md' },
243
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
244
- },
245
- additionalProperties: false
246
- }
245
+ additionalProperties: false
246
+ }
247
+ },
248
+ {
249
+ name: 'faf_clear',
250
+ description: 'Clear caches, temporary files, and reset FAF state for a fresh start',
251
+ annotations: {
252
+ title: 'Clear .faf Data',
253
+ readOnlyHint: false,
254
+ destructiveHint: true,
255
+ openWorldHint: false
247
256
  },
248
- {
249
- name: 'faf_clear',
250
- description: 'Clear caches, temporary files, and reset FAF state for a fresh start',
251
- annotations: {
252
- title: 'Clear .faf Data',
253
- readOnlyHint: false,
254
- destructiveHint: true,
255
- openWorldHint: false
257
+ inputSchema: {
258
+ type: 'object',
259
+ properties: {
260
+ cache: { type: 'boolean', description: 'Clear trust cache only' },
261
+ todos: { type: 'boolean', description: 'Clear todo lists only' },
262
+ backups: { type: 'boolean', description: 'Clear backup files only' },
263
+ all: { type: 'boolean', description: 'Clear everything (default)' }
256
264
  },
257
- inputSchema: {
258
- type: 'object',
259
- properties: {
260
- cache: { type: 'boolean', description: 'Clear trust cache only' },
261
- todos: { type: 'boolean', description: 'Clear todo lists only' },
262
- backups: { type: 'boolean', description: 'Clear backup files only' },
263
- all: { type: 'boolean', description: 'Clear everything (default)' }
264
- },
265
- additionalProperties: false
266
- }
265
+ additionalProperties: false
266
+ }
267
+ },
268
+ {
269
+ name: 'faf_debug',
270
+ description: 'Debug faf-mcp environment - show working directory, permissions, and FAF CLI status',
271
+ annotations: {
272
+ title: 'Debug Info',
273
+ readOnlyHint: true,
274
+ openWorldHint: false
267
275
  },
268
- {
269
- name: 'faf_debug',
270
- description: 'Debug faf-mcp environment - show working directory, permissions, and FAF CLI status',
271
- annotations: {
272
- title: 'Debug Info',
273
- readOnlyHint: true,
274
- openWorldHint: false
275
- },
276
- inputSchema: {
277
- type: 'object',
278
- properties: {},
279
- additionalProperties: false
280
- }
276
+ inputSchema: {
277
+ type: 'object',
278
+ properties: {},
279
+ additionalProperties: false
280
+ }
281
+ },
282
+ {
283
+ name: 'faf_read',
284
+ description: 'Read a file within the project root (cwd / FAF_ALLOWED_ROOTS). Paths that escape the project are refused.',
285
+ annotations: {
286
+ title: 'Read .faf File',
287
+ readOnlyHint: true,
288
+ openWorldHint: false
281
289
  },
282
- {
283
- name: 'faf_read',
284
- description: 'Read a file within the project root (cwd / FAF_ALLOWED_ROOTS). Paths that escape the project are refused.',
285
- annotations: {
286
- title: 'Read .faf File',
287
- readOnlyHint: true,
288
- openWorldHint: false
290
+ inputSchema: {
291
+ type: 'object',
292
+ properties: {
293
+ path: {
294
+ type: 'string',
295
+ description: 'Absolute or relative file path to read'
296
+ }
289
297
  },
290
- inputSchema: {
291
- type: 'object',
292
- properties: {
293
- path: {
294
- type: 'string',
295
- description: 'Absolute or relative file path to read'
296
- }
297
- },
298
- required: ['path'],
299
- additionalProperties: false
300
- }
298
+ required: ['path'],
299
+ additionalProperties: false
300
+ }
301
+ },
302
+ {
303
+ name: 'faf_write',
304
+ description: 'Write a file within the project root (cwd / FAF_ALLOWED_ROOTS). Paths that escape the project are refused.',
305
+ annotations: {
306
+ title: 'Write .faf File',
307
+ readOnlyHint: false,
308
+ destructiveHint: false,
309
+ openWorldHint: false
301
310
  },
302
- {
303
- name: 'faf_write',
304
- description: 'Write a file within the project root (cwd / FAF_ALLOWED_ROOTS). Paths that escape the project are refused.',
305
- annotations: {
306
- title: 'Write .faf File',
307
- readOnlyHint: false,
308
- destructiveHint: false,
309
- openWorldHint: false
310
- },
311
- inputSchema: {
312
- type: 'object',
313
- properties: {
314
- path: {
315
- type: 'string',
316
- description: 'Absolute or relative file path to write'
317
- },
318
- content: {
319
- type: 'string',
320
- description: 'Content to write to the file'
321
- }
311
+ inputSchema: {
312
+ type: 'object',
313
+ properties: {
314
+ path: {
315
+ type: 'string',
316
+ description: 'Absolute or relative file path to write'
322
317
  },
323
- required: ['path', 'content'],
324
- additionalProperties: false
325
- }
326
- },
327
- {
328
- name: 'faf_list',
329
- description: 'List directories and discover projects with project.faf files - Essential for FAF discovery workflow',
330
- annotations: {
331
- title: 'List .faf Files',
332
- readOnlyHint: true,
333
- openWorldHint: false
318
+ content: {
319
+ type: 'string',
320
+ description: 'Content to write to the file'
321
+ }
334
322
  },
335
- inputSchema: {
336
- type: 'object',
337
- properties: {
338
- path: {
339
- type: 'string',
340
- description: 'Directory path to list (e.g., ~/Projects, /Users/username/Projects)'
341
- },
342
- filter: {
343
- type: 'string',
344
- enum: ['faf', 'dirs', 'all'],
345
- description: 'Filter: "faf" (only dirs with project.faf), "dirs" (all directories), "all" (dirs and files). Default: "dirs"'
346
- },
347
- depth: {
348
- type: 'number',
349
- enum: [1, 2],
350
- description: 'Directory depth to scan: 1 (immediate children) or 2 (one level deeper). Default: 1'
351
- },
352
- showHidden: {
353
- type: 'boolean',
354
- description: 'Show hidden files/directories (starting with .). Default: false'
355
- }
356
- },
357
- required: ['path'],
358
- additionalProperties: false
359
- }
323
+ required: ['path', 'content'],
324
+ additionalProperties: false
325
+ }
326
+ },
327
+ {
328
+ name: 'faf_list',
329
+ description: 'List directories and discover projects with project.faf files - Essential for FAF discovery workflow',
330
+ annotations: {
331
+ title: 'List .faf Files',
332
+ readOnlyHint: true,
333
+ openWorldHint: false
360
334
  },
361
- // faf_chat — DEPRECATED, un-advertised. The host IS the chat — a chat-shim
362
- // tool is redundant. Dispatch keeps a deprecation stub (below). Fleet sweep —
363
- // mirrors grok-faf-mcp + claude-faf-mcp's retire.
364
- {
365
- name: 'faf_friday',
366
- description: '🎉 Friday Features - Chrome Extension detection, fuzzy matching & more! 🧡⚡️',
367
- annotations: {
368
- title: 'Fun FAF Facts',
369
- readOnlyHint: true,
370
- openWorldHint: false
371
- },
372
- inputSchema: {
373
- type: 'object',
374
- properties: {
375
- test: {
376
- type: 'string',
377
- description: 'Test fuzzy matching with typos like "raect" or "chr ext"'
378
- }
335
+ inputSchema: {
336
+ type: 'object',
337
+ properties: {
338
+ path: {
339
+ type: 'string',
340
+ description: 'Directory path to list (e.g., ~/Projects, /Users/username/Projects)'
379
341
  },
380
- additionalProperties: false
381
- }
382
- },
383
- {
384
- name: 'faf_guide',
385
- description: 'FAF MCP usage guide for your MCP host - Projects convention, path resolution, and UX patterns',
386
- annotations: {
387
- title: 'Usage Guide',
388
- readOnlyHint: true,
389
- openWorldHint: false
342
+ filter: {
343
+ type: 'string',
344
+ enum: ['faf', 'dirs', 'all'],
345
+ description: 'Filter: "faf" (only dirs with project.faf), "dirs" (all directories), "all" (dirs and files). Default: "dirs"'
346
+ },
347
+ depth: {
348
+ type: 'number',
349
+ enum: [1, 2],
350
+ description: 'Directory depth to scan: 1 (immediate children) or 2 (one level deeper). Default: 1'
351
+ },
352
+ showHidden: {
353
+ type: 'boolean',
354
+ description: 'Show hidden files/directories (starting with .). Default: false'
355
+ }
390
356
  },
391
- inputSchema: {
392
- type: 'object',
393
- properties: {},
394
- additionalProperties: false
395
- }
357
+ required: ['path'],
358
+ additionalProperties: false
359
+ }
360
+ },
361
+ // faf_chat — DEPRECATED, un-advertised. The host IS the chat — a chat-shim
362
+ // tool is redundant. Dispatch keeps a deprecation stub (below). Fleet sweep —
363
+ {
364
+ name: 'faf_guide',
365
+ description: 'FAF MCP usage guide for your MCP host - Projects convention, path resolution, and UX patterns',
366
+ annotations: {
367
+ title: 'Usage Guide',
368
+ readOnlyHint: true,
369
+ openWorldHint: false
396
370
  },
397
- {
398
- name: 'faf_readme',
399
- description: '📖 Extract 6 Ws (Who/What/Why/Where/When/How) from README.md into human_context - Smart pattern matching 🧡⚡️',
400
- annotations: {
401
- title: 'Extract from README',
402
- readOnlyHint: false,
403
- destructiveHint: false,
404
- openWorldHint: false
405
- },
406
- inputSchema: {
407
- type: 'object',
408
- properties: {
409
- apply: { type: 'boolean', description: 'Apply extracted content to project.faf (default: preview only)' },
410
- force: { type: 'boolean', description: 'Overwrite existing human_context values (default: only fill empty slots)' },
411
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
412
- },
413
- additionalProperties: false
414
- }
371
+ inputSchema: {
372
+ type: 'object',
373
+ properties: {},
374
+ additionalProperties: false
375
+ }
376
+ },
377
+ {
378
+ name: 'faf_readme',
379
+ description: 'Extract 6 Ws (Who/What/Why/Where/When/How) from README.md into human_context - Smart pattern matching',
380
+ annotations: {
381
+ title: 'Extract from README',
382
+ readOnlyHint: false,
383
+ destructiveHint: false,
384
+ openWorldHint: false
415
385
  },
416
- {
417
- name: 'faf_human_add',
418
- description: '🧡 Add a human_context field (who/what/why/where/when/how) - Non-interactive for MCP 🧡⚡️',
419
- annotations: {
420
- title: 'Add Human Context',
421
- readOnlyHint: false,
422
- destructiveHint: false,
423
- openWorldHint: false
386
+ inputSchema: {
387
+ type: 'object',
388
+ properties: {
389
+ apply: { type: 'boolean', description: 'Apply extracted content to project.faf (default: preview only)' },
390
+ force: { type: 'boolean', description: 'Overwrite existing human_context values (default: only fill empty slots)' },
391
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
424
392
  },
425
- inputSchema: {
426
- type: 'object',
427
- properties: {
428
- field: {
429
- type: 'string',
430
- enum: ['who', 'what', 'why', 'where', 'when', 'how'],
431
- description: 'The 6 W field to set'
432
- },
433
- value: { type: 'string', description: 'The value to set for the field' },
434
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
435
- },
436
- required: ['field', 'value'],
437
- additionalProperties: false
438
- }
393
+ additionalProperties: false
394
+ }
395
+ },
396
+ {
397
+ name: 'faf_human_add',
398
+ description: 'Add a human_context field (who/what/why/where/when/how) - Non-interactive for MCP',
399
+ annotations: {
400
+ title: 'Add Human Context',
401
+ readOnlyHint: false,
402
+ destructiveHint: false,
403
+ openWorldHint: false
439
404
  },
440
- {
441
- name: 'faf_check',
442
- description: '🔍 Quality inspection for human_context fields + field protection - Shows empty/generic/good/excellent ratings 🧡⚡️',
443
- annotations: {
444
- title: 'Check .faf Health',
445
- readOnlyHint: true,
446
- openWorldHint: false
447
- },
448
- inputSchema: {
449
- type: 'object',
450
- properties: {
451
- protect: { type: 'boolean', description: 'Lock good/excellent fields from being overwritten' },
452
- unlock: { type: 'boolean', description: 'Remove all field protections' },
453
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
405
+ inputSchema: {
406
+ type: 'object',
407
+ properties: {
408
+ field: {
409
+ type: 'string',
410
+ enum: ['who', 'what', 'why', 'where', 'when', 'how'],
411
+ description: 'The 6 W field to set'
454
412
  },
455
- additionalProperties: false
456
- }
413
+ value: { type: 'string', description: 'The value to set for the field' },
414
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
415
+ },
416
+ required: ['field', 'value'],
417
+ additionalProperties: false
418
+ }
419
+ },
420
+ {
421
+ name: 'faf_check',
422
+ description: 'Inspect the human_context fields and rate each empty/generic/good/excellent. Returns the ratings; with protect it locks good/excellent fields from being overwritten, with unlock it releases them. Use this to gauge context quality and guard your best answers.',
423
+ annotations: {
424
+ title: 'Check .faf Health',
425
+ readOnlyHint: false,
426
+ destructiveHint: false,
427
+ openWorldHint: false
457
428
  },
458
- {
459
- name: 'faf_context',
460
- description: '📂 Set or view active project context - Path is remembered for subsequent faf_ calls 🧡⚡️',
461
- annotations: {
462
- title: 'View Context',
463
- readOnlyHint: true,
464
- openWorldHint: false
429
+ inputSchema: {
430
+ type: 'object',
431
+ properties: {
432
+ protect: { type: 'boolean', description: 'Lock good/excellent fields from being overwritten' },
433
+ unlock: { type: 'boolean', description: 'Remove all field protections' },
434
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
465
435
  },
466
- inputSchema: {
467
- type: 'object',
468
- properties: {
469
- path: { type: 'string', description: 'Set active project path. If omitted, shows current context.' }
470
- },
471
- additionalProperties: false
472
- }
436
+ additionalProperties: false
437
+ }
438
+ },
439
+ {
440
+ name: 'faf_context',
441
+ description: 'Set or show the active project path that later faf_ calls resolve against. Returns the current context path. Call this once at the start of a session so the other tools target the right project.',
442
+ annotations: {
443
+ title: 'View Context',
444
+ readOnlyHint: true,
445
+ openWorldHint: false
473
446
  },
474
- {
475
- name: 'faf_go',
476
- description: '🎯 Guided interview to Gold Code - Claude asks questions till you hit 100%! Returns questions for missing fields, then apply answers to reach Gold Code 🧡⚡️',
477
- annotations: {
478
- title: 'Guided Setup',
479
- readOnlyHint: false,
480
- destructiveHint: false,
481
- openWorldHint: false
447
+ inputSchema: {
448
+ type: 'object',
449
+ properties: {
450
+ path: { type: 'string', description: 'Set active project path. If omitted, shows current context.' }
482
451
  },
483
- inputSchema: {
484
- type: 'object',
485
- properties: {
486
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' },
487
- answers: {
488
- type: 'object',
489
- description: 'Answers to apply. Keys are field paths (e.g., "project.goal", "human_context.why"), values are the answers. If provided, applies answers and returns new score.',
490
- additionalProperties: { type: 'string' }
491
- }
492
- },
493
- additionalProperties: false
494
- }
452
+ additionalProperties: false
453
+ }
454
+ },
455
+ {
456
+ name: 'faf_go',
457
+ description: 'Drive a project.faf to 100% through a guided interview — returns the next questions for the missing human-context and goal fields, then applies the answers passed back. Returns the updated score after each round. Use this to close the gap to a complete context when auto-detection cannot fill the human slots.',
458
+ annotations: {
459
+ title: 'Guided Setup',
460
+ readOnlyHint: false,
461
+ destructiveHint: false,
462
+ openWorldHint: false
495
463
  },
496
- {
497
- name: 'faf_auto',
498
- description: '🏎️ ONE COMMAND TO RULE THEM ALL - Zero to Championship AI context instantly! Runs init + sync + formats + bi-sync + score in one go 🧡⚡️',
499
- annotations: {
500
- title: 'Auto-detect Context',
501
- readOnlyHint: false,
502
- destructiveHint: false,
503
- openWorldHint: false
464
+ inputSchema: {
465
+ type: 'object',
466
+ properties: {
467
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' },
468
+ answers: {
469
+ type: 'object',
470
+ description: 'Answers to apply. Keys are field paths (e.g., "project.goal", "human_context.why"), values are the answers. If provided, applies answers and returns new score.',
471
+ additionalProperties: { type: 'string' }
472
+ }
504
473
  },
505
- inputSchema: {
506
- type: 'object',
507
- properties: {
508
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' },
509
- force: { type: 'boolean', description: 'Force overwrite existing files' }
510
- },
511
- additionalProperties: false
512
- }
474
+ additionalProperties: false
475
+ }
476
+ },
477
+ {
478
+ name: 'faf_auto',
479
+ description: 'Run the full setup pipeline in one call — init, stack detection, sync, bi-sync, and score — taking a project from no context to a complete project.faf. Returns the final AI-readiness score and what was created. Use this as the fast path on a fresh project; use the individual tools when you need finer control.',
480
+ annotations: {
481
+ title: 'Auto-detect Context',
482
+ readOnlyHint: false,
483
+ destructiveHint: false,
484
+ openWorldHint: false
513
485
  },
514
- {
515
- name: 'faf_dna',
516
- description: '🧬 Show your FAF DNA journey - See your evolution from birth to championship (22% → 85% → 99%) 🧡⚡️',
517
- annotations: {
518
- title: 'View Project DNA',
519
- readOnlyHint: true,
520
- openWorldHint: false
486
+ inputSchema: {
487
+ type: 'object',
488
+ properties: {
489
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' },
490
+ force: { type: 'boolean', description: 'Force overwrite existing files' }
521
491
  },
522
- inputSchema: {
523
- type: 'object',
524
- properties: {
525
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
526
- },
527
- additionalProperties: false
528
- }
492
+ additionalProperties: false
493
+ }
494
+ },
495
+ {
496
+ name: 'faf_dna',
497
+ description: 'Show your FAF DNA journey - See your evolution from birth to championship (22% 85% 99%)',
498
+ annotations: {
499
+ title: 'View Project DNA',
500
+ readOnlyHint: true,
501
+ openWorldHint: false
529
502
  },
530
- {
531
- name: 'faf_formats',
532
- description: '😽 TURBO-CAT format discovery - Discovers all formats in your project (154+ validated types!) and fills stack slots 🧡⚡️',
533
- annotations: {
534
- title: 'List Formats',
535
- readOnlyHint: true,
536
- openWorldHint: false
503
+ inputSchema: {
504
+ type: 'object',
505
+ properties: {
506
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
537
507
  },
538
- inputSchema: {
539
- type: 'object',
540
- properties: {
541
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' },
542
- json: { type: 'boolean', description: 'Return results as JSON' }
543
- },
544
- additionalProperties: false
545
- }
508
+ additionalProperties: false
509
+ }
510
+ },
511
+ {
512
+ name: 'faf_formats',
513
+ description: 'Scan the project for tech-stack signals across 150+ manifest types (package.json, Cargo.toml, pyproject.toml, go.mod, and more) and surface which project.faf stack slots to fill. Returns the detected formats and slot-fill recommendations. Use this to populate the technical context.',
514
+ annotations: {
515
+ title: 'List Formats',
516
+ readOnlyHint: true,
517
+ openWorldHint: false
546
518
  },
547
- {
548
- name: 'faf_quick',
549
- description: '⚡ Lightning-fast .faf creation - One-liner format: "name, description, language, framework, hosting" 🧡⚡️',
550
- annotations: {
551
- title: 'Quick Create',
552
- readOnlyHint: false,
553
- destructiveHint: false,
554
- openWorldHint: false
519
+ inputSchema: {
520
+ type: 'object',
521
+ properties: {
522
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' },
523
+ json: { type: 'boolean', description: 'Return results as JSON' }
555
524
  },
556
- inputSchema: {
557
- type: 'object',
558
- properties: {
559
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' },
560
- input: { type: 'string', description: 'Quick input: "project-name, description, language, framework, hosting" (minimum: name, description)' },
561
- force: { type: 'boolean', description: 'Force overwrite existing .faf file' }
562
- },
563
- required: ['input'],
564
- additionalProperties: false
565
- }
525
+ additionalProperties: false
526
+ }
527
+ },
528
+ {
529
+ name: 'faf_quick',
530
+ description: 'Lightning-fast .faf creation - One-liner format: "name, description, language, framework, hosting"',
531
+ annotations: {
532
+ title: 'Quick Create',
533
+ readOnlyHint: false,
534
+ destructiveHint: false,
535
+ openWorldHint: false
566
536
  },
567
- {
568
- name: 'faf_doctor',
569
- description: '🏥 Health check for your .faf setup - Diagnose and fix common issues 🧡⚡️',
570
- annotations: {
571
- title: 'Diagnose Issues',
572
- readOnlyHint: true,
573
- openWorldHint: false
537
+ inputSchema: {
538
+ type: 'object',
539
+ properties: {
540
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' },
541
+ input: { type: 'string', description: 'Quick input: "project-name, description, language, framework, hosting" (minimum: name, description)' },
542
+ force: { type: 'boolean', description: 'Force overwrite existing .faf file' }
574
543
  },
575
- inputSchema: {
576
- type: 'object',
577
- properties: {
578
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
579
- },
580
- additionalProperties: false
581
- }
544
+ required: ['input'],
545
+ additionalProperties: false
546
+ }
547
+ },
548
+ {
549
+ name: 'faf_doctor',
550
+ description: 'Diagnose a project.faf setup — report missing files, empty or weak slots, and common configuration issues, each with how to fix it. Returns a prioritized checklist. Use this when your score is low and you need to know why.',
551
+ annotations: {
552
+ title: 'Diagnose Issues',
553
+ readOnlyHint: true,
554
+ openWorldHint: false
582
555
  },
583
- // ============================================================================
584
- // v4.5.0 INTEROP TOOLS
585
- // ============================================================================
586
- {
587
- name: 'faf_agents',
588
- description: 'Import/Export/Sync between AGENTS.md (OpenAI/Codex) and project.faf - AI interop!',
589
- annotations: {
590
- title: 'Sync AGENTS.md',
591
- readOnlyHint: false,
592
- destructiveHint: false,
593
- openWorldHint: false
556
+ inputSchema: {
557
+ type: 'object',
558
+ properties: {
559
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
594
560
  },
595
- inputSchema: {
596
- type: 'object',
597
- properties: {
598
- action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (AGENTS.md -> .faf), export (.faf -> AGENTS.md), sync (bidirectional)' },
599
- force: { type: 'boolean', description: 'Force overwrite existing files' },
600
- merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
601
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
602
- },
603
- required: ['action'],
604
- additionalProperties: false
605
- }
561
+ additionalProperties: false
562
+ }
563
+ },
564
+ // ============================================================================
565
+ // v4.5.0 INTEROP TOOLS
566
+ // ============================================================================
567
+ {
568
+ name: 'faf_agents',
569
+ description: 'Import, export, or sync context between AGENTS.md (the OpenAI/Codex convention) and project.faf. Returns the merged or written result for the chosen action. Use this to keep a Codex/OpenAI-style AGENTS.md and your .faf in agreement from one source.',
570
+ annotations: {
571
+ title: 'Sync AGENTS.md',
572
+ readOnlyHint: false,
573
+ destructiveHint: false,
574
+ openWorldHint: false
606
575
  },
607
- {
608
- name: 'faf_cursor',
609
- description: 'Import/Export/Sync between .cursorrules (Cursor IDE) and project.faf - AI interop!',
610
- annotations: {
611
- title: 'Sync .cursorrules',
612
- readOnlyHint: false,
613
- destructiveHint: false,
614
- openWorldHint: false
576
+ inputSchema: {
577
+ type: 'object',
578
+ properties: {
579
+ action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (AGENTS.md -> .faf), export (.faf -> AGENTS.md), sync (bidirectional)' },
580
+ force: { type: 'boolean', description: 'Force overwrite existing files' },
581
+ merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
582
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
615
583
  },
616
- inputSchema: {
617
- type: 'object',
618
- properties: {
619
- action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (.cursorrules -> .faf), export (.faf -> .cursorrules), sync (bidirectional)' },
620
- force: { type: 'boolean', description: 'Force overwrite existing files' },
621
- merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
622
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
623
- },
624
- required: ['action'],
625
- additionalProperties: false
626
- }
584
+ required: ['action'],
585
+ additionalProperties: false
586
+ }
587
+ },
588
+ {
589
+ name: 'faf_cursor',
590
+ description: 'Import, export, or sync context between .cursorrules (the Cursor IDE convention) and project.faf. Returns the merged or written result for the chosen action. Use this to keep Cursor rules and your .faf in agreement from one source.',
591
+ annotations: {
592
+ title: 'Sync .cursorrules',
593
+ readOnlyHint: false,
594
+ destructiveHint: false,
595
+ openWorldHint: false
627
596
  },
628
- {
629
- name: 'faf_gemini',
630
- description: 'Import/Export/Sync between GEMINI.md (Google Gemini CLI) and project.faf - AI interop!',
631
- annotations: {
632
- title: 'Sync GEMINI.md',
633
- readOnlyHint: false,
634
- destructiveHint: false,
635
- openWorldHint: false
597
+ inputSchema: {
598
+ type: 'object',
599
+ properties: {
600
+ action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (.cursorrules -> .faf), export (.faf -> .cursorrules), sync (bidirectional)' },
601
+ force: { type: 'boolean', description: 'Force overwrite existing files' },
602
+ merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
603
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
636
604
  },
637
- inputSchema: {
638
- type: 'object',
639
- properties: {
640
- action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (GEMINI.md -> .faf), export (.faf -> GEMINI.md), sync (bidirectional)' },
641
- force: { type: 'boolean', description: 'Force overwrite existing files' },
642
- merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
643
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
644
- },
645
- required: ['action'],
646
- additionalProperties: false
647
- }
605
+ required: ['action'],
606
+ additionalProperties: false
607
+ }
608
+ },
609
+ {
610
+ name: 'faf_gemini',
611
+ description: 'Import, export, or sync context between GEMINI.md (the Google Gemini CLI convention) and project.faf. Returns the merged or written result for the chosen action. Use this to keep a Gemini context file and your .faf in agreement from one source.',
612
+ annotations: {
613
+ title: 'Sync GEMINI.md',
614
+ readOnlyHint: false,
615
+ destructiveHint: false,
616
+ openWorldHint: false
648
617
  },
649
- {
650
- name: 'faf_conductor',
651
- description: 'Import/Export between conductor/ directory (Google Conductor) and project.faf - AI interop!',
652
- annotations: {
653
- title: 'Sync Conductor',
654
- readOnlyHint: false,
655
- destructiveHint: false,
656
- openWorldHint: false
618
+ inputSchema: {
619
+ type: 'object',
620
+ properties: {
621
+ action: { type: 'string', enum: ['import', 'export', 'sync'], description: 'Action: import (GEMINI.md -> .faf), export (.faf -> GEMINI.md), sync (bidirectional)' },
622
+ force: { type: 'boolean', description: 'Force overwrite existing files' },
623
+ merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
624
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
657
625
  },
658
- inputSchema: {
659
- type: 'object',
660
- properties: {
661
- action: { type: 'string', enum: ['import', 'export'], description: 'Action: import (conductor/ -> .faf), export (.faf -> conductor/)' },
662
- force: { type: 'boolean', description: 'Force overwrite existing files' },
663
- merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
664
- path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
665
- },
666
- required: ['action'],
667
- additionalProperties: false
668
- }
626
+ required: ['action'],
627
+ additionalProperties: false
628
+ }
629
+ },
630
+ {
631
+ name: 'faf_conductor',
632
+ description: 'Import/Export between conductor/ directory (Google Conductor) and project.faf - AI interop!',
633
+ annotations: {
634
+ title: 'Sync Conductor',
635
+ readOnlyHint: false,
636
+ destructiveHint: false,
637
+ openWorldHint: false
669
638
  },
670
- {
671
- name: 'faf_git',
672
- description: 'Generate project.faf from any GitHub repo URL - 1-click context extraction!',
673
- annotations: {
674
- title: 'Extract from GitHub',
675
- readOnlyHint: false,
676
- destructiveHint: false,
677
- openWorldHint: false
639
+ inputSchema: {
640
+ type: 'object',
641
+ properties: {
642
+ action: { type: 'string', enum: ['import', 'export'], description: 'Action: import (conductor/ -> .faf), export (.faf -> conductor/)' },
643
+ force: { type: 'boolean', description: 'Force overwrite existing files' },
644
+ merge: { type: 'boolean', description: 'Merge imported data with existing .faf instead of replacing' },
645
+ path: { type: 'string', description: 'Project path. Sets session context for subsequent calls.' }
678
646
  },
679
- inputSchema: {
680
- type: 'object',
681
- properties: {
682
- url: { type: 'string', description: 'GitHub repository URL (e.g., https://github.com/owner/repo or owner/repo)' },
683
- path: { type: 'string', description: 'Output directory for generated project.faf. If omitted, returns content without writing.' }
684
- },
685
- required: ['url'],
686
- additionalProperties: false
687
- }
647
+ required: ['action'],
648
+ additionalProperties: false
649
+ }
650
+ },
651
+ {
652
+ name: 'faf_git',
653
+ description: 'Generate a project.faf from any public GitHub repository URL — fetches the repo and extracts its stack and context. Returns the generated .faf. Use this to bootstrap context for a project you have the URL for but not cloned locally.',
654
+ annotations: {
655
+ title: 'Extract from GitHub',
656
+ readOnlyHint: false,
657
+ destructiveHint: false,
658
+ openWorldHint: true
688
659
  },
689
- ]
690
- };
660
+ inputSchema: {
661
+ type: 'object',
662
+ properties: {
663
+ url: { type: 'string', description: 'GitHub repository URL (e.g., https://github.com/owner/repo or owner/repo)' },
664
+ path: { type: 'string', description: 'Output directory for generated project.faf. If omitted, returns content without writing.' }
665
+ },
666
+ required: ['url'],
667
+ additionalProperties: false
668
+ }
669
+ },
670
+ ];
671
+ // Core-tier gate: advertise only the Core by default; FAF_TOOLS=all (or
672
+ // FAF_EXTENDED=1) exposes the full set. Dispatch in callTool keeps every
673
+ // tool callable by name regardless — the gate only shapes tools/list.
674
+ const showAll = process.env.FAF_TOOLS === 'all' || process.env.FAF_EXTENDED === '1';
675
+ return { tools: showAll ? allTools : allTools.filter((t) => CORE_TOOLS.has(t.name)) };
691
676
  }
692
677
  async callTool(name, args) {
693
678
  // Input validation
@@ -706,8 +691,6 @@ class FafToolHandler {
706
691
  return await this.handleFafTrust(args);
707
692
  case 'faf_sync':
708
693
  return await this.handleFafSync(args);
709
- case 'faf_enhance':
710
- return await this.handleFafEnhance(args);
711
694
  case 'faf_bi_sync':
712
695
  return await this.handleFafBiSync(args);
713
696
  case 'faf_clear':
@@ -729,8 +712,6 @@ class FafToolHandler {
729
712
  }
730
713
  case 'faf_chat':
731
714
  return await this.handleFafChat(args);
732
- case 'faf_friday':
733
- return await this.handleFafFriday(args);
734
715
  case 'faf_write':
735
716
  return await fileHandler_1.fileHandlers.faf_write(args);
736
717
  case 'faf_list':
@@ -1056,44 +1037,6 @@ package_manager: ${projectData.package_manager}` : ''}
1056
1037
  }]
1057
1038
  };
1058
1039
  }
1059
- async handleFafEnhance(args) {
1060
- // Set project context if path provided
1061
- if (args?.path) {
1062
- this.getProjectPath(args.path);
1063
- }
1064
- const enhanceArgs = [];
1065
- // Default to Claude optimization if no model specified
1066
- const model = args?.model || 'claude';
1067
- enhanceArgs.push('--model', model);
1068
- if (args?.focus) {
1069
- enhanceArgs.push('--focus', args.focus);
1070
- }
1071
- if (args?.consensus) {
1072
- enhanceArgs.push('--consensus');
1073
- }
1074
- if (args?.dryRun) {
1075
- enhanceArgs.push('--dry-run');
1076
- }
1077
- const result = await this.engineAdapter.callEngine('enhance', enhanceArgs);
1078
- if (!result.success) {
1079
- return {
1080
- content: [{
1081
- type: 'text',
1082
- text: `🚀 Claude FAF Enhancement:\n\nFailed to enhance: ${result.error}`
1083
- }],
1084
- isError: true
1085
- };
1086
- }
1087
- const output = typeof result.data === 'string'
1088
- ? result.data
1089
- : result.data?.message || result.data?.output || JSON.stringify(result.data, null, 2);
1090
- return {
1091
- content: [{
1092
- type: 'text',
1093
- text: `🚀 Claude FAF Enhancement:\n\n${output}`
1094
- }]
1095
- };
1096
- }
1097
1040
  async handleFafBiSync(args) {
1098
1041
  // Set project context if path provided
1099
1042
  if (args?.path) {
@@ -1168,12 +1111,17 @@ package_manager: ${projectData.package_manager}` : ''}
1168
1111
  const packageInfo = {
1169
1112
  name: 'faf-mcp',
1170
1113
  version: version_1.VERSION,
1171
- description: 'We ARE the C in MCP. I⚡🍊 - The formula that changes everything.',
1114
+ description: 'We ARE the C in MCP. I - The formula that changes everything.',
1172
1115
  author: 'FAF Team (team@faf.one)',
1173
1116
  website: 'https://faf.one',
1174
1117
  npm: 'https://www.npmjs.com/package/faf-mcp'
1175
1118
  };
1176
- const aboutText = `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1119
+ const aboutText = `well seeing as you clearly have time to burn, faf is about saving your AI time, how is that working out...
1120
+
1121
+ faff about (v., Brit.) — what your AI does for 20 minutes relearning your project, every session.
1122
+ .faf (n.) — what stops it. Same four letters, opposite outcomes.
1123
+
1124
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1177
1125
  🤖 .faf = project DNA for AI
1178
1126
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1179
1127
 
@@ -1318,47 +1266,6 @@ ${debugInfo.permissions.fafError ? ` FAF Error: ${debugInfo.permissions.fafErr
1318
1266
  }],
1319
1267
  };
1320
1268
  }
1321
- async handleFafFriday(args) {
1322
- const { test } = args || {};
1323
- let response = `🎉 **Friday Features in FAF MCP!**\n\n`;
1324
- response += `**Chrome Extension Auto-Detection** | Boosts scores to 90%+ automatically\n`;
1325
- response += `**Universal Fuzzy Matching** | Typo-tolerant: "raect"→"react", "chr ext"→"chrome extension"\n`;
1326
- response += `**Intel-Friday™** | Smart IF statements that add massive value\n\n`;
1327
- if (test) {
1328
- // Test fuzzy matching
1329
- const suggestion = fuzzy_detector_1.FuzzyDetector.getSuggestion(test);
1330
- const projectType = fuzzy_detector_1.FuzzyDetector.detectProjectType(test);
1331
- const chromeDetection = fuzzy_detector_1.FuzzyDetector.detectChromeExtension(test);
1332
- response += `\n**Testing: "${test}"**\n`;
1333
- if (suggestion) {
1334
- response += `✅ Fuzzy Match: "${test}" → "${suggestion}"\n`;
1335
- }
1336
- response += `📦 Project Type Detected: ${projectType}\n`;
1337
- if (chromeDetection.detected) {
1338
- response += `🎯 Chrome Extension Detected! (Confidence: ${chromeDetection.confidence})\n`;
1339
- if (chromeDetection.corrected) {
1340
- response += ` Corrected from: "${test}" → "${chromeDetection.corrected}"\n`;
1341
- }
1342
- }
1343
- // Show what would be auto-filled
1344
- if (chromeDetection.detected && chromeDetection.confidence === 'high') {
1345
- response += `\n**Auto-fill Preview (7 slots for 90%+ score):**\n`;
1346
- const slots = fuzzy_detector_1.FuzzyDetector.getChromeExtensionSlots();
1347
- for (const [key, value] of Object.entries(slots)) {
1348
- response += `• ${key}: ${value}\n`;
1349
- }
1350
- }
1351
- }
1352
- else {
1353
- response += `\n💡 Try: \`faf_friday test:"raect"\` or \`faf_friday test:"chr ext"\``;
1354
- }
1355
- return {
1356
- content: [{
1357
- type: 'text',
1358
- text: response
1359
- }]
1360
- };
1361
- }
1362
1269
  async handleFafGuide(_args) {
1363
1270
  const guide = `# FAF MCP - your MCP host Guide
1364
1271