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,175 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Discord Documentation Sync Tool (Simplified)
5
+ * Posts FAF documentation to Discord as messages
6
+ *
7
+ * Usage: node scripts/discord-sync-simple.js <webhook-url>
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const https = require('https');
13
+
14
+ const DOCS_DIR = path.join(__dirname, '../docs');
15
+
16
+ // Documentation files to sync
17
+ const DOCS_TO_SYNC = [
18
+ {
19
+ file: 'QUICK_START.md',
20
+ title: '๐Ÿš€ **Quick Start Guide**',
21
+ url: 'https://faf.one',
22
+ order: 1
23
+ },
24
+ {
25
+ file: 'FAQ.md',
26
+ title: 'โ“ **Frequently Asked Questions**',
27
+ url: 'https://faf.one',
28
+ order: 2
29
+ },
30
+ {
31
+ file: 'USER_GUIDE.md',
32
+ title: '๐Ÿ“š **User Guide**',
33
+ url: 'https://faf.one',
34
+ order: 3
35
+ },
36
+ {
37
+ file: 'PODIUM-SYSTEM.md',
38
+ title: '๐Ÿ† **Podium Scoring System**',
39
+ url: 'https://faf.one',
40
+ order: 4
41
+ }
42
+ ];
43
+
44
+ function postToDiscord(webhookUrl, content) {
45
+ return new Promise((resolve, reject) => {
46
+ const url = new URL(webhookUrl);
47
+ const payload = JSON.stringify({ content });
48
+
49
+ const options = {
50
+ hostname: url.hostname,
51
+ path: url.pathname + url.search,
52
+ method: 'POST',
53
+ headers: {
54
+ 'Content-Type': 'application/json',
55
+ 'Content-Length': payload.length
56
+ }
57
+ };
58
+
59
+ const req = https.request(options, (res) => {
60
+ if (res.statusCode === 204 || res.statusCode === 200) {
61
+ resolve();
62
+ } else {
63
+ let body = '';
64
+ res.on('data', chunk => body += chunk);
65
+ res.on('end', () => {
66
+ reject(new Error(`Discord returned status ${res.statusCode}: ${body}`));
67
+ });
68
+ }
69
+ });
70
+
71
+ req.on('error', reject);
72
+ req.write(payload);
73
+ req.end();
74
+ });
75
+ }
76
+
77
+ function createSummary(content, maxLength = 1500) {
78
+ const lines = content.split('\n');
79
+ let summary = '';
80
+ let lineCount = 0;
81
+
82
+ for (const line of lines) {
83
+ // Skip title lines
84
+ if (line.startsWith('# ')) continue;
85
+
86
+ summary += line + '\n';
87
+ lineCount++;
88
+
89
+ // Stop at reasonable length or after good amount of content
90
+ if (summary.length > maxLength || lineCount > 30) {
91
+ break;
92
+ }
93
+ }
94
+
95
+ return summary.trim();
96
+ }
97
+
98
+ async function syncDocs(webhookUrl) {
99
+ console.log('๐Ÿ”„ Starting Discord documentation sync...\n');
100
+
101
+ // Post intro message
102
+ const introMessage = `## ๐Ÿ“š FAF Documentation
103
+
104
+ Welcome to the FAF (Foundational AI-context Format) documentation!
105
+
106
+ **๐Ÿงก IANA-registered format** ยท \`application/vnd.faf+yaml\`
107
+ **๐Ÿ“ฆ MCP:** 6.1k downloads, 1,231/week
108
+ **โšก CLI:** 6.2k downloads, 235/week
109
+
110
+ Full docs available at **https://faf.one**
111
+
112
+ ---`;
113
+
114
+ try {
115
+ await postToDiscord(webhookUrl, introMessage);
116
+ console.log('โœ… Posted intro message');
117
+ await new Promise(resolve => setTimeout(resolve, 1000));
118
+ } catch (error) {
119
+ console.error('โŒ Failed to post intro:', error.message);
120
+ }
121
+
122
+ // Sort docs by order
123
+ const sortedDocs = DOCS_TO_SYNC.sort((a, b) => a.order - b.order);
124
+
125
+ for (const doc of sortedDocs) {
126
+ const filePath = path.join(DOCS_DIR, doc.file);
127
+
128
+ if (!fs.existsSync(filePath)) {
129
+ console.log(`โš ๏ธ Skipping ${doc.file} (not found)`);
130
+ continue;
131
+ }
132
+
133
+ const content = fs.readFileSync(filePath, 'utf-8');
134
+ const summary = createSummary(content);
135
+
136
+ const message = `${doc.title}
137
+
138
+ ${summary}
139
+
140
+ **[Read full guide โ†’](${doc.url})**`;
141
+
142
+ try {
143
+ await postToDiscord(webhookUrl, message);
144
+ console.log(`โœ… Posted ${doc.title}`);
145
+
146
+ // Rate limit: Discord allows 5 requests per 2 seconds
147
+ await new Promise(resolve => setTimeout(resolve, 1000));
148
+ } catch (error) {
149
+ console.error(`โŒ Failed to post ${doc.title}:`, error.message);
150
+ }
151
+ }
152
+
153
+ console.log('\nโœจ Sync complete!');
154
+ }
155
+
156
+ // Main execution
157
+ if (require.main === module) {
158
+ const webhookUrl = process.argv[2];
159
+
160
+ if (!webhookUrl) {
161
+ console.error('Usage: node scripts/discord-sync-simple.js <webhook-url>');
162
+ console.error('\nGet your webhook URL from Discord:');
163
+ console.error('1. Server Settings > Integrations > Webhooks');
164
+ console.error('2. Create New Webhook or use existing');
165
+ console.error('3. Copy Webhook URL');
166
+ process.exit(1);
167
+ }
168
+
169
+ syncDocs(webhookUrl).catch((error) => {
170
+ console.error('Fatal error:', error);
171
+ process.exit(1);
172
+ });
173
+ }
174
+
175
+ module.exports = { syncDocs };
@@ -0,0 +1,187 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Discord Documentation Sync Tool (Working Version)
5
+ * Posts FAF documentation to Discord as properly formatted messages
6
+ *
7
+ * Usage: node scripts/discord-sync-working.js <webhook-url>
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const https = require('https');
13
+
14
+ const DOCS_DIR = path.join(__dirname, '../docs');
15
+
16
+ // Documentation files to sync
17
+ const DOCS_TO_SYNC = [
18
+ {
19
+ file: 'QUICK_START.md',
20
+ title: '๐Ÿš€ Quick Start Guide',
21
+ url: 'https://faf.one',
22
+ order: 1
23
+ },
24
+ {
25
+ file: 'FAQ.md',
26
+ title: 'โ“ Frequently Asked Questions',
27
+ url: 'https://faf.one',
28
+ order: 2
29
+ },
30
+ {
31
+ file: 'USER_GUIDE.md',
32
+ title: '๐Ÿ“š User Guide',
33
+ url: 'https://faf.one',
34
+ order: 3
35
+ },
36
+ {
37
+ file: 'PODIUM-SYSTEM.md',
38
+ title: '๐Ÿ† Podium Scoring System',
39
+ url: 'https://faf.one',
40
+ order: 4
41
+ }
42
+ ];
43
+
44
+ function postToDiscord(webhookUrl, content) {
45
+ return new Promise((resolve, reject) => {
46
+ const url = new URL(webhookUrl);
47
+
48
+ // Create clean payload - only content field
49
+ const payload = JSON.stringify({
50
+ content: content.substring(0, 2000) // Discord limit is 2000 chars per message
51
+ });
52
+
53
+ const options = {
54
+ hostname: url.hostname,
55
+ path: url.pathname + url.search,
56
+ method: 'POST',
57
+ headers: {
58
+ 'Content-Type': 'application/json',
59
+ 'Content-Length': Buffer.byteLength(payload)
60
+ }
61
+ };
62
+
63
+ const req = https.request(options, (res) => {
64
+ let body = '';
65
+ res.on('data', chunk => body += chunk);
66
+ res.on('end', () => {
67
+ if (res.statusCode === 204 || res.statusCode === 200) {
68
+ resolve();
69
+ } else {
70
+ reject(new Error(`Discord returned status ${res.statusCode}: ${body}`));
71
+ }
72
+ });
73
+ });
74
+
75
+ req.on('error', reject);
76
+ req.write(payload);
77
+ req.end();
78
+ });
79
+ }
80
+
81
+ function createSummary(content, maxLength = 1800) {
82
+ const lines = content.split('\n');
83
+ let summary = '';
84
+ let lineCount = 0;
85
+
86
+ for (const line of lines) {
87
+ // Skip main title (first # line)
88
+ if (lineCount === 0 && line.startsWith('# ')) {
89
+ lineCount++;
90
+ continue;
91
+ }
92
+
93
+ // Stop if we're getting too long
94
+ if (summary.length + line.length > maxLength) {
95
+ break;
96
+ }
97
+
98
+ // Stop after reasonable number of lines
99
+ if (lineCount > 40) {
100
+ break;
101
+ }
102
+
103
+ summary += line + '\n';
104
+ lineCount++;
105
+ }
106
+
107
+ return summary.trim();
108
+ }
109
+
110
+ async function syncDocs(webhookUrl) {
111
+ console.log('๐Ÿ”„ Starting Discord documentation sync...\n');
112
+
113
+ // Post intro message
114
+ const introMessage = `**๐Ÿ“š FAF Documentation**
115
+
116
+ Welcome to the FAF (Foundational AI-context Format) documentation!
117
+
118
+ ๐Ÿงก **IANA-registered format** โ€ข \`application/vnd.faf+yaml\`
119
+ ๐Ÿ“ฆ **MCP:** 6.1k downloads, 1,231/week
120
+ โšก **CLI:** 6.2k downloads, 235/week
121
+
122
+ Full docs available at **https://faf.one**
123
+
124
+ โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”`;
125
+
126
+ try {
127
+ await postToDiscord(webhookUrl, introMessage);
128
+ console.log('โœ… Posted intro message');
129
+ await new Promise(resolve => setTimeout(resolve, 1000));
130
+ } catch (error) {
131
+ console.error('โŒ Failed to post intro:', error.message);
132
+ }
133
+
134
+ // Sort docs by order
135
+ const sortedDocs = DOCS_TO_SYNC.sort((a, b) => a.order - b.order);
136
+
137
+ for (const doc of sortedDocs) {
138
+ const filePath = path.join(DOCS_DIR, doc.file);
139
+
140
+ if (!fs.existsSync(filePath)) {
141
+ console.log(`โš ๏ธ Skipping ${doc.file} (not found)`);
142
+ continue;
143
+ }
144
+
145
+ const content = fs.readFileSync(filePath, 'utf-8');
146
+ const summary = createSummary(content);
147
+
148
+ const message = `**${doc.title}**
149
+
150
+ ${summary}
151
+
152
+ **[Read full guide โ†’](${doc.url})**`;
153
+
154
+ try {
155
+ await postToDiscord(webhookUrl, message);
156
+ console.log(`โœ… Posted ${doc.title}`);
157
+
158
+ // Rate limit: Discord allows 5 requests per 2 seconds
159
+ await new Promise(resolve => setTimeout(resolve, 1000));
160
+ } catch (error) {
161
+ console.error(`โŒ Failed to post ${doc.title}:`, error.message);
162
+ }
163
+ }
164
+
165
+ console.log('\nโœจ Sync complete!');
166
+ }
167
+
168
+ // Main execution
169
+ if (require.main === module) {
170
+ const webhookUrl = process.argv[2];
171
+
172
+ if (!webhookUrl) {
173
+ console.error('Usage: node scripts/discord-sync-working.js <webhook-url>');
174
+ console.error('\nGet your webhook URL from Discord:');
175
+ console.error('1. Server Settings > Integrations > Webhooks');
176
+ console.error('2. Create New Webhook or use existing');
177
+ console.error('3. Copy Webhook URL');
178
+ process.exit(1);
179
+ }
180
+
181
+ syncDocs(webhookUrl).catch((error) => {
182
+ console.error('Fatal error:', error);
183
+ process.exit(1);
184
+ });
185
+ }
186
+
187
+ module.exports = { syncDocs };
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Discord Documentation Sync Tool
5
+ * Posts FAF documentation to Discord using webhooks
6
+ *
7
+ * Usage: node scripts/discord-sync.js <webhook-url>
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+ const https = require('https');
13
+
14
+ const DOCS_DIR = path.join(__dirname, '../docs');
15
+ const MAX_EMBED_LENGTH = 4096;
16
+ const CYAN_COLOR = 0x00D4D4; // FAF cyan
17
+
18
+ // Documentation files to sync
19
+ const DOCS_TO_SYNC = [
20
+ {
21
+ file: 'QUICK_START.md',
22
+ title: '๐Ÿš€ Quick Start Guide',
23
+ description: '5-minute setup for claude-faf-mcp',
24
+ order: 1
25
+ },
26
+ {
27
+ file: 'FAQ.md',
28
+ title: 'โ“ Frequently Asked Questions',
29
+ description: 'Common questions and answers',
30
+ order: 2
31
+ },
32
+ {
33
+ file: 'USER_GUIDE.md',
34
+ title: '๐Ÿ“š User Guide',
35
+ description: 'Complete guide to MCP features',
36
+ order: 3
37
+ },
38
+ {
39
+ file: 'PODIUM-SYSTEM.md',
40
+ title: '๐Ÿ† Podium Scoring System',
41
+ description: 'F1-inspired scoring tiers',
42
+ order: 4
43
+ }
44
+ ];
45
+
46
+ function postToDiscord(webhookUrl, embed) {
47
+ return new Promise((resolve, reject) => {
48
+ const url = new URL(webhookUrl);
49
+ const payload = JSON.stringify({
50
+ embeds: [embed]
51
+ });
52
+
53
+ const options = {
54
+ hostname: url.hostname,
55
+ path: url.pathname + url.search,
56
+ method: 'POST',
57
+ headers: {
58
+ 'Content-Type': 'application/json',
59
+ 'Content-Length': payload.length
60
+ }
61
+ };
62
+
63
+ const req = https.request(options, (res) => {
64
+ if (res.statusCode === 204) {
65
+ resolve();
66
+ } else {
67
+ reject(new Error(`Discord returned status ${res.statusCode}`));
68
+ }
69
+ });
70
+
71
+ req.on('error', reject);
72
+ req.write(payload);
73
+ req.end();
74
+ });
75
+ }
76
+
77
+ function truncateContent(content, maxLength) {
78
+ if (content.length <= maxLength) {
79
+ return content;
80
+ }
81
+
82
+ const truncated = content.substring(0, maxLength - 50);
83
+ const lastNewline = truncated.lastIndexOf('\n');
84
+
85
+ return truncated.substring(0, lastNewline > 0 ? lastNewline : maxLength - 50) +
86
+ '\n\n...(view full docs at faf.one)';
87
+ }
88
+
89
+ function extractSummary(content) {
90
+ // Extract first few sections only (intro + first topic)
91
+ const lines = content.split('\n');
92
+ let summary = '';
93
+ let sectionCount = 0;
94
+
95
+ for (const line of lines) {
96
+ if (line.startsWith('# ')) {
97
+ // Skip title
98
+ continue;
99
+ }
100
+
101
+ if (line.startsWith('## ')) {
102
+ sectionCount++;
103
+ if (sectionCount > 2) break; // Stop after 2 sections
104
+ }
105
+
106
+ summary += line + '\n';
107
+
108
+ if (summary.length > 1500) {
109
+ break;
110
+ }
111
+ }
112
+
113
+ return summary.trim() + '\n\n**[View full documentation โ†’](https://faf.one)**';
114
+ }
115
+
116
+ function formatMarkdownForDiscord(content) {
117
+ // Extract just a summary instead of full content
118
+ return extractSummary(content);
119
+ }
120
+
121
+ async function syncDocs(webhookUrl) {
122
+ console.log('๐Ÿ”„ Starting Discord documentation sync...\n');
123
+
124
+ // Sort docs by order
125
+ const sortedDocs = DOCS_TO_SYNC.sort((a, b) => a.order - b.order);
126
+
127
+ for (const doc of sortedDocs) {
128
+ const filePath = path.join(DOCS_DIR, doc.file);
129
+
130
+ if (!fs.existsSync(filePath)) {
131
+ console.log(`โš ๏ธ Skipping ${doc.file} (not found)`);
132
+ continue;
133
+ }
134
+
135
+ const content = fs.readFileSync(filePath, 'utf-8');
136
+ const formattedContent = formatMarkdownForDiscord(content);
137
+
138
+ const embed = {
139
+ title: doc.title,
140
+ description: formattedContent,
141
+ color: CYAN_COLOR,
142
+ footer: {
143
+ text: '๐Ÿงก faf.one โ€ข IANA-registered AI Context format'
144
+ },
145
+ timestamp: new Date().toISOString()
146
+ };
147
+
148
+ try {
149
+ await postToDiscord(webhookUrl, embed);
150
+ console.log(`โœ… Posted ${doc.title}`);
151
+
152
+ // Rate limit: Discord allows 5 requests per 2 seconds
153
+ await new Promise(resolve => setTimeout(resolve, 500));
154
+ } catch (error) {
155
+ console.error(`โŒ Failed to post ${doc.title}:`, error.message);
156
+ }
157
+ }
158
+
159
+ console.log('\nโœจ Sync complete!');
160
+ }
161
+
162
+ // Main execution
163
+ if (require.main === module) {
164
+ const webhookUrl = process.argv[2];
165
+
166
+ if (!webhookUrl) {
167
+ console.error('Usage: node scripts/discord-sync.js <webhook-url>');
168
+ console.error('\nGet your webhook URL from Discord:');
169
+ console.error('1. Server Settings > Integrations > Webhooks');
170
+ console.error('2. Create New Webhook or use existing');
171
+ console.error('3. Copy Webhook URL');
172
+ process.exit(1);
173
+ }
174
+
175
+ syncDocs(webhookUrl).catch((error) => {
176
+ console.error('Fatal error:', error);
177
+ process.exit(1);
178
+ });
179
+ }
180
+
181
+ module.exports = { syncDocs, formatMarkdownForDiscord };
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Post-install check: Verify faf-cli is installed
5
+ *
6
+ * This script runs after npm install to ensure users installed
7
+ * faf-cli BEFORE claude-faf-mcp (required installation order).
8
+ */
9
+
10
+ const { execSync } = require('child_process');
11
+ const os = require('os');
12
+
13
+ function checkFafCli() {
14
+ try {
15
+ // Try to find faf CLI
16
+ const command = os.platform() === 'win32' ? 'where faf' : 'which faf';
17
+ execSync(command, { stdio: 'ignore' });
18
+
19
+ // CLI found - success!
20
+ console.log('โœ… faf-cli detected - installation order correct');
21
+ return true;
22
+ } catch (error) {
23
+ // CLI not found - warn user
24
+ console.error('');
25
+ console.error('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
26
+ console.error('โš ๏ธ WARNING: faf-cli NOT DETECTED');
27
+ console.error('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
28
+ console.error('');
29
+ console.error('claude-faf-mcp requires faf-cli to be installed FIRST.');
30
+ console.error('');
31
+ console.error('CORRECT INSTALLATION ORDER:');
32
+ console.error(' 1๏ธโƒฃ npm install -g faf-cli (DO THIS FIRST)');
33
+ console.error(' 2๏ธโƒฃ npm install -g claude-faf-mcp (ALREADY DONE)');
34
+ console.error('');
35
+ console.error('Please install faf-cli now:');
36
+ console.error(' npm install -g faf-cli');
37
+ console.error('');
38
+ console.error('Then restart Claude Desktop to use all MCP features.');
39
+ console.error('โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”');
40
+ console.error('');
41
+ return false;
42
+ }
43
+ }
44
+
45
+ // Run check
46
+ checkFafCli();