fa-mcp-sdk 0.2.120 → 0.2.125

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 (97) hide show
  1. package/bin/fa-mcp.js +84 -24
  2. package/cli-template/config/_local.yaml +21 -1
  3. package/cli-template/config/custom-environment-variables.yaml +11 -1
  4. package/cli-template/config/default.yaml +11 -1
  5. package/cli-template/fa-mcp-sdk-spec.md +385 -2
  6. package/cli-template/package.json +72 -73
  7. package/cli-template/src/_examples/custom-basic-auth-example.ts +252 -0
  8. package/cli-template/src/_examples/multi-auth-examples.ts +333 -0
  9. package/cli-template/src/custom-resources.ts +1 -0
  10. package/cli-template/yarn.lock +6375 -0
  11. package/dist/core/_types_/TNtlm.d.ts +5 -0
  12. package/dist/core/_types_/TNtlm.d.ts.map +1 -0
  13. package/dist/core/_types_/TNtlm.js +2 -0
  14. package/dist/core/_types_/TNtlm.js.map +1 -0
  15. package/dist/core/_types_/config.d.ts +88 -0
  16. package/dist/core/_types_/config.d.ts.map +1 -0
  17. package/dist/core/_types_/config.js +2 -0
  18. package/dist/core/_types_/config.js.map +1 -0
  19. package/dist/core/_types_/types.d.ts +8 -0
  20. package/dist/core/_types_/types.d.ts.map +1 -1
  21. package/dist/core/{token/token-core.d.ts → auth/jwt-validation.d.ts} +2 -2
  22. package/dist/core/auth/jwt-validation.d.ts.map +1 -0
  23. package/dist/core/{token/token-core.js → auth/jwt-validation.js} +4 -4
  24. package/dist/core/auth/jwt-validation.js.map +1 -0
  25. package/dist/core/auth/middleware.d.ts +47 -0
  26. package/dist/core/auth/middleware.d.ts.map +1 -0
  27. package/dist/core/{token/token-auth.js → auth/middleware.js} +114 -2
  28. package/dist/core/auth/middleware.js.map +1 -0
  29. package/dist/core/auth/multi-auth.d.ts +27 -0
  30. package/dist/core/auth/multi-auth.d.ts.map +1 -0
  31. package/dist/core/auth/multi-auth.js +300 -0
  32. package/dist/core/auth/multi-auth.js.map +1 -0
  33. package/dist/core/auth/token-generator/html.d.ts.map +1 -0
  34. package/dist/core/{token/gen-token-app → auth/token-generator}/html.js +2 -2
  35. package/dist/core/auth/token-generator/html.js.map +1 -0
  36. package/dist/core/auth/token-generator/ntlm-auth-options.d.ts.map +1 -0
  37. package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-auth-options.js +1 -1
  38. package/dist/core/auth/token-generator/ntlm-auth-options.js.map +1 -0
  39. package/dist/core/auth/token-generator/ntlm-domain-config.d.ts.map +1 -0
  40. package/dist/core/auth/token-generator/ntlm-domain-config.js.map +1 -0
  41. package/dist/core/auth/token-generator/ntlm-integration.d.ts.map +1 -0
  42. package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-integration.js +4 -4
  43. package/dist/core/auth/token-generator/ntlm-integration.js.map +1 -0
  44. package/dist/core/auth/token-generator/ntlm-session-storage.d.ts.map +1 -0
  45. package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-session-storage.js +1 -1
  46. package/dist/core/auth/token-generator/ntlm-session-storage.js.map +1 -0
  47. package/dist/core/auth/token-generator/ntlm-templates.d.ts.map +1 -0
  48. package/dist/core/auth/token-generator/ntlm-templates.js.map +1 -0
  49. package/dist/core/{token/gen-token-app/gen-token-server.d.ts → auth/token-generator/server.d.ts} +1 -1
  50. package/dist/core/auth/token-generator/server.d.ts.map +1 -0
  51. package/dist/core/{token/gen-token-app/gen-token-server.js → auth/token-generator/server.js} +3 -3
  52. package/dist/core/auth/token-generator/server.js.map +1 -0
  53. package/dist/core/auth/types.d.ts +35 -0
  54. package/dist/core/auth/types.d.ts.map +1 -0
  55. package/dist/core/auth/types.js +14 -0
  56. package/dist/core/auth/types.js.map +1 -0
  57. package/dist/core/cache/cache.d.ts.map +1 -1
  58. package/dist/core/cache/cache.js +3 -2
  59. package/dist/core/cache/cache.js.map +1 -1
  60. package/dist/core/index.d.ts +5 -3
  61. package/dist/core/index.d.ts.map +1 -1
  62. package/dist/core/index.js +4 -2
  63. package/dist/core/index.js.map +1 -1
  64. package/dist/core/web/server-http.js +1 -1
  65. package/dist/core/web/server-http.js.map +1 -1
  66. package/package.json +4 -2
  67. package/dist/core/token/gen-token-app/gen-token-server.d.ts.map +0 -1
  68. package/dist/core/token/gen-token-app/gen-token-server.js.map +0 -1
  69. package/dist/core/token/gen-token-app/html.d.ts.map +0 -1
  70. package/dist/core/token/gen-token-app/html.js.map +0 -1
  71. package/dist/core/token/gen-token-app/ntlm-auth-options.d.ts.map +0 -1
  72. package/dist/core/token/gen-token-app/ntlm-auth-options.js.map +0 -1
  73. package/dist/core/token/gen-token-app/ntlm-domain-config.d.ts.map +0 -1
  74. package/dist/core/token/gen-token-app/ntlm-domain-config.js.map +0 -1
  75. package/dist/core/token/gen-token-app/ntlm-integration.d.ts.map +0 -1
  76. package/dist/core/token/gen-token-app/ntlm-integration.js.map +0 -1
  77. package/dist/core/token/gen-token-app/ntlm-session-storage.d.ts.map +0 -1
  78. package/dist/core/token/gen-token-app/ntlm-session-storage.js.map +0 -1
  79. package/dist/core/token/gen-token-app/ntlm-templates.d.ts.map +0 -1
  80. package/dist/core/token/gen-token-app/ntlm-templates.js.map +0 -1
  81. package/dist/core/token/i-token.d.ts +0 -13
  82. package/dist/core/token/i-token.d.ts.map +0 -1
  83. package/dist/core/token/i-token.js +0 -2
  84. package/dist/core/token/i-token.js.map +0 -1
  85. package/dist/core/token/token-auth.d.ts +0 -17
  86. package/dist/core/token/token-auth.d.ts.map +0 -1
  87. package/dist/core/token/token-auth.js.map +0 -1
  88. package/dist/core/token/token-core.d.ts.map +0 -1
  89. package/dist/core/token/token-core.js.map +0 -1
  90. /package/dist/core/{token/gen-token-app → auth/token-generator}/html.d.ts +0 -0
  91. /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-auth-options.d.ts +0 -0
  92. /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-domain-config.d.ts +0 -0
  93. /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-domain-config.js +0 -0
  94. /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-integration.d.ts +0 -0
  95. /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-session-storage.d.ts +0 -0
  96. /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-templates.d.ts +0 -0
  97. /package/dist/core/{token/gen-token-app → auth/token-generator}/ntlm-templates.js +0 -0
