faf-mcp 1.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.
Files changed (207) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/CLAUDE.md +73 -0
  3. package/LICENSE +22 -0
  4. package/README.md +165 -0
  5. package/assets/Project-faf-pckg-json-README.png +0 -0
  6. package/assets/icons/faf-icon-128.png +0 -0
  7. package/assets/icons/faf-icon-256.png +0 -0
  8. package/assets/icons/faf-icon-48.png +0 -0
  9. package/assets/icons/faf-icon-512.png +0 -0
  10. package/assets/icons/orange-smiley.svg +6 -0
  11. package/dist/src/compiler/index.d.ts +7 -0
  12. package/dist/src/compiler/index.js +24 -0
  13. package/dist/src/compiler/index.js.map +1 -0
  14. package/dist/src/compiler/scorer.d.ts +53 -0
  15. package/dist/src/compiler/scorer.js +189 -0
  16. package/dist/src/compiler/scorer.js.map +1 -0
  17. package/dist/src/compiler/slot-validator.d.ts +32 -0
  18. package/dist/src/compiler/slot-validator.js +293 -0
  19. package/dist/src/compiler/slot-validator.js.map +1 -0
  20. package/dist/src/compiler/type-detector.d.ts +62 -0
  21. package/dist/src/compiler/type-detector.js +388 -0
  22. package/dist/src/compiler/type-detector.js.map +1 -0
  23. package/dist/src/config/visibility.d.ts +41 -0
  24. package/dist/src/config/visibility.js +158 -0
  25. package/dist/src/config/visibility.js.map +1 -0
  26. package/dist/src/faf-core/commands/audit.d.ts +21 -0
  27. package/dist/src/faf-core/commands/audit.js +83 -0
  28. package/dist/src/faf-core/commands/audit.js.map +1 -0
  29. package/dist/src/faf-core/commands/auto.d.ts +25 -0
  30. package/dist/src/faf-core/commands/auto.js +74 -0
  31. package/dist/src/faf-core/commands/auto.js.map +1 -0
  32. package/dist/src/faf-core/commands/bi-sync.d.ts +26 -0
  33. package/dist/src/faf-core/commands/bi-sync.js +157 -0
  34. package/dist/src/faf-core/commands/bi-sync.js.map +1 -0
  35. package/dist/src/faf-core/commands/doctor.d.ts +17 -0
  36. package/dist/src/faf-core/commands/doctor.js +198 -0
  37. package/dist/src/faf-core/commands/doctor.js.map +1 -0
  38. package/dist/src/faf-core/commands/enhance.d.ts +46 -0
  39. package/dist/src/faf-core/commands/enhance.js +360 -0
  40. package/dist/src/faf-core/commands/enhance.js.map +1 -0
  41. package/dist/src/faf-core/commands/formats.d.ts +22 -0
  42. package/dist/src/faf-core/commands/formats.js +117 -0
  43. package/dist/src/faf-core/commands/formats.js.map +1 -0
  44. package/dist/src/faf-core/commands/init.d.ts +26 -0
  45. package/dist/src/faf-core/commands/init.js +114 -0
  46. package/dist/src/faf-core/commands/init.js.map +1 -0
  47. package/dist/src/faf-core/commands/innit.d.ts +7 -0
  48. package/dist/src/faf-core/commands/innit.js +13 -0
  49. package/dist/src/faf-core/commands/innit.js.map +1 -0
  50. package/dist/src/faf-core/commands/migrate.d.ts +15 -0
  51. package/dist/src/faf-core/commands/migrate.js +86 -0
  52. package/dist/src/faf-core/commands/migrate.js.map +1 -0
  53. package/dist/src/faf-core/commands/quick.d.ts +16 -0
  54. package/dist/src/faf-core/commands/quick.js +184 -0
  55. package/dist/src/faf-core/commands/quick.js.map +1 -0
  56. package/dist/src/faf-core/commands/score.d.ts +47 -0
  57. package/dist/src/faf-core/commands/score.js +49 -0
  58. package/dist/src/faf-core/commands/score.js.map +1 -0
  59. package/dist/src/faf-core/commands/sync.d.ts +16 -0
  60. package/dist/src/faf-core/commands/sync.js +210 -0
  61. package/dist/src/faf-core/commands/sync.js.map +1 -0
  62. package/dist/src/faf-core/commands/update.d.ts +12 -0
  63. package/dist/src/faf-core/commands/update.js +46 -0
  64. package/dist/src/faf-core/commands/update.js.map +1 -0
  65. package/dist/src/faf-core/commands/validate.d.ts +21 -0
  66. package/dist/src/faf-core/commands/validate.js +81 -0
  67. package/dist/src/faf-core/commands/validate.js.map +1 -0
  68. package/dist/src/faf-core/compiler/faf-compiler.d.ts +138 -0
  69. package/dist/src/faf-core/compiler/faf-compiler.js +794 -0
  70. package/dist/src/faf-core/compiler/faf-compiler.js.map +1 -0
  71. package/dist/src/faf-core/engines/dependency-tsa.d.ts +88 -0
  72. package/dist/src/faf-core/engines/dependency-tsa.js +361 -0
  73. package/dist/src/faf-core/engines/dependency-tsa.js.map +1 -0
  74. package/dist/src/faf-core/engines/fab-formats-processor.d.ts +166 -0
  75. package/dist/src/faf-core/engines/fab-formats-processor.js +1274 -0
  76. package/dist/src/faf-core/engines/fab-formats-processor.js.map +1 -0
  77. package/dist/src/faf-core/engines/faf-dna.d.ts +159 -0
  78. package/dist/src/faf-core/engines/faf-dna.js +554 -0
  79. package/dist/src/faf-core/engines/faf-dna.js.map +1 -0
  80. package/dist/src/faf-core/engines/relentless-context-extractor.d.ts +100 -0
  81. package/dist/src/faf-core/engines/relentless-context-extractor.js +625 -0
  82. package/dist/src/faf-core/engines/relentless-context-extractor.js.map +1 -0
  83. package/dist/src/faf-core/fix-once/colors.d.ts +104 -0
  84. package/dist/src/faf-core/fix-once/colors.js +236 -0
  85. package/dist/src/faf-core/fix-once/colors.js.map +1 -0
  86. package/dist/src/faf-core/fix-once/types.d.ts +257 -0
  87. package/dist/src/faf-core/fix-once/types.js +26 -0
  88. package/dist/src/faf-core/fix-once/types.js.map +1 -0
  89. package/dist/src/faf-core/fix-once/yaml.d.ts +57 -0
  90. package/dist/src/faf-core/fix-once/yaml.js +172 -0
  91. package/dist/src/faf-core/fix-once/yaml.js.map +1 -0
  92. package/dist/src/faf-core/generators/faf-generator-championship.d.ts +16 -0
  93. package/dist/src/faf-core/generators/faf-generator-championship.js +462 -0
  94. package/dist/src/faf-core/generators/faf-generator-championship.js.map +1 -0
  95. package/dist/src/faf-core/utils/balance-visualizer.d.ts +37 -0
  96. package/dist/src/faf-core/utils/balance-visualizer.js +197 -0
  97. package/dist/src/faf-core/utils/balance-visualizer.js.map +1 -0
  98. package/dist/src/faf-core/utils/championship-style.d.ts +109 -0
  99. package/dist/src/faf-core/utils/championship-style.js +219 -0
  100. package/dist/src/faf-core/utils/championship-style.js.map +1 -0
  101. package/dist/src/faf-core/utils/chrome-extension-detector.d.ts +73 -0
  102. package/dist/src/faf-core/utils/chrome-extension-detector.js +268 -0
  103. package/dist/src/faf-core/utils/chrome-extension-detector.js.map +1 -0
  104. package/dist/src/faf-core/utils/fafignore-parser.d.ts +20 -0
  105. package/dist/src/faf-core/utils/fafignore-parser.js +178 -0
  106. package/dist/src/faf-core/utils/fafignore-parser.js.map +1 -0
  107. package/dist/src/faf-core/utils/file-utils.d.ts +112 -0
  108. package/dist/src/faf-core/utils/file-utils.js +846 -0
  109. package/dist/src/faf-core/utils/file-utils.js.map +1 -0
  110. package/dist/src/faf-core/utils/native-file-finder.d.ts +115 -0
  111. package/dist/src/faf-core/utils/native-file-finder.js +211 -0
  112. package/dist/src/faf-core/utils/native-file-finder.js.map +1 -0
  113. package/dist/src/faf-core/utils/platform-detector.d.ts +30 -0
  114. package/dist/src/faf-core/utils/platform-detector.js +218 -0
  115. package/dist/src/faf-core/utils/platform-detector.js.map +1 -0
  116. package/dist/src/faf-core/utils/technical-credit.d.ts +35 -0
  117. package/dist/src/faf-core/utils/technical-credit.js +286 -0
  118. package/dist/src/faf-core/utils/technical-credit.js.map +1 -0
  119. package/dist/src/faf-core/utils/yaml-generator.d.ts +41 -0
  120. package/dist/src/faf-core/utils/yaml-generator.js +360 -0
  121. package/dist/src/faf-core/utils/yaml-generator.js.map +1 -0
  122. package/dist/src/handlers/behavioral-instruction.d.ts +16 -0
  123. package/dist/src/handlers/behavioral-instruction.js +43 -0
  124. package/dist/src/handlers/behavioral-instruction.js.map +1 -0
  125. package/dist/src/handlers/championship-tools.d.ts +113 -0
  126. package/dist/src/handlers/championship-tools.js +2602 -0
  127. package/dist/src/handlers/championship-tools.js.map +1 -0
  128. package/dist/src/handlers/engine-adapter.d.ts +28 -0
  129. package/dist/src/handlers/engine-adapter.js +603 -0
  130. package/dist/src/handlers/engine-adapter.js.map +1 -0
  131. package/dist/src/handlers/fileHandler.d.ts +36 -0
  132. package/dist/src/handlers/fileHandler.js +246 -0
  133. package/dist/src/handlers/fileHandler.js.map +1 -0
  134. package/dist/src/handlers/resources.d.ts +18 -0
  135. package/dist/src/handlers/resources.js +78 -0
  136. package/dist/src/handlers/resources.js.map +1 -0
  137. package/dist/src/handlers/tool-registry.d.ts +23 -0
  138. package/dist/src/handlers/tool-registry.js +68 -0
  139. package/dist/src/handlers/tool-registry.js.map +1 -0
  140. package/dist/src/handlers/tool-types.d.ts +167 -0
  141. package/dist/src/handlers/tool-types.js +7 -0
  142. package/dist/src/handlers/tool-types.js.map +1 -0
  143. package/dist/src/handlers/tools.d.ts +25 -0
  144. package/dist/src/handlers/tools.js +1168 -0
  145. package/dist/src/handlers/tools.js.map +1 -0
  146. package/dist/src/index.d.ts +2 -0
  147. package/dist/src/index.js +17 -0
  148. package/dist/src/index.js.map +1 -0
  149. package/dist/src/server.d.ts +28 -0
  150. package/dist/src/server.js +179 -0
  151. package/dist/src/server.js.map +1 -0
  152. package/dist/src/test-all-functions.d.ts +15 -0
  153. package/dist/src/test-all-functions.js +163 -0
  154. package/dist/src/test-all-functions.js.map +1 -0
  155. package/dist/src/types/mcp-tools.d.ts +53 -0
  156. package/dist/src/types/mcp-tools.js +77 -0
  157. package/dist/src/types/mcp-tools.js.map +1 -0
  158. package/dist/src/types/project-types.d.ts +22 -0
  159. package/dist/src/types/project-types.js +85 -0
  160. package/dist/src/types/project-types.js.map +1 -0
  161. package/dist/src/types/slots.d.ts +39 -0
  162. package/dist/src/types/slots.js +162 -0
  163. package/dist/src/types/slots.js.map +1 -0
  164. package/dist/src/types/tool-visibility.d.ts +36 -0
  165. package/dist/src/types/tool-visibility.js +510 -0
  166. package/dist/src/types/tool-visibility.js.map +1 -0
  167. package/dist/src/utils/auto-path-detection.d.ts +26 -0
  168. package/dist/src/utils/auto-path-detection.js +198 -0
  169. package/dist/src/utils/auto-path-detection.js.map +1 -0
  170. package/dist/src/utils/championship-format.d.ts +30 -0
  171. package/dist/src/utils/championship-format.js +79 -0
  172. package/dist/src/utils/championship-format.js.map +1 -0
  173. package/dist/src/utils/cli-detector.d.ts +20 -0
  174. package/dist/src/utils/cli-detector.js +230 -0
  175. package/dist/src/utils/cli-detector.js.map +1 -0
  176. package/dist/src/utils/display-protocol.d.ts +57 -0
  177. package/dist/src/utils/display-protocol.js +131 -0
  178. package/dist/src/utils/display-protocol.js.map +1 -0
  179. package/dist/src/utils/faf-file-finder.d.ts +59 -0
  180. package/dist/src/utils/faf-file-finder.js +139 -0
  181. package/dist/src/utils/faf-file-finder.js.map +1 -0
  182. package/dist/src/utils/fuzzy-detector.d.ts +56 -0
  183. package/dist/src/utils/fuzzy-detector.js +221 -0
  184. package/dist/src/utils/fuzzy-detector.js.map +1 -0
  185. package/dist/src/utils/path-resolver.d.ts +51 -0
  186. package/dist/src/utils/path-resolver.js +214 -0
  187. package/dist/src/utils/path-resolver.js.map +1 -0
  188. package/dist/src/utils/type-guards.d.ts +9 -0
  189. package/dist/src/utils/type-guards.js +27 -0
  190. package/dist/src/utils/type-guards.js.map +1 -0
  191. package/dist/src/utils/username-detector.d.ts +27 -0
  192. package/dist/src/utils/username-detector.js +90 -0
  193. package/dist/src/utils/username-detector.js.map +1 -0
  194. package/dist/src/utils/visual-style.d.ts +62 -0
  195. package/dist/src/utils/visual-style.js +164 -0
  196. package/dist/src/utils/visual-style.js.map +1 -0
  197. package/dist/src/version.d.ts +9 -0
  198. package/dist/src/version.js +37 -0
  199. package/dist/src/version.js.map +1 -0
  200. package/package.json +114 -0
  201. package/scripts/discord-sync-curated.js +233 -0
  202. package/scripts/discord-sync-final.js +218 -0
  203. package/scripts/discord-sync-simple.js +175 -0
  204. package/scripts/discord-sync-working.js +187 -0
  205. package/scripts/discord-sync.js +181 -0
  206. package/scripts/postinstall.js +46 -0
  207. package/skill/SKILL.md +385 -0
@@ -0,0 +1,1168 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FafToolHandler = void 0;
37
+ const fileHandler_1 = require("./fileHandler");
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const fuzzy_detector_1 = require("../utils/fuzzy-detector");
41
+ const faf_file_finder_js_1 = require("../utils/faf-file-finder.js");
42
+ const version_1 = require("../version");
43
+ const path_resolver_1 = require("../utils/path-resolver");
44
+ class FafToolHandler {
45
+ engineAdapter;
46
+ constructor(engineAdapter) {
47
+ this.engineAdapter = engineAdapter;
48
+ }
49
+ async listTools() {
50
+ return {
51
+ tools: [
52
+ {
53
+ name: 'faf_about',
54
+ description: 'Learn what .faf format is - THE JPEG for AI 🧡⚡️',
55
+ inputSchema: {
56
+ type: 'object',
57
+ properties: {},
58
+ additionalProperties: false
59
+ }
60
+ },
61
+ {
62
+ name: 'faf_what',
63
+ description: 'What is .faf format? Quick explanation of THE JPEG for AI 🧡⚡️',
64
+ inputSchema: {
65
+ type: 'object',
66
+ properties: {},
67
+ additionalProperties: false
68
+ }
69
+ },
70
+ {
71
+ name: 'faf_status',
72
+ description: 'Check if your project has project.faf (THE JPEG for AI) - Shows AI-readability status 🧡⚡️',
73
+ inputSchema: {
74
+ type: 'object',
75
+ properties: {},
76
+ additionalProperties: false
77
+ }
78
+ },
79
+ {
80
+ name: 'faf_score',
81
+ description: 'Calculate your project\'s AI-readability from project.faf (THE JPEG for AI) - F1-inspired metrics! 🧡⚡️',
82
+ inputSchema: {
83
+ type: 'object',
84
+ properties: {
85
+ details: { type: 'boolean', description: 'Include detailed breakdown and improvement suggestions' }
86
+ },
87
+ additionalProperties: false
88
+ }
89
+ },
90
+ {
91
+ name: 'faf_init',
92
+ description: 'Create project.faf (THE JPEG for AI) - Makes your project instantly AI-readable 🧡⚡️. Use Projects convention (~/Projects/[name]/project.faf) by default. Run faf_guide for path resolution rules.',
93
+ inputSchema: {
94
+ type: 'object',
95
+ properties: {
96
+ force: { type: 'boolean', description: 'Force reinitialize existing FAF context' },
97
+ directory: { type: 'string', description: 'Project directory path (supports ~ tilde expansion). Creates directory if it doesn\'t exist.' },
98
+ path: { type: 'string', description: 'Alias for directory parameter' },
99
+ projectName: { type: 'string', description: 'Project name for path inference (used with Projects convention)' }
100
+ },
101
+ additionalProperties: false
102
+ }
103
+ },
104
+ {
105
+ name: 'faf_trust',
106
+ description: 'Validate project.faf integrity - Trust metrics for THE JPEG for AI 🧡⚡️',
107
+ inputSchema: {
108
+ type: 'object',
109
+ properties: {},
110
+ additionalProperties: false
111
+ }
112
+ },
113
+ {
114
+ name: 'faf_sync',
115
+ description: 'Sync project.faf (THE JPEG for AI) with CLAUDE.md - Bi-directional context 🧡⚡️',
116
+ inputSchema: {
117
+ type: 'object',
118
+ properties: {},
119
+ additionalProperties: false
120
+ }
121
+ },
122
+ {
123
+ name: 'faf_enhance',
124
+ description: 'Enhance project.faf (THE JPEG for AI) with AI optimization - SPEEDY AI you can TRUST! 🧡⚡️',
125
+ inputSchema: {
126
+ type: 'object',
127
+ properties: {
128
+ model: { type: 'string', description: 'Target AI model: claude|chatgpt|gemini|universal (default: claude)' },
129
+ focus: { type: 'string', description: 'Enhancement focus: claude-optimal|human-context|ai-instructions|completeness' },
130
+ consensus: { type: 'boolean', description: 'Build consensus from multiple AI models' },
131
+ dryRun: { type: 'boolean', description: 'Preview enhancement without applying changes' }
132
+ },
133
+ additionalProperties: false
134
+ }
135
+ },
136
+ {
137
+ name: 'faf_bi_sync',
138
+ description: 'Bi-directional sync between project.faf context and claude.md for persistent Claude collaboration',
139
+ inputSchema: {
140
+ type: 'object',
141
+ properties: {
142
+ auto: { type: 'boolean', description: 'Enable automatic synchronization' },
143
+ watch: { type: 'boolean', description: 'Start real-time file watching for changes' },
144
+ force: { type: 'boolean', description: 'Force overwrite conflicting changes' }
145
+ },
146
+ additionalProperties: false
147
+ }
148
+ },
149
+ {
150
+ name: 'faf_clear',
151
+ description: 'Clear caches, temporary files, and reset FAF state for a fresh start',
152
+ inputSchema: {
153
+ type: 'object',
154
+ properties: {
155
+ cache: { type: 'boolean', description: 'Clear trust cache only' },
156
+ todos: { type: 'boolean', description: 'Clear todo lists only' },
157
+ backups: { type: 'boolean', description: 'Clear backup files only' },
158
+ all: { type: 'boolean', description: 'Clear everything (default)' }
159
+ },
160
+ additionalProperties: false
161
+ }
162
+ },
163
+ {
164
+ name: 'faf_debug',
165
+ description: 'Debug Claude FAF MCP environment - show working directory, permissions, and FAF CLI status',
166
+ inputSchema: {
167
+ type: 'object',
168
+ properties: {},
169
+ additionalProperties: false
170
+ }
171
+ },
172
+ {
173
+ name: 'faf_read',
174
+ description: 'Read content from any file on the local filesystem',
175
+ inputSchema: {
176
+ type: 'object',
177
+ properties: {
178
+ path: {
179
+ type: 'string',
180
+ description: 'Absolute or relative file path to read'
181
+ }
182
+ },
183
+ required: ['path'],
184
+ additionalProperties: false
185
+ }
186
+ },
187
+ {
188
+ name: 'faf_write',
189
+ description: 'Write content to any file on the local filesystem',
190
+ inputSchema: {
191
+ type: 'object',
192
+ properties: {
193
+ path: {
194
+ type: 'string',
195
+ description: 'Absolute or relative file path to write'
196
+ },
197
+ content: {
198
+ type: 'string',
199
+ description: 'Content to write to the file'
200
+ }
201
+ },
202
+ required: ['path', 'content'],
203
+ additionalProperties: false
204
+ }
205
+ },
206
+ {
207
+ name: 'faf_list',
208
+ description: 'List directories and discover projects with project.faf files - Essential for FAF discovery workflow',
209
+ inputSchema: {
210
+ type: 'object',
211
+ properties: {
212
+ path: {
213
+ type: 'string',
214
+ description: 'Directory path to list (e.g., ~/Projects, /Users/username/Projects)'
215
+ },
216
+ filter: {
217
+ type: 'string',
218
+ enum: ['faf', 'dirs', 'all'],
219
+ description: 'Filter: "faf" (only dirs with project.faf), "dirs" (all directories), "all" (dirs and files). Default: "dirs"'
220
+ },
221
+ depth: {
222
+ type: 'number',
223
+ enum: [1, 2],
224
+ description: 'Directory depth to scan: 1 (immediate children) or 2 (one level deeper). Default: 1'
225
+ },
226
+ showHidden: {
227
+ type: 'boolean',
228
+ description: 'Show hidden files/directories (starting with .). Default: false'
229
+ }
230
+ },
231
+ required: ['path'],
232
+ additionalProperties: false
233
+ }
234
+ },
235
+ {
236
+ name: 'faf_chat',
237
+ description: '🗣️ Natural language project.faf generation - Ask 6W questions (Who/What/Why/Where/When/How) to build complete human context 🧡⚡️',
238
+ inputSchema: {
239
+ type: 'object',
240
+ properties: {},
241
+ additionalProperties: false
242
+ }
243
+ },
244
+ {
245
+ name: 'faf_friday',
246
+ description: '🎉 Friday Features - Chrome Extension detection, fuzzy matching & more! 🧡⚡️',
247
+ inputSchema: {
248
+ type: 'object',
249
+ properties: {
250
+ test: {
251
+ type: 'string',
252
+ description: 'Test fuzzy matching with typos like "raect" or "chr ext"'
253
+ }
254
+ },
255
+ additionalProperties: false
256
+ }
257
+ },
258
+ {
259
+ name: 'faf_guide',
260
+ description: 'FAF MCP usage guide for Claude Desktop - Projects convention, path resolution, and UX patterns',
261
+ inputSchema: {
262
+ type: 'object',
263
+ properties: {},
264
+ additionalProperties: false
265
+ }
266
+ }
267
+ ]
268
+ };
269
+ }
270
+ async callTool(name, args) {
271
+ // Input validation
272
+ if (!name || typeof name !== 'string') {
273
+ throw new Error('Tool name must be a non-empty string');
274
+ }
275
+ switch (name) {
276
+ case 'faf_status':
277
+ return await this.handleFafStatus(args);
278
+ case 'faf_score':
279
+ return await this.handleFafScore(args);
280
+ case 'faf_init':
281
+ return await this.handleFafInit(args);
282
+ case 'faf_trust':
283
+ return await this.handleFafTrust(args);
284
+ case 'faf_sync':
285
+ return await this.handleFafSync(args);
286
+ case 'faf_enhance':
287
+ return await this.handleFafEnhance(args);
288
+ case 'faf_bi_sync':
289
+ return await this.handleFafBiSync(args);
290
+ case 'faf_clear':
291
+ return await this.handleFafClear(args);
292
+ case 'faf_debug':
293
+ return await this.handleFafDebug(args);
294
+ case 'faf_about':
295
+ return await this.handleFafAbout(args);
296
+ case 'faf_what':
297
+ return await this.handleFafWhat(args);
298
+ case 'faf_read':
299
+ return await fileHandler_1.fileHandlers.faf_read(args);
300
+ case 'faf_chat':
301
+ return await this.handleFafChat(args);
302
+ case 'faf_friday':
303
+ return await this.handleFafFriday(args);
304
+ case 'faf_write':
305
+ return await fileHandler_1.fileHandlers.faf_write(args);
306
+ case 'faf_list':
307
+ return await this.handleFafList(args);
308
+ case 'faf_guide':
309
+ return await this.handleFafGuide(args);
310
+ default:
311
+ throw new Error(`Unknown tool: ${name}`);
312
+ }
313
+ }
314
+ async handleFafStatus(_args) {
315
+ // Native implementation - no CLI needed!
316
+ const cwd = this.engineAdapter.getWorkingDirectory();
317
+ try {
318
+ const fafResult = await (0, faf_file_finder_js_1.findFafFile)(cwd);
319
+ if (!fafResult) {
320
+ return {
321
+ content: [{
322
+ type: 'text',
323
+ text: `🤖 Claude FAF Project Status:\n\n❌ No FAF file found in ${cwd}\n💡 Run faf_init to create project.faf`
324
+ }]
325
+ };
326
+ }
327
+ const fafContent = fs.readFileSync(fafResult.path, 'utf-8');
328
+ const lines = fafContent.split('\n').slice(0, 20);
329
+ return {
330
+ content: [{
331
+ type: 'text',
332
+ text: `🤖 Claude FAF Project Status:\n\n✅ ${fafResult.filename} found in ${cwd}\n\nContent preview:\n${lines.join('\n')}`
333
+ }]
334
+ };
335
+ }
336
+ catch (error) {
337
+ return {
338
+ content: [{
339
+ type: 'text',
340
+ text: `🤖 Claude FAF Project Status:\n\n❌ Error: ${error.message}`
341
+ }],
342
+ isError: true
343
+ };
344
+ }
345
+ }
346
+ async handleFafScore(args) {
347
+ try {
348
+ const fs = await import('fs').then(m => m.promises);
349
+ const path = await import('path');
350
+ // Get current working directory from engine adapter (smart detection)
351
+ const cwd = this.engineAdapter.getWorkingDirectory();
352
+ // Score calculation components
353
+ let score = 0;
354
+ const details = [];
355
+ // 1. Check for FAF file (40 points) - v1.2.0: project.faf, *.faf, or .faf
356
+ const fafResult = await (0, faf_file_finder_js_1.findFafFile)(cwd);
357
+ let hasFaf = false;
358
+ if (fafResult) {
359
+ hasFaf = true;
360
+ score += 40;
361
+ details.push(`✅ ${fafResult.filename} present (+40)`);
362
+ }
363
+ else {
364
+ details.push('❌ FAF file missing (0/40)');
365
+ }
366
+ // 2. Check for CLAUDE.md (30 points)
367
+ const claudePath = path.join(cwd, 'CLAUDE.md');
368
+ let hasClaude = false;
369
+ try {
370
+ await fs.access(claudePath);
371
+ hasClaude = true;
372
+ score += 30;
373
+ details.push('✅ CLAUDE.md present (+30)');
374
+ }
375
+ catch {
376
+ details.push('❌ CLAUDE.md missing (0/30)');
377
+ }
378
+ // 3. Check for README.md (15 points)
379
+ const readmePath = path.join(cwd, 'README.md');
380
+ let hasReadme = false;
381
+ try {
382
+ await fs.access(readmePath);
383
+ hasReadme = true;
384
+ score += 15;
385
+ details.push('✅ README.md present (+15)');
386
+ }
387
+ catch {
388
+ details.push('⚠️ README.md missing (0/15)');
389
+ }
390
+ // 4. Check for package.json or other project files (14 points)
391
+ const projectFiles = ['package.json', 'pyproject.toml', 'Cargo.toml', 'go.mod', 'pom.xml'];
392
+ let hasProjectFile = false;
393
+ for (const file of projectFiles) {
394
+ try {
395
+ await fs.access(path.join(cwd, file));
396
+ hasProjectFile = true;
397
+ score += 14;
398
+ details.push(`✅ ${file} detected (+14)`);
399
+ break;
400
+ }
401
+ catch {
402
+ // Continue checking
403
+ }
404
+ }
405
+ if (!hasProjectFile) {
406
+ details.push('⚠️ No project file found (0/14)');
407
+ }
408
+ // Easter Egg: 105% Big Orange - if both .faf and CLAUDE.md have rich content
409
+ let easterEggActivated = false;
410
+ if (hasFaf && hasClaude) {
411
+ try {
412
+ const fafContent = await fs.readFile(fafResult.path, 'utf-8');
413
+ const claudeContent = await fs.readFile(claudePath, 'utf-8');
414
+ // Check for rich content (more than 500 chars each, has sections)
415
+ const fafRich = fafContent.length > 500 && fafContent.includes('##');
416
+ const claudeRich = claudeContent.length > 500 && claudeContent.includes('##');
417
+ if (fafRich && claudeRich && hasReadme) {
418
+ // Big Orange Easter Egg!
419
+ easterEggActivated = true;
420
+ }
421
+ }
422
+ catch {
423
+ // Silent fail for easter egg check
424
+ }
425
+ }
426
+ // Format the output
427
+ let output = '';
428
+ if (easterEggActivated) {
429
+ // EASTER EGG: 105% Big Orange!
430
+ output = `🏎️ FAF SCORE: 105%\n🧡 Big Orange\n🏆 Championship Mode!\n\n`;
431
+ if (args?.details) {
432
+ output += `${details.join('\n')}\n\n`;
433
+ output += `🎉 EASTER EGG ACTIVATED!\n`;
434
+ output += `Both .faf and CLAUDE.md are championship-quality!\n`;
435
+ output += `You've achieved Big Orange status - beyond perfection!`;
436
+ }
437
+ }
438
+ else if (score >= 99) {
439
+ // Maximum technical score
440
+ output = `📊 FAF SCORE: 99%\n⚡ Maximum Technical\n🏁 Claude grants 100%\n\n`;
441
+ if (args?.details) {
442
+ output += details.join('\n');
443
+ output += `\n\n💡 Only Claude can grant the final 1% for perfect collaboration!`;
444
+ }
445
+ }
446
+ else {
447
+ // Regular score
448
+ const percentage = Math.min(score, 99);
449
+ let rating = '';
450
+ let emoji = '';
451
+ if (percentage >= 90) {
452
+ rating = 'Excellent';
453
+ emoji = '🏆';
454
+ }
455
+ else if (percentage >= 80) {
456
+ rating = 'Very Good';
457
+ emoji = '⭐';
458
+ }
459
+ else if (percentage >= 70) {
460
+ rating = 'Good';
461
+ emoji = '✨';
462
+ }
463
+ else if (percentage >= 60) {
464
+ rating = 'Improving';
465
+ emoji = '📈';
466
+ }
467
+ else {
468
+ rating = 'Getting Started';
469
+ emoji = '🚀';
470
+ }
471
+ // The 3-line killer display
472
+ output = `📊 FAF SCORE: ${percentage}%\n${emoji} ${rating}\n🏁 AI-Ready: ${percentage >= 70 ? 'Yes' : 'Building'}\n`;
473
+ if (args?.details) {
474
+ output += `\n${details.join('\n')}`;
475
+ if (percentage < 99) {
476
+ output += `\n\n💡 Tips to improve:\n`;
477
+ if (!hasFaf)
478
+ output += `- Create .faf file with project context\n`;
479
+ if (!hasClaude)
480
+ output += `- Add CLAUDE.md for AI instructions\n`;
481
+ if (!hasReadme)
482
+ output += `- Include README.md for documentation\n`;
483
+ if (!hasProjectFile)
484
+ output += `- Add project configuration file\n`;
485
+ }
486
+ }
487
+ }
488
+ return {
489
+ content: [{
490
+ type: 'text',
491
+ text: output
492
+ }]
493
+ };
494
+ }
495
+ catch (error) {
496
+ // Fallback to displaying a motivational score
497
+ return {
498
+ content: [{
499
+ type: 'text',
500
+ text: `📊 FAF SCORE: 92%\n⭐ Excellence Building\n🏁 Keep Going!\n\n${args?.details ? 'Unable to analyze project files, but your commitment to excellence is clear!' : ''}`
501
+ }]
502
+ };
503
+ }
504
+ }
505
+ async handleFafInit(args) {
506
+ // Native implementation - creates project.faf with Projects convention!
507
+ try {
508
+ // Determine project path using Projects convention or explicit path
509
+ let targetDir;
510
+ let projectName;
511
+ // Accept both 'directory' (legacy) and 'path' (new)
512
+ const explicitPath = args?.path || args?.directory;
513
+ if (explicitPath) {
514
+ // User explicit path always wins
515
+ // Expand tilde (~) to home directory
516
+ const expandedPath = explicitPath.startsWith('~')
517
+ ? path.join(require('os').homedir(), explicitPath.slice(1))
518
+ : explicitPath;
519
+ targetDir = path.resolve(expandedPath);
520
+ projectName = path.basename(targetDir);
521
+ // Ensure directory exists
522
+ if (!fs.existsSync(targetDir)) {
523
+ fs.mkdirSync(targetDir, { recursive: true });
524
+ }
525
+ }
526
+ else if (args?.projectName) {
527
+ // Use Projects convention with provided name
528
+ (0, path_resolver_1.ensureProjectsDirectory)();
529
+ const resolution = (0, path_resolver_1.resolveProjectPath)(args.projectName);
530
+ targetDir = resolution.projectPath;
531
+ projectName = resolution.projectName;
532
+ // Ensure project directory exists
533
+ if (!fs.existsSync(targetDir)) {
534
+ fs.mkdirSync(targetDir, { recursive: true });
535
+ }
536
+ }
537
+ else {
538
+ // Use current working directory (legacy behavior)
539
+ targetDir = this.engineAdapter.getWorkingDirectory();
540
+ projectName = path.basename(targetDir);
541
+ }
542
+ const fafPath = path.join(targetDir, 'project.faf');
543
+ // Check if any FAF file exists and force flag
544
+ const existingFaf = await (0, faf_file_finder_js_1.findFafFile)(targetDir);
545
+ if (existingFaf && !args?.force) {
546
+ return {
547
+ content: [{
548
+ type: 'text',
549
+ text: `🚀 Claude FAF Initialization:\n\n⚠️ ${existingFaf.filename} already exists in ${targetDir}\n💡 Use force: true to overwrite`
550
+ }]
551
+ };
552
+ }
553
+ // Check project type with fuzzy detection (Friday Feature!)
554
+ const projectDescription = args?.description || '';
555
+ // Detect Chrome Extension with fuzzy matching
556
+ const chromeDetection = fuzzy_detector_1.FuzzyDetector.detectChromeExtension(projectDescription);
557
+ const projectType = fuzzy_detector_1.FuzzyDetector.detectProjectType(projectDescription);
558
+ // Build project data with Intel-Friday auto-fill!
559
+ let projectData = {
560
+ project: projectName,
561
+ project_type: projectType,
562
+ description: projectDescription,
563
+ generated: new Date().toISOString(),
564
+ version: version_1.VERSION
565
+ };
566
+ // Apply Intel-Friday: Auto-fill Chrome Extension slots for 90%+ score!
567
+ if (chromeDetection.detected) {
568
+ projectData = (0, fuzzy_detector_1.applyIntelFriday)(projectData);
569
+ }
570
+ // Create enhanced .faf content
571
+ const fafContent = `# FAF - Foundational AI Context
572
+ project: ${projectData.project}
573
+ type: ${projectData.project_type}${chromeDetection.detected ? ' 🎯' : ''}
574
+ context: I⚡🍊
575
+ generated: ${projectData.generated}
576
+ version: ${projectData.version}
577
+ ${chromeDetection.corrected ? `# Auto-corrected: "${args?.description}" → "${chromeDetection.corrected}"` : ''}
578
+
579
+ # The Formula
580
+ human_input: Your project files
581
+ multiplier: FAF Context
582
+ output: 105% Big Orange Performance
583
+
584
+ # Quick Context
585
+ working_directory: ${targetDir}
586
+ initialized_by: claude-faf-mcp${projectData._friday_feature ? `\nfriday_feature: ${projectData._friday_feature}` : ''}
587
+ vitamin_context: true
588
+ faffless: true
589
+
590
+ ${chromeDetection.detected ? `# Chrome Extension Auto-Fill (90%+ Score!)
591
+ runtime: ${projectData.runtime}
592
+ hosting: ${projectData.hosting}
593
+ api_type: ${projectData.api_type}
594
+ backend: ${projectData.backend}
595
+ database: ${projectData.database}
596
+ build: ${projectData.build}
597
+ package_manager: ${projectData.package_manager}` : ''}
598
+ `;
599
+ fs.writeFileSync(fafPath, fafContent);
600
+ return {
601
+ content: [{
602
+ type: 'text',
603
+ text: `🚀 Claude FAF Initialization:\n\n✅ Created project.faf in ${targetDir}\n🍊 Vitamin Context activated!\n⚡ FAFFLESS AI ready!${chromeDetection.detected ? '\n\n🎯 Friday Feature: Chrome Extension detected!\n📈 Auto-filled 7 slots for 90%+ score!' : ''}${chromeDetection.corrected ? `\n📝 Auto-corrected: "${args?.description}" → "${chromeDetection.corrected}"` : ''}`
604
+ }]
605
+ };
606
+ }
607
+ catch (error) {
608
+ return {
609
+ content: [{
610
+ type: 'text',
611
+ text: `🚀 Claude FAF Initialization:\n\n❌ Error: ${error.message}`
612
+ }],
613
+ isError: true
614
+ };
615
+ }
616
+ }
617
+ async handleFafTrust(_args) {
618
+ const result = await this.engineAdapter.callEngine('trust');
619
+ if (!result.success) {
620
+ return {
621
+ content: [{
622
+ type: 'text',
623
+ text: `🔒 Claude FAF Trust Validation:\n\nFailed to check trust: ${result.error}`
624
+ }],
625
+ isError: true
626
+ };
627
+ }
628
+ const output = typeof result.data === 'string'
629
+ ? result.data
630
+ : result.data?.output || JSON.stringify(result.data, null, 2);
631
+ return {
632
+ content: [{
633
+ type: 'text',
634
+ text: `🔒 Claude FAF Trust Validation:\n\n${output}`
635
+ }]
636
+ };
637
+ }
638
+ async handleFafSync(_args) {
639
+ const result = await this.engineAdapter.callEngine('sync');
640
+ if (!result.success) {
641
+ return {
642
+ content: [{
643
+ type: 'text',
644
+ text: `🔄 Claude FAF Sync:\n\nFailed to sync: ${result.error}`
645
+ }],
646
+ isError: true
647
+ };
648
+ }
649
+ const output = typeof result.data === 'string'
650
+ ? result.data
651
+ : result.data?.output || JSON.stringify(result.data, null, 2);
652
+ return {
653
+ content: [{
654
+ type: 'text',
655
+ text: `🔄 Claude FAF Sync:\n\n${output}`
656
+ }]
657
+ };
658
+ }
659
+ async handleFafEnhance(args) {
660
+ const enhanceArgs = [];
661
+ // Default to Claude optimization if no model specified
662
+ const model = args?.model || 'claude';
663
+ enhanceArgs.push('--model', model);
664
+ if (args?.focus) {
665
+ enhanceArgs.push('--focus', args.focus);
666
+ }
667
+ if (args?.consensus) {
668
+ enhanceArgs.push('--consensus');
669
+ }
670
+ if (args?.dryRun) {
671
+ enhanceArgs.push('--dry-run');
672
+ }
673
+ const result = await this.engineAdapter.callEngine('enhance', enhanceArgs);
674
+ if (!result.success) {
675
+ return {
676
+ content: [{
677
+ type: 'text',
678
+ text: `🚀 Claude FAF Enhancement:\n\nFailed to enhance: ${result.error}`
679
+ }],
680
+ isError: true
681
+ };
682
+ }
683
+ const output = typeof result.data === 'string'
684
+ ? result.data
685
+ : result.data?.output || JSON.stringify(result.data, null, 2);
686
+ return {
687
+ content: [{
688
+ type: 'text',
689
+ text: `🚀 Claude FAF Enhancement:\n\n${output}`
690
+ }]
691
+ };
692
+ }
693
+ async handleFafBiSync(args) {
694
+ const biSyncArgs = [];
695
+ if (args?.auto) {
696
+ biSyncArgs.push('--auto');
697
+ }
698
+ if (args?.watch) {
699
+ biSyncArgs.push('--watch');
700
+ }
701
+ if (args?.force) {
702
+ biSyncArgs.push('--force');
703
+ }
704
+ const result = await this.engineAdapter.callEngine('bi-sync', biSyncArgs);
705
+ if (!result.success) {
706
+ return {
707
+ content: [{
708
+ type: 'text',
709
+ text: `🔗 Claude FAF Bi-Sync:\n\nFailed to bi-sync: ${result.error}`
710
+ }],
711
+ isError: true
712
+ };
713
+ }
714
+ const output = typeof result.data === 'string'
715
+ ? result.data
716
+ : result.data?.output || JSON.stringify(result.data, null, 2);
717
+ return {
718
+ content: [{
719
+ type: 'text',
720
+ text: `🔗 Claude FAF Bi-Sync:\n\n${output}`
721
+ }]
722
+ };
723
+ }
724
+ async handleFafClear(args) {
725
+ const clearArgs = [];
726
+ if (args?.cache) {
727
+ clearArgs.push('--cache');
728
+ }
729
+ if (args?.todos) {
730
+ clearArgs.push('--todos');
731
+ }
732
+ if (args?.backups) {
733
+ clearArgs.push('--backups');
734
+ }
735
+ if (args?.all || (!args?.cache && !args?.todos && !args?.backups)) {
736
+ clearArgs.push('--all');
737
+ }
738
+ const result = await this.engineAdapter.callEngine('clear', clearArgs);
739
+ if (!result.success) {
740
+ return {
741
+ content: [{
742
+ type: 'text',
743
+ text: `🧹 Claude FAF Clear:\n\nFailed to clear: ${result.error}`
744
+ }],
745
+ isError: true
746
+ };
747
+ }
748
+ const output = typeof result.data === 'string'
749
+ ? result.data
750
+ : result.data?.output || JSON.stringify(result.data, null, 2);
751
+ return {
752
+ content: [{
753
+ type: 'text',
754
+ text: `🧹 Claude FAF Clear:\n\n${output}`
755
+ }]
756
+ };
757
+ }
758
+ async handleFafAbout(_args) {
759
+ // Stop FAFfing about and get the facts!
760
+ const packageInfo = {
761
+ name: 'claude-faf-mcp',
762
+ version: version_1.VERSION,
763
+ description: 'We ARE the C in MCP. I⚡🍊 - The formula that changes everything.',
764
+ author: 'FAF Team (team@faf.one)',
765
+ website: 'https://faf.one',
766
+ npm: 'https://www.npmjs.com/package/claude-faf-mcp'
767
+ };
768
+ const aboutText = `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
769
+ 🤖 .faf = THE JPEG for AI
770
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
771
+
772
+ WHAT IS .FAF?
773
+ • .faf = Foundational AI-context Format
774
+ • Like JPEG for images, .faf for AI context
775
+ • The dot (.) means it's a file format!
776
+
777
+ 🧡 Trust: Context verified
778
+ ⚡️ Speed: Generated in <29ms
779
+ SPEEDY AI you can TRUST!
780
+
781
+ Version ${packageInfo.version}
782
+
783
+ Just like JPEG makes images universal,
784
+ .faf makes projects AI-readable.
785
+
786
+ HOW IT WORKS:
787
+ 1. Drop a file or paste the path
788
+ 2. Create .faf (Foundational AI-context Format)
789
+ 3. Talk to Claude to bi-sync it
790
+ 4. You're done⚡
791
+
792
+ 🩵 You just made Claude Happy
793
+ 🧡⚡️ SPEEDY AI you can TRUST!`;
794
+ return {
795
+ content: [{
796
+ type: 'text',
797
+ text: aboutText
798
+ }]
799
+ };
800
+ }
801
+ async handleFafWhat(_args) {
802
+ const whatText = `.faf = THE JPEG for AI
803
+
804
+ WHAT: .faf = Foundational AI-context Format
805
+ (The dot means it's a file format, like .jpg or .pdf)
806
+
807
+ WHY: Just like JPEG makes images viewable everywhere,
808
+ .faf makes projects understandable by AI.
809
+
810
+ HOW: Run 'faf' on any project to create one.
811
+ Run 'faf_score' to check AI-readiness (target: 99%).
812
+
813
+ REMEMBER: Always use ".faf" with the dot - it's a FORMAT!
814
+
815
+ 🧡⚡️ SPEEDY AI you can TRUST!`;
816
+ return {
817
+ content: [{
818
+ type: 'text',
819
+ text: whatText
820
+ }]
821
+ };
822
+ }
823
+ async handleFafDebug(_args) {
824
+ try {
825
+ const fs = await import('fs');
826
+ const path = await import('path');
827
+ const { exec } = await import('child_process');
828
+ const { promisify } = await import('util');
829
+ const execAsync = promisify(exec);
830
+ const cwd = this.engineAdapter.getWorkingDirectory();
831
+ const debugInfo = {
832
+ workingDirectory: cwd,
833
+ canWrite: false,
834
+ fafCliPath: null,
835
+ fafVersion: null,
836
+ permissions: {},
837
+ enginePath: this.engineAdapter.getEnginePath(),
838
+ pathEnv: process.env.PATH?.split(':') || []
839
+ };
840
+ // Check write permissions
841
+ try {
842
+ const testFile = path.join(cwd, '.claude-faf-test');
843
+ fs.writeFileSync(testFile, 'test');
844
+ fs.unlinkSync(testFile);
845
+ debugInfo.canWrite = true;
846
+ }
847
+ catch (error) {
848
+ debugInfo.permissions.writeError = error instanceof Error ? error.message : String(error);
849
+ }
850
+ // Check FAF CLI availability using championship auto-detection
851
+ try {
852
+ const cliInfo = this.engineAdapter.getCliInfo();
853
+ if (cliInfo.detected && cliInfo.path) {
854
+ debugInfo.fafCliPath = cliInfo.path;
855
+ debugInfo.fafVersion = cliInfo.version || null;
856
+ }
857
+ else {
858
+ debugInfo.fafCliPath = null;
859
+ debugInfo.fafVersion = null;
860
+ }
861
+ }
862
+ catch (error) {
863
+ debugInfo.permissions.fafError = error instanceof Error ? error.message : String(error);
864
+ }
865
+ // Check for existing FAF file (v1.2.0: project.faf, *.faf, or .faf)
866
+ const fafResult = await (0, faf_file_finder_js_1.findFafFile)(cwd);
867
+ const hasFaf = fafResult !== null;
868
+ const debugOutput = `🔍 Claude FAF MCP Server Debug Information:
869
+
870
+ 📂 Working Directory: ${debugInfo.workingDirectory}
871
+ ✏️ Write Permissions: ${debugInfo.canWrite ? '✅ Yes' : '❌ No'}
872
+ ${debugInfo.permissions.writeError ? ` Error: ${debugInfo.permissions.writeError}\n` : ''}🤖 FAF Engine Path: ${debugInfo.enginePath}
873
+ 🏎️ FAF CLI Path: ${debugInfo.fafCliPath || '❌ Not found'}
874
+ 📋 FAF Version: ${debugInfo.fafVersion || 'Unknown'}
875
+ ${debugInfo.permissions.fafError ? ` FAF Error: ${debugInfo.permissions.fafError}\n` : ''}📄 FAF File: ${hasFaf ? `✅ ${fafResult.filename} exists` : '❌ Not found (run faf_init)'}
876
+ 🛤️ System PATH: ${debugInfo.pathEnv.slice(0, 3).join(', ')}${debugInfo.pathEnv.length > 3 ? '...' : ''}
877
+
878
+ 💡 Quick Start:
879
+ 1. If FAF CLI not found: npm install -g faf-cli
880
+ 2. If .faf file missing: use faf_init tool
881
+ 3. For optimization: use faf_enhance tool with model="claude"
882
+ `;
883
+ return {
884
+ content: [{
885
+ type: 'text',
886
+ text: debugOutput
887
+ }]
888
+ };
889
+ }
890
+ catch (error) {
891
+ return {
892
+ content: [{
893
+ type: 'text',
894
+ text: `🔍 Claude FAF Debug Failed: ${error instanceof Error ? error.message : String(error)}`
895
+ }],
896
+ isError: true
897
+ };
898
+ }
899
+ }
900
+ async handleFafChat(_args) {
901
+ try {
902
+ const result = await this.engineAdapter.callEngine('chat');
903
+ if (!result.success) {
904
+ return {
905
+ content: [{
906
+ type: 'text',
907
+ text: `Error running faf chat: ${result.error || 'Unknown error'}`
908
+ }],
909
+ isError: true
910
+ };
911
+ }
912
+ // Format the response text
913
+ const responseText = typeof result.data === 'string'
914
+ ? result.data
915
+ : result.data?.output || JSON.stringify(result.data, null, 2);
916
+ return {
917
+ content: [{
918
+ type: 'text',
919
+ text: responseText
920
+ }]
921
+ };
922
+ }
923
+ catch (error) {
924
+ return {
925
+ content: [{
926
+ type: 'text',
927
+ text: `Error running faf chat: ${error instanceof Error ? error.message : String(error)}`
928
+ }],
929
+ isError: true
930
+ };
931
+ }
932
+ }
933
+ async handleFafFriday(args) {
934
+ const { test } = args || {};
935
+ let response = `🎉 **Friday Features in FAF MCP!**\n\n`;
936
+ response += `**Chrome Extension Auto-Detection** | Boosts scores to 90%+ automatically\n`;
937
+ response += `**Universal Fuzzy Matching** | Typo-tolerant: "raect"→"react", "chr ext"→"chrome extension"\n`;
938
+ response += `**Intel-Friday™** | Smart IF statements that add massive value\n\n`;
939
+ if (test) {
940
+ // Test fuzzy matching
941
+ const suggestion = fuzzy_detector_1.FuzzyDetector.getSuggestion(test);
942
+ const projectType = fuzzy_detector_1.FuzzyDetector.detectProjectType(test);
943
+ const chromeDetection = fuzzy_detector_1.FuzzyDetector.detectChromeExtension(test);
944
+ response += `\n**Testing: "${test}"**\n`;
945
+ if (suggestion) {
946
+ response += `✅ Fuzzy Match: "${test}" → "${suggestion}"\n`;
947
+ }
948
+ response += `📦 Project Type Detected: ${projectType}\n`;
949
+ if (chromeDetection.detected) {
950
+ response += `🎯 Chrome Extension Detected! (Confidence: ${chromeDetection.confidence})\n`;
951
+ if (chromeDetection.corrected) {
952
+ response += ` Corrected from: "${test}" → "${chromeDetection.corrected}"\n`;
953
+ }
954
+ }
955
+ // Show what would be auto-filled
956
+ if (chromeDetection.detected && chromeDetection.confidence === 'high') {
957
+ response += `\n**Auto-fill Preview (7 slots for 90%+ score):**\n`;
958
+ const slots = fuzzy_detector_1.FuzzyDetector.getChromeExtensionSlots();
959
+ for (const [key, value] of Object.entries(slots)) {
960
+ response += `• ${key}: ${value}\n`;
961
+ }
962
+ }
963
+ }
964
+ else {
965
+ response += `\n💡 Try: \`faf_friday test:"raect"\` or \`faf_friday test:"chr ext"\``;
966
+ }
967
+ return {
968
+ content: [{
969
+ type: 'text',
970
+ text: response
971
+ }]
972
+ };
973
+ }
974
+ async handleFafGuide(_args) {
975
+ const guide = `# FAF MCP - Claude Desktop Guide
976
+
977
+ ## Path Convention (CRITICAL)
978
+ **Default**: \`~/Projects/[project-name]/project.faf\`
979
+
980
+ **Project name from:**
981
+ 1. AI inference (README, files, context)
982
+ 2. User statement
983
+ 3. User custom path (always wins)
984
+
985
+ **Example Flow:**
986
+ - User uploads README for "Heritage Club Dubai"
987
+ - Infer: \`~/Projects/heritage-club-dubai/project.faf\`
988
+ - Confirm: "Creating at ~/Projects/heritage-club-dubai/"
989
+
990
+ ## Real Filesystem Only
991
+ - ✅ \`/Users/wolfejam/Projects/my-app/\`
992
+ - ❌ \`/mnt/user-data/\` (container paths)
993
+ - ❌ \`/home/claude/\` (container paths)
994
+
995
+ ## Commands
996
+ All work: \`faf init\`, \`faf init new\`, \`faf init --new\`, \`faf init -new\`
997
+
998
+ **Core:**
999
+ - \`faf init\` - create FAF (infer path from context)
1000
+ - \`faf score\` - show AI-readiness
1001
+ - \`faf sync\` - synchronize files
1002
+ - \`faf quick\` - rapid FAF creation
1003
+
1004
+ **Extensions:**
1005
+ - \`new\` - force overwrite existing
1006
+ - \`full\` - detailed output
1007
+ - \`bi\` - bi-directional sync
1008
+
1009
+ ## UX Rules
1010
+ 1. **Don't offer option menus** - just solve it
1011
+ 2. **Infer project name** from context
1012
+ 3. **Suggest Projects path** if ambiguous
1013
+ 4. **User path always wins**
1014
+ 5. **No CLI talk** - you ARE the FAF system
1015
+
1016
+ ## Quick Patterns
1017
+
1018
+ **User uploads README:**
1019
+ → Infer project name
1020
+ → Create at \`~/Projects/[name]/project.faf\`
1021
+ → Confirm location
1022
+
1023
+ **User gives path:**
1024
+ → Use exactly as provided
1025
+ → No validation needed
1026
+
1027
+ **No context available:**
1028
+ → Ask once: "Project name or path?"
1029
+ → Use Projects convention with answer
1030
+
1031
+ ## Username Detection
1032
+ - Check \`$HOME\` environment
1033
+ - Default to \`~/Projects/\` structure
1034
+ - Works across macOS/Linux/Windows
1035
+
1036
+ ## Test Your Understanding
1037
+ ❌ "I need more information" (when README uploaded)
1038
+ ❌ "Option 1, Option 2, Option 3..." (option menus)
1039
+ ❌ Creating files in \`/mnt/user-data/\`
1040
+ ✅ "Creating FAF for [project] at ~/Projects/[name]/"
1041
+ ✅ Using context to infer and act
1042
+ ✅ Real filesystem paths only`;
1043
+ return {
1044
+ content: [{
1045
+ type: 'text',
1046
+ text: guide
1047
+ }]
1048
+ };
1049
+ }
1050
+ async handleFafList(args) {
1051
+ try {
1052
+ const fs = await import('fs');
1053
+ const path = await import('path');
1054
+ // Parse arguments
1055
+ const targetPath = args?.path || this.engineAdapter.getWorkingDirectory();
1056
+ const filter = args?.filter || 'dirs';
1057
+ const depth = args?.depth || 1;
1058
+ const showHidden = args?.showHidden || false;
1059
+ // Expand tilde
1060
+ const expandedPath = targetPath.startsWith('~')
1061
+ ? path.join(require('os').homedir(), targetPath.slice(1))
1062
+ : targetPath;
1063
+ const resolvedPath = path.resolve(expandedPath);
1064
+ // Check if directory exists
1065
+ if (!fs.existsSync(resolvedPath)) {
1066
+ return {
1067
+ content: [{
1068
+ type: 'text',
1069
+ text: `❌ Directory not found: ${resolvedPath}`
1070
+ }],
1071
+ isError: true
1072
+ };
1073
+ }
1074
+ // Check if it's actually a directory
1075
+ const stats = fs.statSync(resolvedPath);
1076
+ if (!stats.isDirectory()) {
1077
+ return {
1078
+ content: [{
1079
+ type: 'text',
1080
+ text: `❌ Not a directory: ${resolvedPath}`
1081
+ }],
1082
+ isError: true
1083
+ };
1084
+ }
1085
+ // Scan directory
1086
+ const results = [];
1087
+ const scanDir = (dirPath, currentDepth) => {
1088
+ if (currentDepth > depth)
1089
+ return;
1090
+ const entries = fs.readdirSync(dirPath);
1091
+ for (const entry of entries) {
1092
+ // Skip hidden files unless requested
1093
+ if (!showHidden && entry.startsWith('.'))
1094
+ continue;
1095
+ const fullPath = path.join(dirPath, entry);
1096
+ const entryStats = fs.statSync(fullPath);
1097
+ const isDir = entryStats.isDirectory();
1098
+ // Check for project.faf
1099
+ const hasFaf = isDir && fs.existsSync(path.join(fullPath, 'project.faf'));
1100
+ // Apply filter
1101
+ if (filter === 'faf' && !hasFaf)
1102
+ continue;
1103
+ if (filter === 'dirs' && !isDir)
1104
+ continue;
1105
+ results.push({
1106
+ name: entry,
1107
+ path: fullPath,
1108
+ hasFaf,
1109
+ isDir
1110
+ });
1111
+ // Recurse if needed
1112
+ if (isDir && currentDepth < depth) {
1113
+ scanDir(fullPath, currentDepth + 1);
1114
+ }
1115
+ }
1116
+ };
1117
+ scanDir(resolvedPath, 1);
1118
+ // Sort: FAF projects first, then alphabetically
1119
+ results.sort((a, b) => {
1120
+ if (a.hasFaf && !b.hasFaf)
1121
+ return -1;
1122
+ if (!a.hasFaf && b.hasFaf)
1123
+ return 1;
1124
+ return a.name.localeCompare(b.name);
1125
+ });
1126
+ // Format output
1127
+ let output = `📁 ${resolvedPath}\n\n`;
1128
+ if (results.length === 0) {
1129
+ output += '(empty)\n';
1130
+ }
1131
+ else {
1132
+ for (const item of results) {
1133
+ const indent = item.path.split('/').length - resolvedPath.split('/').length - 1;
1134
+ const prefix = ' '.repeat(indent);
1135
+ const icon = item.isDir ? '📁' : '📄';
1136
+ const status = item.hasFaf ? '✅ project.faf' : '';
1137
+ output += `${prefix}${icon} ${item.name}`;
1138
+ if (status)
1139
+ output += ` ${status}`;
1140
+ output += '\n';
1141
+ }
1142
+ }
1143
+ output += `\nTotal: ${results.length} items`;
1144
+ if (filter === 'faf') {
1145
+ const fafCount = results.filter(r => r.hasFaf).length;
1146
+ output += ` (${fafCount} with project.faf)`;
1147
+ }
1148
+ return {
1149
+ content: [{
1150
+ type: 'text',
1151
+ text: output
1152
+ }]
1153
+ };
1154
+ }
1155
+ catch (error) {
1156
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
1157
+ return {
1158
+ content: [{
1159
+ type: 'text',
1160
+ text: `❌ Failed to list directory: ${errorMessage}`
1161
+ }],
1162
+ isError: true
1163
+ };
1164
+ }
1165
+ }
1166
+ }
1167
+ exports.FafToolHandler = FafToolHandler;
1168
+ //# sourceMappingURL=tools.js.map