package/bin/fa-mcp.js CHANGED
@@ -6,6 +6,7 @@ import { fileURLToPath } from 'url';
6
6
  import readline from 'readline';
7
7
  import { v4 as uuidv4 } from 'uuid';
8
8
  import chalk from 'chalk';
9
+ import yaml from 'js-yaml';
9
10
 
10
11
  const __filename = fileURLToPath(import.meta.url);
11
12
  const __dirname = path.dirname(__filename);
@@ -71,6 +72,34 @@ const getAsk = () => {
71
72
  };
72
73
  };
73
74
 
75
+ /**
76
+ * Parse configuration file (JSON or YAML)
77
+ * @param {string} filePath - Path to the configuration file
78
+ * @param {string} content - Content of the file
79
+ * @returns {object} Parsed configuration object
80
+ */
81
+ const parseConfigFile = (filePath, content) => {
82
+ const ext = path.extname(filePath).toLowerCase();
83
+
84
+ try {
85
+ if (ext === '.json') {
86
+ return JSON.parse(content);
87
+ } else if (ext === '.yaml' || ext === '.yml') {
88
+ return yaml.load(content, { schema: yaml.DEFAULT_SCHEMA });
89
+ } else {
90
+ // Try to detect format by content
91
+ const trimmed = content.trim();
92
+ if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
93
+ return JSON.parse(content);
94
+ } else {
95
+ return yaml.load(content, { schema: yaml.DEFAULT_SCHEMA });
96
+ }
97
+ }
98
+ } catch (error) {
99
+ throw new Error(`Failed to parse configuration file ${filePath}: ${error.message}`);
100
+ }
101
+ };
102
+
74
103
  class MCPGenerator {
75
104
  constructor () {
76
105
  this.templateDir = path.join(__dirname, '..', 'cli-template');
@@ -166,6 +195,11 @@ class MCPGenerator {
166
195
  defaultValue: '<envCode.prod>',
167
196
  title: 'Production environment code for Consul service ID generation',
168
197
  },
198
+ {
199
+ name: 'NODE_CONSUL_ENV',
200
+ defaultValue: '',
201
+ title: 'Affects how the Consul service ID is formed - as a product or development ID. Valid values: "" | "development" | "production"',
202
+ },
169
203
 
170
204
  {
171
205
  name: 'mcp.domain',
@@ -487,6 +521,18 @@ certificate's public and private keys`,
487
521
  config[name] = String(enabled);
488
522
  continue;
489
523
  }
524
+ case 'NODE_CONSUL_ENV': {
525
+ if (currentValue === '') {
526
+ continue;
527
+ }
528
+ value = await ask.optional(title, name, defaultValue);
529
+ if (value === '' || value === 'development' || value === 'production') {
530
+ config[name] = value;
531
+ } else {
532
+ config[name] = '';
533
+ }
534
+ continue;
535
+ }
490
536
 
491
537
  default:
492
538
  value = await ask.optional(title, name, defaultValue);
@@ -534,17 +580,17 @@ certificate's public and private keys`,
534
580
 
535
581
  async collectConfiguration () {
536
582
  const config = {};
537
- const configFile = process.argv.find((arg) => arg.endsWith('.json')) ||
583
+ const configFile = process.argv.find((arg) => arg.endsWith('.json') || arg.endsWith('.yaml') || arg.endsWith('.yml')) ||
538
584
  process.argv.find((arg) => arg.startsWith('--config='))?.split('=')[1];
539
585
 
540
586
  if (configFile) {
541
587
  try {
542
588
  const configData = await fs.readFile(configFile, 'utf8');
543
- const parsedConfig = JSON.parse(configData);
589
+ const parsedConfig = parseConfigFile(configFile, configData);
544
590
  Object.assign(config, parsedConfig);
545
591
  console.log(`📋 Loaded configuration from: ${hly(configFile)}`);
546
592
  } catch (error) {
547
- console.warn(`⚠️ Warning: Could not load config file ${configFile}`);
593
+ console.warn(`⚠️ Warning: Could not load config file ${configFile}: ${error.message}`);
548
594
  }
549
595
  }
550
596
 
@@ -565,7 +611,9 @@ certificate's public and private keys`,
565
611
  } else if (configProxy.NODE_ENV === 'production') {
566
612
  configProxy.isProduction = 'true';
567
613
  }
568
-
614
+ if (config['logger.useFileLogger'] !== 'true') {
615
+ config['logger.dir'] = '';
616
+ }
569
617
  let confirmed = false;
570
618
  let isRetry = false;
571
619
 
@@ -592,34 +640,34 @@ certificate's public and private keys`,
592
640
  async getTargetPath (config = {}) {
593
641
  const ask = getAsk();
594
642
 
595
- let targetPath = process.cwd();
643
+ let tp = process.cwd();
596
644
  let createInCurrent;
597
645
  let pPath = trim(config.projectAbsPath);
598
646
  if (pPath) {
599
- targetPath = path.resolve(pPath);
600
- console.log(`Create project in: ${hl(targetPath)}${FROM_CONFIG}`);
647
+ tp = path.resolve(pPath);
648
+ console.log(`Create project in: ${hl(tp)}${FROM_CONFIG}`);
601
649
  } else {
602
- createInCurrent = await ask.yn(`Create project in current directory? (${hl(targetPath)})`, '', 'n');
650
+ createInCurrent = await ask.yn(`Create project in current directory? (${hl(tp)})`, '', 'n');
603
651
  if (!createInCurrent) {
604
- targetPath = await ask.question('Enter absolute path for project: ');
605
- targetPath = path.resolve(targetPath);
652
+ tp = await ask.question('Enter absolute path for project: ');
653
+ tp = path.resolve(tp);
606
654
  }
607
655
  }
608
656
 
609
- config.projectAbsPath = targetPath;
657
+ config.projectAbsPath = tp;
610
658
  // Create directory if it doesn't exist
611
659
  try {
612
- await fs.access(targetPath);
660
+ await fs.access(tp);
613
661
  } catch {
614
662
  console.log('Creating directory recursively...');
615
- await fs.mkdir(targetPath, { recursive: true });
663
+ await fs.mkdir(tp, { recursive: true });
616
664
  }
617
665
 
618
- const errMsg = `❌ Directory ${hl(targetPath)} not empty - cannot create project here. Use an empty directory or specify a different path.`;
666
+ const errMsg = `❌ Directory ${hl(tp)} not empty - cannot create project here. Use an empty directory or specify a different path.`;
619
667
 
620
668
  // Check if directory is empty
621
669
  try {
622
- const files = await fs.readdir(targetPath);
670
+ const files = await fs.readdir(tp);
623
671
  const allowedFiles = [
624
672
  '.git',
625
673
  '.idea',
@@ -650,7 +698,7 @@ certificate's public and private keys`,
650
698
  }
651
699
 
652
700
  ask.close();
653
- return targetPath;
701
+ return tp;
654
702
  }
655
703
 
656
704
  async copyDirectory (source, target) {
@@ -675,6 +723,7 @@ certificate's public and private keys`,
675
723
 
676
724
  async handlePackageJson (content, config) {
677
725
  try {
726
+ content = content.replace('"project.name"', '"{{project.name}}"');
678
727
  // First replace all template parameters in the content string
679
728
  let updatedContent = content;
680
729
  for (const [param, value] of Object.entries(config)) {
@@ -728,7 +777,16 @@ certificate's public and private keys`,
728
777
  return files;
729
778
  }
730
779
 
731
- async replaceTemplateParameters (targetPath, config) {
780
+ async transformTargetFile (config, targetRelPath, transformFn) {
781
+ const targetPath = config.projectAbsPath;
782
+ const targetFullPath = path.join(targetPath, targetRelPath);
783
+ const content = await fs.readFile(targetFullPath, 'utf8');
784
+ const transformedContent = transformFn(content, config);
785
+ await fs.writeFile(targetFullPath, transformedContent, 'utf8');
786
+ }
787
+
788
+ async replaceTemplateParameters (config) {
789
+ const targetPath = config.projectAbsPath;
732
790
  const files = await this.getAllFiles(targetPath);
733
791
 
734
792
  for (const filePath of files) {
@@ -754,10 +812,11 @@ certificate's public and private keys`,
754
812
  await fs.writeFile(filePath, content, 'utf8');
755
813
  }
756
814
  }
815
+ if (config['NODE_CONSUL_ENV'] === '') {
816
+ await this.transformTargetFile(config, '.env', (c) => c.replace(/^(NODE_CONSUL_ENV)=([^\r\n]*)/m, '#$1=$2'));
817
+ }
757
818
  if (config['claude.isBypassPermissions'] === 'true') {
758
- const settingsPath = path.join(targetPath, '.claude', 'settings.json');
759
- const content = await fs.readFile(settingsPath, 'utf8')
760
- .replace('"acceptEdits"', '"bypassPermissions"')
819
+ const transformFn = (c) => c.replace('"acceptEdits"', '"bypassPermissions"')
761
820
  .replace(/"allow": \[\s+"Edit",/, `"allow": [
762
821
  "Bash(sudo cp:*)",
763
822
  "Bash(sudo:*)",
@@ -791,11 +850,12 @@ certificate's public and private keys`,
791
850
  "Bash(unset http_proxy)",
792
851
  "Bash(wc:*)",
793
852
  "Edit",`);
794
- await fs.writeFile(settingsPath, content, 'utf8');
853
+ await this.transformTargetFile(config, '.claude/settings.json', transformFn);
795
854
  }
796
855
  }
797
856
 
798
- async createProject (targetPath, config) {
857
+ async createProject (config) {
858
+ const targetPath = config.projectAbsPath;
799
859
  // Copy template files
800
860
  await this.copyDirectory(this.templateDir, targetPath);
801
861
  await fs.copyFile(path.join(targetPath, '.env.example'), path.join(targetPath, '.env')); // VVT
@@ -829,7 +889,7 @@ certificate's public and private keys`,
829
889
  }
830
890
 
831
891
  // Replace template parameters
832
- await this.replaceTemplateParameters(targetPath, config);
892
+ await this.replaceTemplateParameters(config);
833
893
 
834
894
  // Replace template placeholders with defaultValue from optionalParams and save as _local.yaml
835
895
  if (localYamlContent) {
@@ -878,7 +938,7 @@ certificate's public and private keys`,
878
938
  const targetPath = await this.getTargetPath(config);
879
939
 
880
940
  console.log(`\n📁 Creating project in: ${targetPath}`);
881
- await this.createProject(targetPath, config);
941
+ await this.createProject(config);
882
942
 
883
943
  console.log('\n✅ MCP Server template created successfully!');
884
944
  console.log('\n📋 Next steps:');
@@ -1,6 +1,16 @@
1
1
  # Copy this file to local.yaml and update with your database credentials
2
2
  # local.yaml is gitignored and won't be committed
3
3
  ---
4
+ #ad:
5
+ # domains:
6
+ # MYDOMAIN:
7
+ # default: true
8
+ # controllers:
9
+ # - 'ldap://c1.corp.com'
10
+ # - 'ldap://c2.corp.com'
11
+ # username: '***'
12
+ # password: '***'
13
+
4
14
  # --------------------------------------------------
5
15
  # CACHING Reduces API calls by caching responses
6
16
  # --------------------------------------------------
@@ -69,8 +79,18 @@ webServer:
69
79
  enabled: {{webServer.auth.enabled}} # Enables/disables token authorization
70
80
  # An array of fixed tokens that pass to the MCP (use only for MCPs with green data or for development)
71
81
  permanentServerTokens: []
72
- token:
82
+ jwtToken:
73
83
  # Symmetric encryption key to generate a token for this MCP
74
84
  encryptKey: '{{webServer.auth.token.encryptKey}}'
75
85
  # If webServer.auth.enabled and the parameter true, the service name and the service specified in the token will be checked
76
86
  checkMCPName: {{webServer.auth.token.checkMCPName}}
87
+ #basic:
88
+ # username: '***'
89
+ # password: '***'
90
+ #oauth2:
91
+ # type: 'oauth2';
92
+ # clientId: '***'
93
+ # clientSecret: '***'
94
+ # redirectUri?: 'string'
95
+ # tokenEndpoint?: string # For custom OAuth providers // VVR
96
+ #pat: string;
@@ -1,6 +1,7 @@
1
1
  cache:
2
2
  ttlSeconds: CACHE_TTL_SECONDS
3
3
  maxItems: CACHE_MAX_ITEMS
4
+ checkPeriod: CACHE_CHECK_PERIOD
4
5
 
5
6
  db:
6
7
  postgres:
@@ -33,6 +34,15 @@ webServer:
33
34
  auth:
34
35
  enabled: WS_AUTH_ENABLED
35
36
  permanentServerTokens: WS_SERVER_TOKENS # comma separated list
36
- token:
37
+ jwtToken:
37
38
  encryptKey: WS_TOKEN_ENCRYPT_KEY
38
39
  checkMCPName: WS_CHECK_MC_NAME
40
+ basic:
41
+ username: WS_AUTH_BASIC_USERNAME
42
+ password: WS_AUTH_BASIC_PASSWORD
43
+ oauth2:
44
+ clientId: WS_AUTH_OAUTH2_CLIENT_ID
45
+ clientSecret: WS_AUTH_OAUTH2_CLIENT_SECRET
46
+ redirectUri: WS_AUTH_OAUTH2_REDIRECT_URI
47
+ tokenEndpoint: WS_AUTH_OAUTH2_TOKEN_ENDPOINT # For custom OAuth providers // VVR
48
+ pat: WS_AUTH_PAT
@@ -114,8 +114,18 @@ webServer:
114
114
  enabled: false # Enables/disables token authorization
115
115
  # An array of fixed tokens that pass to the MCP (use only for MCPs with green data or for development)
116
116
  permanentServerTokens: []
117
- token:
117
+ jwtToken:
118
118
  # Symmetric encryption key to generate a token for this MCP
119
119
  encryptKey: '***'
120
120
  # If webServer.auth.enabled and the parameter true, the service name and the service specified in the token will be checked
121
121
  checkMCPName: true
122
+ #basic:
123
+ # username: '***'
124
+ # password: '***'
125
+ #oauth2:
126
+ # type: 'oauth2';
127
+ # clientId: '***'
128
+ # clientSecret: '***'
129
+ # redirectUri?: 'string'
130
+ # tokenEndpoint?: string # For custom OAuth providers // VVR
131
+ #pat: string;