cast-code 1.0.0 → 1.0.2

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.
@@ -75,9 +75,6 @@ let ConfigService = class ConfigService {
75
75
  ollamaBaseUrl: frontmatter.ollamaBaseUrl || process.env.OLLAMA_BASE_URL || this.config.ollamaBaseUrl
76
76
  };
77
77
  }
78
- if (this.config.provider === 'openai' && !this.config.apiKey) {
79
- throw new Error('OPENAI_API_KEY not configured. Set it in environment or ~/.cast/config.md');
80
- }
81
78
  }
82
79
  getConfig() {
83
80
  return this.config;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/common/services/config.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport * as path from 'path';\nimport { MarkdownParserService } from './markdown-parser.service';\nimport { GLOBAL_CONFIG_DIR, DEFAULT_MODEL, DEFAULT_TEMPERATURE } from '../constants';\n\ninterface GlobalConfigFrontmatter {\n model?: string;\n temperature?: number;\n apiKey?: string;\n provider?: string;\n ollamaBaseUrl?: string;\n}\n\nexport interface GlobalConfig {\n model: string;\n temperature: number;\n apiKey: string;\n provider: string;\n ollamaBaseUrl: string;\n}\n\n@Injectable()\nexport class ConfigService {\n private config: GlobalConfig = {\n model: process.env.OLLAMA_MODEL || DEFAULT_MODEL,\n temperature: DEFAULT_TEMPERATURE,\n apiKey: process.env.OPENAI_API_KEY || '',\n provider: process.env.LLM_PROVIDER || 'openai',\n ollamaBaseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',\n };\n\n constructor(private readonly markdownParser: MarkdownParserService) {}\n\n async loadGlobalConfig() {\n const configPath = path.join(GLOBAL_CONFIG_DIR, 'config.md');\n\n if (await this.markdownParser.exists(configPath)) {\n const { frontmatter } =\n await this.markdownParser.parse<GlobalConfigFrontmatter>(configPath);\n\n this.config = {\n model: frontmatter.model || process.env.OLLAMA_MODEL || this.config.model,\n temperature: frontmatter.temperature ?? this.config.temperature,\n apiKey: frontmatter.apiKey || process.env.OPENAI_API_KEY || '',\n provider: frontmatter.provider || process.env.LLM_PROVIDER || this.config.provider,\n ollamaBaseUrl: frontmatter.ollamaBaseUrl || process.env.OLLAMA_BASE_URL || this.config.ollamaBaseUrl,\n };\n }\n\n if (this.config.provider === 'openai' && !this.config.apiKey) {\n throw new Error(\n 'OPENAI_API_KEY not configured. Set it in environment or ~/.cast/config.md',\n );\n }\n }\n\n getConfig(): GlobalConfig {\n return this.config;\n }\n\n getModel(): string {\n return this.config.model;\n }\n\n getTemperature(): number {\n return this.config.temperature;\n }\n\n getApiKey(): string {\n return this.config.apiKey;\n }\n\n getProvider(): string {\n return this.config.provider;\n }\n\n getOllamaBaseUrl(): string {\n return this.config.ollamaBaseUrl;\n }\n}\n"],"names":["ConfigService","loadGlobalConfig","configPath","path","join","GLOBAL_CONFIG_DIR","markdownParser","exists","frontmatter","parse","config","model","process","env","OLLAMA_MODEL","temperature","apiKey","OPENAI_API_KEY","provider","LLM_PROVIDER","ollamaBaseUrl","OLLAMA_BASE_URL","Error","getConfig","getModel","getTemperature","getApiKey","getProvider","getOllamaBaseUrl","DEFAULT_MODEL","DEFAULT_TEMPERATURE"],"mappings":";;;;+BAsBaA;;;eAAAA;;;wBAtBc;8DACL;uCACgB;2BACgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmB/D,IAAA,AAAMA,gBAAN,MAAMA;IAWX,MAAMC,mBAAmB;QACvB,MAAMC,aAAaC,MAAKC,IAAI,CAACC,4BAAiB,EAAE;QAEhD,IAAI,MAAM,IAAI,CAACC,cAAc,CAACC,MAAM,CAACL,aAAa;YAChD,MAAM,EAAEM,WAAW,EAAE,GACnB,MAAM,IAAI,CAACF,cAAc,CAACG,KAAK,CAA0BP;YAE3D,IAAI,CAACQ,MAAM,GAAG;gBACZC,OAAOH,YAAYG,KAAK,IAAIC,QAAQC,GAAG,CAACC,YAAY,IAAI,IAAI,CAACJ,MAAM,CAACC,KAAK;gBACzEI,aAAaP,YAAYO,WAAW,IAAI,IAAI,CAACL,MAAM,CAACK,WAAW;gBAC/DC,QAAQR,YAAYQ,MAAM,IAAIJ,QAAQC,GAAG,CAACI,cAAc,IAAI;gBAC5DC,UAAUV,YAAYU,QAAQ,IAAIN,QAAQC,GAAG,CAACM,YAAY,IAAI,IAAI,CAACT,MAAM,CAACQ,QAAQ;gBAClFE,eAAeZ,YAAYY,aAAa,IAAIR,QAAQC,GAAG,CAACQ,eAAe,IAAI,IAAI,CAACX,MAAM,CAACU,aAAa;YACtG;QACF;QAEA,IAAI,IAAI,CAACV,MAAM,CAACQ,QAAQ,KAAK,YAAY,CAAC,IAAI,CAACR,MAAM,CAACM,MAAM,EAAE;YAC5D,MAAM,IAAIM,MACR;QAEJ;IACF;IAEAC,YAA0B;QACxB,OAAO,IAAI,CAACb,MAAM;IACpB;IAEAc,WAAmB;QACjB,OAAO,IAAI,CAACd,MAAM,CAACC,KAAK;IAC1B;IAEAc,iBAAyB;QACvB,OAAO,IAAI,CAACf,MAAM,CAACK,WAAW;IAChC;IAEAW,YAAoB;QAClB,OAAO,IAAI,CAAChB,MAAM,CAACM,MAAM;IAC3B;IAEAW,cAAsB;QACpB,OAAO,IAAI,CAACjB,MAAM,CAACQ,QAAQ;IAC7B;IAEAU,mBAA2B;QACzB,OAAO,IAAI,CAAClB,MAAM,CAACU,aAAa;IAClC;IA/CA,YAAY,AAAiBd,cAAqC,CAAE;aAAvCA,iBAAAA;aARrBI,SAAuB;YAC7BC,OAAOC,QAAQC,GAAG,CAACC,YAAY,IAAIe,wBAAa;YAChDd,aAAae,8BAAmB;YAChCd,QAAQJ,QAAQC,GAAG,CAACI,cAAc,IAAI;YACtCC,UAAUN,QAAQC,GAAG,CAACM,YAAY,IAAI;YACtCC,eAAeR,QAAQC,GAAG,CAACQ,eAAe,IAAI;QAChD;IAEqE;AAgDvE"}
1
+ {"version":3,"sources":["../../../src/common/services/config.service.ts"],"sourcesContent":["import { Injectable } from '@nestjs/common';\nimport * as path from 'path';\nimport { MarkdownParserService } from './markdown-parser.service';\nimport { GLOBAL_CONFIG_DIR, DEFAULT_MODEL, DEFAULT_TEMPERATURE } from '../constants';\n\ninterface GlobalConfigFrontmatter {\n model?: string;\n temperature?: number;\n apiKey?: string;\n provider?: string;\n ollamaBaseUrl?: string;\n}\n\nexport interface GlobalConfig {\n model: string;\n temperature: number;\n apiKey: string;\n provider: string;\n ollamaBaseUrl: string;\n}\n\n@Injectable()\nexport class ConfigService {\n private config: GlobalConfig = {\n model: process.env.OLLAMA_MODEL || DEFAULT_MODEL,\n temperature: DEFAULT_TEMPERATURE,\n apiKey: process.env.OPENAI_API_KEY || '',\n provider: process.env.LLM_PROVIDER || 'openai',\n ollamaBaseUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',\n };\n\n constructor(private readonly markdownParser: MarkdownParserService) {}\n\n async loadGlobalConfig() {\n const configPath = path.join(GLOBAL_CONFIG_DIR, 'config.md');\n\n if (await this.markdownParser.exists(configPath)) {\n const { frontmatter } =\n await this.markdownParser.parse<GlobalConfigFrontmatter>(configPath);\n\n this.config = {\n model: frontmatter.model || process.env.OLLAMA_MODEL || this.config.model,\n temperature: frontmatter.temperature ?? this.config.temperature,\n apiKey: frontmatter.apiKey || process.env.OPENAI_API_KEY || '',\n provider: frontmatter.provider || process.env.LLM_PROVIDER || this.config.provider,\n ollamaBaseUrl: frontmatter.ollamaBaseUrl || process.env.OLLAMA_BASE_URL || this.config.ollamaBaseUrl,\n };\n }\n\n }\n\n getConfig(): GlobalConfig {\n return this.config;\n }\n\n getModel(): string {\n return this.config.model;\n }\n\n getTemperature(): number {\n return this.config.temperature;\n }\n\n getApiKey(): string {\n return this.config.apiKey;\n }\n\n getProvider(): string {\n return this.config.provider;\n }\n\n getOllamaBaseUrl(): string {\n return this.config.ollamaBaseUrl;\n }\n}\n"],"names":["ConfigService","loadGlobalConfig","configPath","path","join","GLOBAL_CONFIG_DIR","markdownParser","exists","frontmatter","parse","config","model","process","env","OLLAMA_MODEL","temperature","apiKey","OPENAI_API_KEY","provider","LLM_PROVIDER","ollamaBaseUrl","OLLAMA_BASE_URL","getConfig","getModel","getTemperature","getApiKey","getProvider","getOllamaBaseUrl","DEFAULT_MODEL","DEFAULT_TEMPERATURE"],"mappings":";;;;+BAsBaA;;;eAAAA;;;wBAtBc;8DACL;uCACgB;2BACgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmB/D,IAAA,AAAMA,gBAAN,MAAMA;IAWX,MAAMC,mBAAmB;QACvB,MAAMC,aAAaC,MAAKC,IAAI,CAACC,4BAAiB,EAAE;QAEhD,IAAI,MAAM,IAAI,CAACC,cAAc,CAACC,MAAM,CAACL,aAAa;YAChD,MAAM,EAAEM,WAAW,EAAE,GACnB,MAAM,IAAI,CAACF,cAAc,CAACG,KAAK,CAA0BP;YAE3D,IAAI,CAACQ,MAAM,GAAG;gBACZC,OAAOH,YAAYG,KAAK,IAAIC,QAAQC,GAAG,CAACC,YAAY,IAAI,IAAI,CAACJ,MAAM,CAACC,KAAK;gBACzEI,aAAaP,YAAYO,WAAW,IAAI,IAAI,CAACL,MAAM,CAACK,WAAW;gBAC/DC,QAAQR,YAAYQ,MAAM,IAAIJ,QAAQC,GAAG,CAACI,cAAc,IAAI;gBAC5DC,UAAUV,YAAYU,QAAQ,IAAIN,QAAQC,GAAG,CAACM,YAAY,IAAI,IAAI,CAACT,MAAM,CAACQ,QAAQ;gBAClFE,eAAeZ,YAAYY,aAAa,IAAIR,QAAQC,GAAG,CAACQ,eAAe,IAAI,IAAI,CAACX,MAAM,CAACU,aAAa;YACtG;QACF;IAEF;IAEAE,YAA0B;QACxB,OAAO,IAAI,CAACZ,MAAM;IACpB;IAEAa,WAAmB;QACjB,OAAO,IAAI,CAACb,MAAM,CAACC,KAAK;IAC1B;IAEAa,iBAAyB;QACvB,OAAO,IAAI,CAACd,MAAM,CAACK,WAAW;IAChC;IAEAU,YAAoB;QAClB,OAAO,IAAI,CAACf,MAAM,CAACM,MAAM;IAC3B;IAEAU,cAAsB;QACpB,OAAO,IAAI,CAAChB,MAAM,CAACQ,QAAQ;IAC7B;IAEAS,mBAA2B;QACzB,OAAO,IAAI,CAACjB,MAAM,CAACU,aAAa;IAClC;IA1CA,YAAY,AAAiBd,cAAqC,CAAE;aAAvCA,iBAAAA;aARrBI,SAAuB;YAC7BC,OAAOC,QAAQC,GAAG,CAACC,YAAY,IAAIc,wBAAa;YAChDb,aAAac,8BAAmB;YAChCb,QAAQJ,QAAQC,GAAG,CAACI,cAAc,IAAI;YACtCC,UAAUN,QAAQC,GAAG,CAACM,YAAY,IAAI;YACtCC,eAAeR,QAAQC,GAAG,CAACQ,eAAe,IAAI;QAChD;IAEqE;AA2CvE"}
package/dist/main.js CHANGED
@@ -10,7 +10,9 @@ const _appmodule = require("./app.module");
10
10
  const _replservice = require("./modules/repl/services/repl.service");
11
11
  const _configmanagerservice = require("./modules/config/services/config-manager.service");
12
12
  const _initconfigservice = require("./modules/config/services/init-config.service");
13
- (0, _dotenv.config)();
13
+ (0, _dotenv.config)({
14
+ quiet: true
15
+ });
14
16
  async function checkAndRunSetup(configManager, initService) {
15
17
  const hasConfig = await configManager.configExists();
16
18
  if (!hasConfig) {
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\nimport 'reflect-metadata';\nimport { config } from 'dotenv';\nimport { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\nimport { ReplService } from './modules/repl/services/repl.service';\nimport { ConfigManagerService } from './modules/config/services/config-manager.service';\nimport { InitConfigService } from './modules/config/services/init-config.service';\n\nconfig();\n\nasync function checkAndRunSetup(configManager: ConfigManagerService, initService: InitConfigService): Promise<boolean> {\n const hasConfig = await configManager.configExists();\n \n if (!hasConfig) {\n console.log('\\n👋 Bem-vindo ao Cast Code!\\n');\n console.log('Parece que esta é a primeira vez que você executa o Cast.');\n console.log('Vamos fazer a configuração inicial agora.\\n');\n\n try {\n await initService.runInitialSetup();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`\\n❌ Falha na configuração inicial: ${message}\\n`);\n return false;\n }\n\n const created = await configManager.configExists();\n if (!created) {\n console.log('\\n⚠️ Configuração não concluída. Rode: cast config init\\n');\n return false;\n }\n\n return true;\n }\n \n return true;\n}\n\nasync function bootstrap() {\n const args = process.argv.slice(2);\n const command = args[0];\n \n if (command === 'config' || command === 'init') {\n const app = await NestFactory.createApplicationContext(AppModule, {\n logger: false,\n });\n \n const configCommands = app.get(InitConfigService);\n try {\n await configCommands.runInitialSetup();\n } catch (error) {\n const message = error instanceof Error ? error.stack || error.message : String(error);\n console.error('\\nFailed to run initial setup:\\n', message);\n process.exitCode = 1;\n }\n await app.close();\n return;\n }\n\n const app = await NestFactory.createApplicationContext(AppModule, {\n logger: false,\n });\n\n const configManager = app.get(ConfigManagerService);\n const initService = app.get(InitConfigService);\n \n const ready = await checkAndRunSetup(configManager, initService);\n \n if (!ready) {\n await app.close();\n process.exit(1);\n }\n\n await configManager.loadConfig();\n\n const repl = app.get(ReplService);\n\n process.on('SIGINT', () => {\n repl.stop();\n app.close();\n process.exit(0);\n });\n\n try {\n await repl.start();\n } catch (error) {\n console.error('Failed to start:', (error as Error).message);\n process.exit(1);\n }\n}\n\nbootstrap().catch((error) => {\n const message = error instanceof Error ? error.stack || error.message : String(error);\n console.error('\\nFatal bootstrap error:\\n', message);\n process.exit(1);\n});\n"],"names":["config","checkAndRunSetup","configManager","initService","hasConfig","configExists","console","log","runInitialSetup","error","message","Error","String","created","bootstrap","args","process","argv","slice","command","app","NestFactory","createApplicationContext","AppModule","logger","configCommands","get","InitConfigService","stack","exitCode","close","ConfigManagerService","ready","exit","loadConfig","repl","ReplService","on","stop","start","catch"],"mappings":";;;;;QACO;wBACgB;sBACK;2BACF;6BACE;sCACS;mCACH;AAElCA,IAAAA,cAAM;AAEN,eAAeC,iBAAiBC,aAAmC,EAAEC,WAA8B;IACjG,MAAMC,YAAY,MAAMF,cAAcG,YAAY;IAElD,IAAI,CAACD,WAAW;QACdE,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QAEZ,IAAI;YACF,MAAMJ,YAAYK,eAAe;QACnC,EAAE,OAAOC,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChEH,QAAQG,KAAK,CAAC,CAAC,mCAAmC,EAAEC,QAAQ,EAAE,CAAC;YAC/D,OAAO;QACT;QAEA,MAAMG,UAAU,MAAMX,cAAcG,YAAY;QAChD,IAAI,CAACQ,SAAS;YACZP,QAAQC,GAAG,CAAC;YACZ,OAAO;QACT;QAEA,OAAO;IACT;IAEA,OAAO;AACT;AAEA,eAAeO;IACb,MAAMC,OAAOC,QAAQC,IAAI,CAACC,KAAK,CAAC;IAChC,MAAMC,UAAUJ,IAAI,CAAC,EAAE;IAEvB,IAAII,YAAY,YAAYA,YAAY,QAAQ;QAC9C,MAAMC,MAAM,MAAMC,iBAAW,CAACC,wBAAwB,CAACC,oBAAS,EAAE;YAChEC,QAAQ;QACV;QAEA,MAAMC,iBAAiBL,IAAIM,GAAG,CAACC,oCAAiB;QAChD,IAAI;YACF,MAAMF,eAAejB,eAAe;QACtC,EAAE,OAAOC,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMmB,KAAK,IAAInB,MAAMC,OAAO,GAAGE,OAAOH;YAC/EH,QAAQG,KAAK,CAAC,oCAAoCC;YAClDM,QAAQa,QAAQ,GAAG;QACrB;QACA,MAAMT,IAAIU,KAAK;QACf;IACF;IAEA,MAAMV,MAAM,MAAMC,iBAAW,CAACC,wBAAwB,CAACC,oBAAS,EAAE;QAChEC,QAAQ;IACV;IAEA,MAAMtB,gBAAgBkB,IAAIM,GAAG,CAACK,0CAAoB;IAClD,MAAM5B,cAAciB,IAAIM,GAAG,CAACC,oCAAiB;IAE7C,MAAMK,QAAQ,MAAM/B,iBAAiBC,eAAeC;IAEpD,IAAI,CAAC6B,OAAO;QACV,MAAMZ,IAAIU,KAAK;QACfd,QAAQiB,IAAI,CAAC;IACf;IAEA,MAAM/B,cAAcgC,UAAU;IAE9B,MAAMC,OAAOf,IAAIM,GAAG,CAACU,wBAAW;IAEhCpB,QAAQqB,EAAE,CAAC,UAAU;QACnBF,KAAKG,IAAI;QACTlB,IAAIU,KAAK;QACTd,QAAQiB,IAAI,CAAC;IACf;IAEA,IAAI;QACF,MAAME,KAAKI,KAAK;IAClB,EAAE,OAAO9B,OAAO;QACdH,QAAQG,KAAK,CAAC,oBAAoB,AAACA,MAAgBC,OAAO;QAC1DM,QAAQiB,IAAI,CAAC;IACf;AACF;AAEAnB,YAAY0B,KAAK,CAAC,CAAC/B;IACjB,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMmB,KAAK,IAAInB,MAAMC,OAAO,GAAGE,OAAOH;IAC/EH,QAAQG,KAAK,CAAC,8BAA8BC;IAC5CM,QAAQiB,IAAI,CAAC;AACf"}
1
+ {"version":3,"sources":["../src/main.ts"],"sourcesContent":["#!/usr/bin/env node\nimport 'reflect-metadata';\nimport { config } from 'dotenv';\nimport { NestFactory } from '@nestjs/core';\nimport { AppModule } from './app.module';\nimport { ReplService } from './modules/repl/services/repl.service';\nimport { ConfigManagerService } from './modules/config/services/config-manager.service';\nimport { InitConfigService } from './modules/config/services/init-config.service';\n\nconfig({ quiet: true });\n\nasync function checkAndRunSetup(configManager: ConfigManagerService, initService: InitConfigService): Promise<boolean> {\n const hasConfig = await configManager.configExists();\n \n if (!hasConfig) {\n console.log('\\n👋 Bem-vindo ao Cast Code!\\n');\n console.log('Parece que esta é a primeira vez que você executa o Cast.');\n console.log('Vamos fazer a configuração inicial agora.\\n');\n\n try {\n await initService.runInitialSetup();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(`\\n❌ Falha na configuração inicial: ${message}\\n`);\n return false;\n }\n\n const created = await configManager.configExists();\n if (!created) {\n console.log('\\n⚠️ Configuração não concluída. Rode: cast config init\\n');\n return false;\n }\n\n return true;\n }\n \n return true;\n}\n\nasync function bootstrap() {\n const args = process.argv.slice(2);\n const command = args[0];\n \n if (command === 'config' || command === 'init') {\n const app = await NestFactory.createApplicationContext(AppModule, {\n logger: false,\n });\n \n const configCommands = app.get(InitConfigService);\n try {\n await configCommands.runInitialSetup();\n } catch (error) {\n const message = error instanceof Error ? error.stack || error.message : String(error);\n console.error('\\nFailed to run initial setup:\\n', message);\n process.exitCode = 1;\n }\n await app.close();\n return;\n }\n\n const app = await NestFactory.createApplicationContext(AppModule, {\n logger: false,\n });\n\n const configManager = app.get(ConfigManagerService);\n const initService = app.get(InitConfigService);\n \n const ready = await checkAndRunSetup(configManager, initService);\n \n if (!ready) {\n await app.close();\n process.exit(1);\n }\n\n await configManager.loadConfig();\n\n const repl = app.get(ReplService);\n\n process.on('SIGINT', () => {\n repl.stop();\n app.close();\n process.exit(0);\n });\n\n try {\n await repl.start();\n } catch (error) {\n console.error('Failed to start:', (error as Error).message);\n process.exit(1);\n }\n}\n\nbootstrap().catch((error) => {\n const message = error instanceof Error ? error.stack || error.message : String(error);\n console.error('\\nFatal bootstrap error:\\n', message);\n process.exit(1);\n});\n"],"names":["config","quiet","checkAndRunSetup","configManager","initService","hasConfig","configExists","console","log","runInitialSetup","error","message","Error","String","created","bootstrap","args","process","argv","slice","command","app","NestFactory","createApplicationContext","AppModule","logger","configCommands","get","InitConfigService","stack","exitCode","close","ConfigManagerService","ready","exit","loadConfig","repl","ReplService","on","stop","start","catch"],"mappings":";;;;;QACO;wBACgB;sBACK;2BACF;6BACE;sCACS;mCACH;AAElCA,IAAAA,cAAM,EAAC;IAAEC,OAAO;AAAK;AAErB,eAAeC,iBAAiBC,aAAmC,EAAEC,WAA8B;IACjG,MAAMC,YAAY,MAAMF,cAAcG,YAAY;IAElD,IAAI,CAACD,WAAW;QACdE,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QACZD,QAAQC,GAAG,CAAC;QAEZ,IAAI;YACF,MAAMJ,YAAYK,eAAe;QACnC,EAAE,OAAOC,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChEH,QAAQG,KAAK,CAAC,CAAC,mCAAmC,EAAEC,QAAQ,EAAE,CAAC;YAC/D,OAAO;QACT;QAEA,MAAMG,UAAU,MAAMX,cAAcG,YAAY;QAChD,IAAI,CAACQ,SAAS;YACZP,QAAQC,GAAG,CAAC;YACZ,OAAO;QACT;QAEA,OAAO;IACT;IAEA,OAAO;AACT;AAEA,eAAeO;IACb,MAAMC,OAAOC,QAAQC,IAAI,CAACC,KAAK,CAAC;IAChC,MAAMC,UAAUJ,IAAI,CAAC,EAAE;IAEvB,IAAII,YAAY,YAAYA,YAAY,QAAQ;QAC9C,MAAMC,MAAM,MAAMC,iBAAW,CAACC,wBAAwB,CAACC,oBAAS,EAAE;YAChEC,QAAQ;QACV;QAEA,MAAMC,iBAAiBL,IAAIM,GAAG,CAACC,oCAAiB;QAChD,IAAI;YACF,MAAMF,eAAejB,eAAe;QACtC,EAAE,OAAOC,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMmB,KAAK,IAAInB,MAAMC,OAAO,GAAGE,OAAOH;YAC/EH,QAAQG,KAAK,CAAC,oCAAoCC;YAClDM,QAAQa,QAAQ,GAAG;QACrB;QACA,MAAMT,IAAIU,KAAK;QACf;IACF;IAEA,MAAMV,MAAM,MAAMC,iBAAW,CAACC,wBAAwB,CAACC,oBAAS,EAAE;QAChEC,QAAQ;IACV;IAEA,MAAMtB,gBAAgBkB,IAAIM,GAAG,CAACK,0CAAoB;IAClD,MAAM5B,cAAciB,IAAIM,GAAG,CAACC,oCAAiB;IAE7C,MAAMK,QAAQ,MAAM/B,iBAAiBC,eAAeC;IAEpD,IAAI,CAAC6B,OAAO;QACV,MAAMZ,IAAIU,KAAK;QACfd,QAAQiB,IAAI,CAAC;IACf;IAEA,MAAM/B,cAAcgC,UAAU;IAE9B,MAAMC,OAAOf,IAAIM,GAAG,CAACU,wBAAW;IAEhCpB,QAAQqB,EAAE,CAAC,UAAU;QACnBF,KAAKG,IAAI;QACTlB,IAAIU,KAAK;QACTd,QAAQiB,IAAI,CAAC;IACf;IAEA,IAAI;QACF,MAAME,KAAKI,KAAK;IAClB,EAAE,OAAO9B,OAAO;QACdH,QAAQG,KAAK,CAAC,oBAAoB,AAACA,MAAgBC,OAAO;QAC1DM,QAAQiB,IAAI,CAAC;IACf;AACF;AAEAnB,YAAY0B,KAAK,CAAC,CAAC/B;IACjB,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMmB,KAAK,IAAInB,MAAMC,OAAO,GAAGE,OAAOH;IAC/EH,QAAQG,KAAK,CAAC,8BAA8BC;IAC5CM,QAAQiB,IAAI,CAAC;AACf"}
@@ -149,8 +149,19 @@ const MCP_TEMPLATES = {
149
149
  // ===== DESIGN =====
150
150
  figma: {
151
151
  id: 'figma',
152
- name: 'Figma',
153
- description: 'Acesse designs e componentes (OAuth)',
152
+ name: 'Figma Desktop',
153
+ description: 'Acesse designs via app desktop local (sem OAuth)',
154
+ category: 'design',
155
+ config: {
156
+ type: 'http',
157
+ endpoint: 'http://127.0.0.1:3845/mcp'
158
+ },
159
+ credentials: []
160
+ },
161
+ 'figma-remote': {
162
+ id: 'figma-remote',
163
+ name: 'Figma Remote (OAuth)',
164
+ description: 'Servidor remoto Figma — requer cliente pré-aprovado',
154
165
  category: 'design',
155
166
  config: {
156
167
  type: 'http',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/mcp/catalog/mcp-templates.ts"],"sourcesContent":["import { McpConfig } from '../types';\n\nexport type McpCategory = 'dev' | 'design' | 'data' | 'search' | 'cloud' | 'productivity' | 'payments' | 'browser' | 'filesystem';\n\nexport interface McpTemplate {\n id: string;\n name: string;\n description: string;\n category: McpCategory;\n config: McpConfig;\n credentials: {\n name: string;\n envVar: string;\n placeholder: string;\n required: boolean;\n isArg?: boolean;\n }[];\n}\n\nexport const MCP_TEMPLATES: Record<string, McpTemplate> = {\n // ===== DEV TOOLS =====\n github: {\n id: 'github',\n name: 'GitHub',\n description: 'Acesse repos, issues, PRs',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-github'],\n env: {},\n },\n credentials: [\n {\n name: 'GitHub Token',\n envVar: 'GITHUB_PERSONAL_ACCESS_TOKEN',\n placeholder: 'ghp_...',\n required: true,\n },\n ],\n },\n\n linear: {\n id: 'linear',\n name: 'Linear',\n description: 'Gerencie issues e projetos',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@larryhudson/linear-mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Linear API Key',\n envVar: 'LINEAR_API_KEY',\n placeholder: 'lin_api_...',\n required: true,\n },\n ],\n },\n\n jira: {\n id: 'jira',\n name: 'Jira',\n description: 'Gerencie issues e sprints',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@aashari/mcp-server-atlassian-jira'],\n env: {},\n },\n credentials: [\n {\n name: 'Jira Host',\n envVar: 'JIRA_HOST',\n placeholder: 'empresa.atlassian.net',\n required: true,\n },\n {\n name: 'Jira Email',\n envVar: 'JIRA_EMAIL',\n placeholder: 'você@empresa.com',\n required: true,\n },\n {\n name: 'Jira API Token',\n envVar: 'JIRA_API_TOKEN',\n placeholder: 'ATATT...',\n required: true,\n },\n ],\n },\n\n sentry: {\n id: 'sentry',\n name: 'Sentry',\n description: 'Monitore erros e performance',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@sentry/mcp-server'],\n env: {\n EMBEDDED_AGENT_PROVIDER: 'anthropic',\n },\n },\n credentials: [\n {\n name: 'Sentry Access Token',\n envVar: 'SENTRY_ACCESS_TOKEN',\n placeholder: 'sntrys_...',\n required: true,\n },\n ],\n },\n\n docker: {\n id: 'docker',\n name: 'Docker',\n description: 'Gerencie containers e images',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@0xshariq/docker-mcp-server'],\n env: {},\n },\n credentials: [],\n },\n\n // ===== DESIGN =====\n figma: {\n id: 'figma',\n name: 'Figma',\n description: 'Acesse designs e componentes (OAuth)',\n category: 'design',\n config: {\n type: 'http',\n endpoint: 'https://mcp.figma.com/mcp',\n },\n credentials: [],\n },\n\n // ===== DATA =====\n postgres: {\n id: 'postgres',\n name: 'PostgreSQL',\n description: 'Consulte bancos de dados',\n category: 'data',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-postgres'],\n env: {},\n },\n credentials: [\n {\n name: 'Database URL',\n envVar: '',\n placeholder: 'postgresql://user:pass@host/db',\n required: true,\n isArg: true,\n },\n ],\n },\n\n mongodb: {\n id: 'mongodb',\n name: 'MongoDB',\n description: 'Consulte coleções e documentos',\n category: 'data',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@mongodb-js/mongodb-mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Connection String',\n envVar: 'MDB_MCP_CONNECTION_STRING',\n placeholder: 'mongodb+srv://...',\n required: true,\n },\n ],\n },\n\n redis: {\n id: 'redis',\n name: 'Redis',\n description: 'Cache e key-value store',\n category: 'data',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-redis'],\n env: {},\n },\n credentials: [\n {\n name: 'Redis URL',\n envVar: 'REDIS_URL',\n placeholder: 'redis://localhost:6379',\n required: true,\n },\n ],\n },\n\n supabase: {\n id: 'supabase',\n name: 'Supabase',\n description: 'Banco de dados e backend',\n category: 'data',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@cloud9-labs/mcp-supabase'],\n env: {},\n },\n credentials: [\n {\n name: 'Supabase URL',\n envVar: 'SUPABASE_URL',\n placeholder: 'https://xyz.supabase.co',\n required: true,\n },\n {\n name: 'Service Key',\n envVar: 'SUPABASE_SERVICE_KEY',\n placeholder: 'eyJ...',\n required: true,\n },\n ],\n },\n\n // ===== SEARCH =====\n 'brave-search': {\n id: 'brave-search',\n name: 'Brave Search',\n description: 'Busca na web',\n category: 'search',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-brave-search'],\n env: {},\n },\n credentials: [\n {\n name: 'Brave API Key',\n envVar: 'BRAVE_API_KEY',\n placeholder: 'BSA...',\n required: true,\n },\n ],\n },\n\n exa: {\n id: 'exa',\n name: 'Exa Search',\n description: 'Busca semântica na web',\n category: 'search',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', 'exa-mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Exa API Key',\n envVar: 'EXA_API_KEY',\n placeholder: 'exa_...',\n required: true,\n },\n ],\n },\n\n perplexity: {\n id: 'perplexity',\n name: 'Perplexity',\n description: 'Busca com IA',\n category: 'search',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@perplexity-ai/mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Perplexity API Key',\n envVar: 'PERPLEXITY_API_KEY',\n placeholder: 'pplx-...',\n required: true,\n },\n ],\n },\n\n context7: {\n id: 'context7',\n name: 'Context7',\n description: 'Busca em documentações técnicas',\n category: 'search',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@upstash/context7-mcp'],\n env: {},\n },\n credentials: [],\n },\n\n // ===== CLOUD =====\n vercel: {\n id: 'vercel',\n name: 'Vercel',\n description: 'Deploy e gerenciamento',\n category: 'cloud',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@vercel/mcp-adapter'],\n env: {},\n },\n credentials: [],\n },\n\n cloudflare: {\n id: 'cloudflare',\n name: 'Cloudflare',\n description: 'Workers, KV, R2',\n category: 'cloud',\n config: {\n type: 'http',\n endpoint: 'https://mcp.cloudflare.com',\n },\n credentials: [],\n },\n\n 'aws-s3': {\n id: 'aws-s3',\n name: 'AWS S3',\n description: 'Armazenamento de objetos',\n category: 'cloud',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', 'aws-s3-mcp'],\n env: {},\n },\n credentials: [\n {\n name: 'Access Key ID',\n envVar: 'AWS_ACCESS_KEY_ID',\n placeholder: 'AKIA...',\n required: true,\n },\n {\n name: 'Secret Access Key',\n envVar: 'AWS_SECRET_ACCESS_KEY',\n placeholder: 'xxx',\n required: true,\n },\n {\n name: 'Region',\n envVar: 'AWS_REGION',\n placeholder: 'us-east-1',\n required: true,\n },\n ],\n },\n\n // ===== PRODUCTIVITY =====\n slack: {\n id: 'slack',\n name: 'Slack',\n description: 'Envie mensagens e gerencie canais',\n category: 'productivity',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', 'slack-mcp-server@latest', '--transport', 'stdio'],\n env: {},\n },\n credentials: [\n {\n name: 'Slack Bot Token',\n envVar: 'SLACK_BOT_TOKEN',\n placeholder: 'xoxb-...',\n required: true,\n },\n {\n name: 'Team ID',\n envVar: 'SLACK_TEAM_ID',\n placeholder: 'T...',\n required: true,\n },\n ],\n },\n\n notion: {\n id: 'notion',\n name: 'Notion',\n description: 'Gerencie páginas e databases',\n category: 'productivity',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@notionhq/notion-mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Notion Token',\n envVar: 'NOTION_TOKEN',\n placeholder: 'secret_...',\n required: true,\n },\n ],\n },\n\n 'google-drive': {\n id: 'google-drive',\n name: 'Google Drive',\n description: 'Acesse arquivos e pastas (OAuth)',\n category: 'productivity',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-gdrive'],\n env: {},\n },\n credentials: [],\n },\n\n 'google-maps': {\n id: 'google-maps',\n name: 'Google Maps',\n description: 'Geocoding e rotas',\n category: 'productivity',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@googlemaps/code-assist-mcp@latest'],\n env: {},\n },\n credentials: [],\n },\n\n // ===== PAYMENTS =====\n stripe: {\n id: 'stripe',\n name: 'Stripe',\n description: 'Pagamentos e assinaturas',\n category: 'payments',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@stripe/mcp', '--tools=all'],\n env: {},\n },\n credentials: [\n {\n name: 'Stripe Secret Key',\n envVar: 'STRIPE_SECRET_KEY',\n placeholder: 'sk_test_... ou rk_...',\n required: true,\n },\n ],\n },\n\n twilio: {\n id: 'twilio',\n name: 'Twilio',\n description: 'SMS e chamadas',\n category: 'payments',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@twilio-alpha/mcp'],\n env: {},\n },\n credentials: [\n {\n name: 'Account SID',\n envVar: '',\n placeholder: 'AC...',\n required: true,\n isArg: true,\n },\n {\n name: 'API Key:Secret',\n envVar: '',\n placeholder: 'SK...:...',\n required: true,\n isArg: true,\n },\n ],\n },\n\n // ===== BROWSER =====\n puppeteer: {\n id: 'puppeteer',\n name: 'Puppeteer',\n description: 'Automação de browser',\n category: 'browser',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-puppeteer'],\n env: {},\n },\n credentials: [],\n },\n\n // ===== FILESYSTEM =====\n filesystem: {\n id: 'filesystem',\n name: 'Filesystem',\n description: 'Acesse arquivos locais',\n category: 'filesystem',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-filesystem'],\n env: {},\n },\n credentials: [\n {\n name: 'Diretório permitido',\n envVar: '',\n placeholder: '/caminho/para/diretório',\n required: true,\n isArg: true,\n },\n ],\n },\n};\n\nexport function getTemplatesByCategory(category: McpCategory): McpTemplate[] {\n return Object.values(MCP_TEMPLATES).filter(t => t.category === category);\n}\n\nexport function getAllTemplates(): McpTemplate[] {\n return Object.values(MCP_TEMPLATES);\n}\n\nexport function getTemplate(id: string): McpTemplate | undefined {\n return MCP_TEMPLATES[id];\n}\n"],"names":["MCP_TEMPLATES","getAllTemplates","getTemplate","getTemplatesByCategory","github","id","name","description","category","config","type","command","args","env","credentials","envVar","placeholder","required","linear","jira","sentry","EMBEDDED_AGENT_PROVIDER","docker","figma","endpoint","postgres","isArg","mongodb","redis","supabase","exa","perplexity","context7","vercel","cloudflare","slack","notion","stripe","twilio","puppeteer","filesystem","Object","values","filter","t"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/modules/mcp/catalog/mcp-templates.ts"],"sourcesContent":["import { McpConfig } from '../types';\n\nexport type McpCategory = 'dev' | 'design' | 'data' | 'search' | 'cloud' | 'productivity' | 'payments' | 'browser' | 'filesystem';\n\nexport interface McpTemplate {\n id: string;\n name: string;\n description: string;\n category: McpCategory;\n config: McpConfig;\n credentials: {\n name: string;\n envVar: string;\n placeholder: string;\n required: boolean;\n isArg?: boolean;\n }[];\n}\n\nexport const MCP_TEMPLATES: Record<string, McpTemplate> = {\n // ===== DEV TOOLS =====\n github: {\n id: 'github',\n name: 'GitHub',\n description: 'Acesse repos, issues, PRs',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-github'],\n env: {},\n },\n credentials: [\n {\n name: 'GitHub Token',\n envVar: 'GITHUB_PERSONAL_ACCESS_TOKEN',\n placeholder: 'ghp_...',\n required: true,\n },\n ],\n },\n\n linear: {\n id: 'linear',\n name: 'Linear',\n description: 'Gerencie issues e projetos',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@larryhudson/linear-mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Linear API Key',\n envVar: 'LINEAR_API_KEY',\n placeholder: 'lin_api_...',\n required: true,\n },\n ],\n },\n\n jira: {\n id: 'jira',\n name: 'Jira',\n description: 'Gerencie issues e sprints',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@aashari/mcp-server-atlassian-jira'],\n env: {},\n },\n credentials: [\n {\n name: 'Jira Host',\n envVar: 'JIRA_HOST',\n placeholder: 'empresa.atlassian.net',\n required: true,\n },\n {\n name: 'Jira Email',\n envVar: 'JIRA_EMAIL',\n placeholder: 'você@empresa.com',\n required: true,\n },\n {\n name: 'Jira API Token',\n envVar: 'JIRA_API_TOKEN',\n placeholder: 'ATATT...',\n required: true,\n },\n ],\n },\n\n sentry: {\n id: 'sentry',\n name: 'Sentry',\n description: 'Monitore erros e performance',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@sentry/mcp-server'],\n env: {\n EMBEDDED_AGENT_PROVIDER: 'anthropic',\n },\n },\n credentials: [\n {\n name: 'Sentry Access Token',\n envVar: 'SENTRY_ACCESS_TOKEN',\n placeholder: 'sntrys_...',\n required: true,\n },\n ],\n },\n\n docker: {\n id: 'docker',\n name: 'Docker',\n description: 'Gerencie containers e images',\n category: 'dev',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@0xshariq/docker-mcp-server'],\n env: {},\n },\n credentials: [],\n },\n\n // ===== DESIGN =====\n figma: {\n id: 'figma',\n name: 'Figma Desktop',\n description: 'Acesse designs via app desktop local (sem OAuth)',\n category: 'design',\n config: {\n type: 'http',\n endpoint: 'http://127.0.0.1:3845/mcp',\n },\n credentials: [],\n },\n\n 'figma-remote': {\n id: 'figma-remote',\n name: 'Figma Remote (OAuth)',\n description: 'Servidor remoto Figma — requer cliente pré-aprovado',\n category: 'design',\n config: {\n type: 'http',\n endpoint: 'https://mcp.figma.com/mcp',\n },\n credentials: [],\n },\n\n // ===== DATA =====\n postgres: {\n id: 'postgres',\n name: 'PostgreSQL',\n description: 'Consulte bancos de dados',\n category: 'data',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-postgres'],\n env: {},\n },\n credentials: [\n {\n name: 'Database URL',\n envVar: '',\n placeholder: 'postgresql://user:pass@host/db',\n required: true,\n isArg: true,\n },\n ],\n },\n\n mongodb: {\n id: 'mongodb',\n name: 'MongoDB',\n description: 'Consulte coleções e documentos',\n category: 'data',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@mongodb-js/mongodb-mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Connection String',\n envVar: 'MDB_MCP_CONNECTION_STRING',\n placeholder: 'mongodb+srv://...',\n required: true,\n },\n ],\n },\n\n redis: {\n id: 'redis',\n name: 'Redis',\n description: 'Cache e key-value store',\n category: 'data',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-redis'],\n env: {},\n },\n credentials: [\n {\n name: 'Redis URL',\n envVar: 'REDIS_URL',\n placeholder: 'redis://localhost:6379',\n required: true,\n },\n ],\n },\n\n supabase: {\n id: 'supabase',\n name: 'Supabase',\n description: 'Banco de dados e backend',\n category: 'data',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@cloud9-labs/mcp-supabase'],\n env: {},\n },\n credentials: [\n {\n name: 'Supabase URL',\n envVar: 'SUPABASE_URL',\n placeholder: 'https://xyz.supabase.co',\n required: true,\n },\n {\n name: 'Service Key',\n envVar: 'SUPABASE_SERVICE_KEY',\n placeholder: 'eyJ...',\n required: true,\n },\n ],\n },\n\n // ===== SEARCH =====\n 'brave-search': {\n id: 'brave-search',\n name: 'Brave Search',\n description: 'Busca na web',\n category: 'search',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-brave-search'],\n env: {},\n },\n credentials: [\n {\n name: 'Brave API Key',\n envVar: 'BRAVE_API_KEY',\n placeholder: 'BSA...',\n required: true,\n },\n ],\n },\n\n exa: {\n id: 'exa',\n name: 'Exa Search',\n description: 'Busca semântica na web',\n category: 'search',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', 'exa-mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Exa API Key',\n envVar: 'EXA_API_KEY',\n placeholder: 'exa_...',\n required: true,\n },\n ],\n },\n\n perplexity: {\n id: 'perplexity',\n name: 'Perplexity',\n description: 'Busca com IA',\n category: 'search',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@perplexity-ai/mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Perplexity API Key',\n envVar: 'PERPLEXITY_API_KEY',\n placeholder: 'pplx-...',\n required: true,\n },\n ],\n },\n\n context7: {\n id: 'context7',\n name: 'Context7',\n description: 'Busca em documentações técnicas',\n category: 'search',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@upstash/context7-mcp'],\n env: {},\n },\n credentials: [],\n },\n\n // ===== CLOUD =====\n vercel: {\n id: 'vercel',\n name: 'Vercel',\n description: 'Deploy e gerenciamento',\n category: 'cloud',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@vercel/mcp-adapter'],\n env: {},\n },\n credentials: [],\n },\n\n cloudflare: {\n id: 'cloudflare',\n name: 'Cloudflare',\n description: 'Workers, KV, R2',\n category: 'cloud',\n config: {\n type: 'http',\n endpoint: 'https://mcp.cloudflare.com',\n },\n credentials: [],\n },\n\n 'aws-s3': {\n id: 'aws-s3',\n name: 'AWS S3',\n description: 'Armazenamento de objetos',\n category: 'cloud',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', 'aws-s3-mcp'],\n env: {},\n },\n credentials: [\n {\n name: 'Access Key ID',\n envVar: 'AWS_ACCESS_KEY_ID',\n placeholder: 'AKIA...',\n required: true,\n },\n {\n name: 'Secret Access Key',\n envVar: 'AWS_SECRET_ACCESS_KEY',\n placeholder: 'xxx',\n required: true,\n },\n {\n name: 'Region',\n envVar: 'AWS_REGION',\n placeholder: 'us-east-1',\n required: true,\n },\n ],\n },\n\n // ===== PRODUCTIVITY =====\n slack: {\n id: 'slack',\n name: 'Slack',\n description: 'Envie mensagens e gerencie canais',\n category: 'productivity',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', 'slack-mcp-server@latest', '--transport', 'stdio'],\n env: {},\n },\n credentials: [\n {\n name: 'Slack Bot Token',\n envVar: 'SLACK_BOT_TOKEN',\n placeholder: 'xoxb-...',\n required: true,\n },\n {\n name: 'Team ID',\n envVar: 'SLACK_TEAM_ID',\n placeholder: 'T...',\n required: true,\n },\n ],\n },\n\n notion: {\n id: 'notion',\n name: 'Notion',\n description: 'Gerencie páginas e databases',\n category: 'productivity',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@notionhq/notion-mcp-server'],\n env: {},\n },\n credentials: [\n {\n name: 'Notion Token',\n envVar: 'NOTION_TOKEN',\n placeholder: 'secret_...',\n required: true,\n },\n ],\n },\n\n 'google-drive': {\n id: 'google-drive',\n name: 'Google Drive',\n description: 'Acesse arquivos e pastas (OAuth)',\n category: 'productivity',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-gdrive'],\n env: {},\n },\n credentials: [],\n },\n\n 'google-maps': {\n id: 'google-maps',\n name: 'Google Maps',\n description: 'Geocoding e rotas',\n category: 'productivity',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@googlemaps/code-assist-mcp@latest'],\n env: {},\n },\n credentials: [],\n },\n\n // ===== PAYMENTS =====\n stripe: {\n id: 'stripe',\n name: 'Stripe',\n description: 'Pagamentos e assinaturas',\n category: 'payments',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@stripe/mcp', '--tools=all'],\n env: {},\n },\n credentials: [\n {\n name: 'Stripe Secret Key',\n envVar: 'STRIPE_SECRET_KEY',\n placeholder: 'sk_test_... ou rk_...',\n required: true,\n },\n ],\n },\n\n twilio: {\n id: 'twilio',\n name: 'Twilio',\n description: 'SMS e chamadas',\n category: 'payments',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@twilio-alpha/mcp'],\n env: {},\n },\n credentials: [\n {\n name: 'Account SID',\n envVar: '',\n placeholder: 'AC...',\n required: true,\n isArg: true,\n },\n {\n name: 'API Key:Secret',\n envVar: '',\n placeholder: 'SK...:...',\n required: true,\n isArg: true,\n },\n ],\n },\n\n // ===== BROWSER =====\n puppeteer: {\n id: 'puppeteer',\n name: 'Puppeteer',\n description: 'Automação de browser',\n category: 'browser',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-puppeteer'],\n env: {},\n },\n credentials: [],\n },\n\n // ===== FILESYSTEM =====\n filesystem: {\n id: 'filesystem',\n name: 'Filesystem',\n description: 'Acesse arquivos locais',\n category: 'filesystem',\n config: {\n type: 'stdio',\n command: 'npx',\n args: ['-y', '@modelcontextprotocol/server-filesystem'],\n env: {},\n },\n credentials: [\n {\n name: 'Diretório permitido',\n envVar: '',\n placeholder: '/caminho/para/diretório',\n required: true,\n isArg: true,\n },\n ],\n },\n};\n\nexport function getTemplatesByCategory(category: McpCategory): McpTemplate[] {\n return Object.values(MCP_TEMPLATES).filter(t => t.category === category);\n}\n\nexport function getAllTemplates(): McpTemplate[] {\n return Object.values(MCP_TEMPLATES);\n}\n\nexport function getTemplate(id: string): McpTemplate | undefined {\n return MCP_TEMPLATES[id];\n}\n"],"names":["MCP_TEMPLATES","getAllTemplates","getTemplate","getTemplatesByCategory","github","id","name","description","category","config","type","command","args","env","credentials","envVar","placeholder","required","linear","jira","sentry","EMBEDDED_AGENT_PROVIDER","docker","figma","endpoint","postgres","isArg","mongodb","redis","supabase","exa","perplexity","context7","vercel","cloudflare","slack","notion","stripe","twilio","puppeteer","filesystem","Object","values","filter","t"],"mappings":";;;;;;;;;;;QAmBaA;eAAAA;;QA4hBGC;eAAAA;;QAIAC;eAAAA;;QARAC;eAAAA;;;AAxhBT,MAAMH,gBAA6C;IACxD,wBAAwB;IACxBI,QAAQ;QACNC,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAsC;YACnDC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAC,QAAQ;QACNb,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAiC;YAC9CC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAE,MAAM;QACJd,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAqC;YAClDC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;YACA;gBACEX,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;YACA;gBACEX,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAG,QAAQ;QACNf,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAqB;YAClCC,KAAK;gBACHQ,yBAAyB;YAC3B;QACF;QACAP,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAK,QAAQ;QACNjB,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAA8B;YAC3CC,KAAK,CAAC;QACR;QACAC,aAAa,EAAE;IACjB;IAEA,qBAAqB;IACrBS,OAAO;QACLlB,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNc,UAAU;QACZ;QACAV,aAAa,EAAE;IACjB;IAEA,gBAAgB;QACdT,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNc,UAAU;QACZ;QACAV,aAAa,EAAE;IACjB;IAEA,mBAAmB;IACnBW,UAAU;QACRpB,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAwC;YACrDC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;gBACVS,OAAO;YACT;SACD;IACH;IAEAC,SAAS;QACPtB,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAiC;YAC9CC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAW,OAAO;QACLvB,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAqC;YAClDC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAY,UAAU;QACRxB,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAA4B;YACzCC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;YACA;gBACEX,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEA,qBAAqB;IACrB,gBAAgB;QACdZ,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAA4C;YACzDC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAa,KAAK;QACHzB,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAiB;YAC9BC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAc,YAAY;QACV1B,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAA4B;YACzCC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAe,UAAU;QACR3B,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAwB;YACrCC,KAAK,CAAC;QACR;QACAC,aAAa,EAAE;IACjB;IAEA,oBAAoB;IACpBmB,QAAQ;QACN5B,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAsB;YACnCC,KAAK,CAAC;QACR;QACAC,aAAa,EAAE;IACjB;IAEAoB,YAAY;QACV7B,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNc,UAAU;QACZ;QACAV,aAAa,EAAE;IACjB;IAEA,UAAU;QACRT,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAa;YAC1BC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;YACA;gBACEX,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;YACA;gBACEX,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEA,2BAA2B;IAC3BkB,OAAO;QACL9B,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;gBAA2B;gBAAe;aAAQ;YAC/DC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;YACA;gBACEX,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAmB,QAAQ;QACN/B,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAA8B;YAC3CC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEA,gBAAgB;QACdZ,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAsC;YACnDC,KAAK,CAAC;QACR;QACAC,aAAa,EAAE;IACjB;IAEA,eAAe;QACbT,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAqC;YAClDC,KAAK,CAAC;QACR;QACAC,aAAa,EAAE;IACjB;IAEA,uBAAuB;IACvBuB,QAAQ;QACNhC,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;gBAAe;aAAc;YAC1CC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;YACZ;SACD;IACH;IAEAqB,QAAQ;QACNjC,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAoB;YACjCC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;gBACVS,OAAO;YACT;YACA;gBACEpB,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;gBACVS,OAAO;YACT;SACD;IACH;IAEA,sBAAsB;IACtBa,WAAW;QACTlC,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAAyC;YACtDC,KAAK,CAAC;QACR;QACAC,aAAa,EAAE;IACjB;IAEA,yBAAyB;IACzB0B,YAAY;QACVnC,IAAI;QACJC,MAAM;QACNC,aAAa;QACbC,UAAU;QACVC,QAAQ;YACNC,MAAM;YACNC,SAAS;YACTC,MAAM;gBAAC;gBAAM;aAA0C;YACvDC,KAAK,CAAC;QACR;QACAC,aAAa;YACX;gBACER,MAAM;gBACNS,QAAQ;gBACRC,aAAa;gBACbC,UAAU;gBACVS,OAAO;YACT;SACD;IACH;AACF;AAEO,SAASvB,uBAAuBK,QAAqB;IAC1D,OAAOiC,OAAOC,MAAM,CAAC1C,eAAe2C,MAAM,CAACC,CAAAA,IAAKA,EAAEpC,QAAQ,KAAKA;AACjE;AAEO,SAASP;IACd,OAAOwC,OAAOC,MAAM,CAAC1C;AACvB;AAEO,SAASE,YAAYG,EAAU;IACpC,OAAOL,aAAa,CAACK,GAAG;AAC1B"}
@@ -0,0 +1,187 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "CastOAuthProvider", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return CastOAuthProvider;
9
+ }
10
+ });
11
+ const _fs = /*#__PURE__*/ _interop_require_wildcard(require("fs"));
12
+ const _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
13
+ const _http = /*#__PURE__*/ _interop_require_wildcard(require("http"));
14
+ const _os = require("os");
15
+ const _child_process = require("child_process");
16
+ function _getRequireWildcardCache(nodeInterop) {
17
+ if (typeof WeakMap !== "function") return null;
18
+ var cacheBabelInterop = new WeakMap();
19
+ var cacheNodeInterop = new WeakMap();
20
+ return (_getRequireWildcardCache = function(nodeInterop) {
21
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
22
+ })(nodeInterop);
23
+ }
24
+ function _interop_require_wildcard(obj, nodeInterop) {
25
+ if (!nodeInterop && obj && obj.__esModule) {
26
+ return obj;
27
+ }
28
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
29
+ return {
30
+ default: obj
31
+ };
32
+ }
33
+ var cache = _getRequireWildcardCache(nodeInterop);
34
+ if (cache && cache.has(obj)) {
35
+ return cache.get(obj);
36
+ }
37
+ var newObj = {
38
+ __proto__: null
39
+ };
40
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
41
+ for(var key in obj){
42
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
43
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
44
+ if (desc && (desc.get || desc.set)) {
45
+ Object.defineProperty(newObj, key, desc);
46
+ } else {
47
+ newObj[key] = obj[key];
48
+ }
49
+ }
50
+ }
51
+ newObj.default = obj;
52
+ if (cache) {
53
+ cache.set(obj, newObj);
54
+ }
55
+ return newObj;
56
+ }
57
+ const CAST_AUTH_DIR = _path.join((0, _os.homedir)(), '.cast', 'mcp-auth');
58
+ let CastOAuthProvider = class CastOAuthProvider {
59
+ get redirectUrl() {
60
+ return `http://127.0.0.1:${this.port}/callback`;
61
+ }
62
+ get clientMetadata() {
63
+ return {
64
+ client_name: 'Cast Code',
65
+ redirect_uris: [
66
+ this.redirectUrl
67
+ ],
68
+ grant_types: [
69
+ 'authorization_code',
70
+ 'refresh_token'
71
+ ],
72
+ response_types: [
73
+ 'code'
74
+ ],
75
+ token_endpoint_auth_method: 'none'
76
+ };
77
+ }
78
+ clientInformation() {
79
+ const file = _path.join(this.authDir, 'client.json');
80
+ if (!_fs.existsSync(file)) return undefined;
81
+ try {
82
+ return JSON.parse(_fs.readFileSync(file, 'utf-8'));
83
+ } catch {
84
+ return undefined;
85
+ }
86
+ }
87
+ saveClientInformation(info) {
88
+ _fs.writeFileSync(_path.join(this.authDir, 'client.json'), JSON.stringify(info, null, 2));
89
+ }
90
+ tokens() {
91
+ const file = _path.join(this.authDir, 'tokens.json');
92
+ if (!_fs.existsSync(file)) return undefined;
93
+ try {
94
+ return JSON.parse(_fs.readFileSync(file, 'utf-8'));
95
+ } catch {
96
+ return undefined;
97
+ }
98
+ }
99
+ saveTokens(tokens) {
100
+ _fs.writeFileSync(_path.join(this.authDir, 'tokens.json'), JSON.stringify(tokens, null, 2));
101
+ }
102
+ redirectToAuthorization(url) {
103
+ try {
104
+ (0, _child_process.spawn)('xdg-open', [
105
+ url.toString()
106
+ ], {
107
+ detached: true,
108
+ stdio: 'ignore'
109
+ }).unref();
110
+ } catch {
111
+ // Silently ignore if xdg-open is not available
112
+ }
113
+ }
114
+ saveCodeVerifier(verifier) {
115
+ _fs.writeFileSync(_path.join(this.authDir, 'verifier.txt'), verifier);
116
+ }
117
+ codeVerifier() {
118
+ const file = _path.join(this.authDir, 'verifier.txt');
119
+ if (!_fs.existsSync(file)) throw new Error(`No PKCE code verifier saved for ${this.serverName}`);
120
+ return _fs.readFileSync(file, 'utf-8');
121
+ }
122
+ invalidateCredentials(scope) {
123
+ const remove = (name)=>{
124
+ const f = _path.join(this.authDir, name);
125
+ if (_fs.existsSync(f)) _fs.unlinkSync(f);
126
+ };
127
+ if (scope === 'all' || scope === 'tokens') remove('tokens.json');
128
+ if (scope === 'all' || scope === 'client') remove('client.json');
129
+ if (scope === 'all' || scope === 'verifier') remove('verifier.txt');
130
+ }
131
+ /**
132
+ * Starts a local HTTP server on the callback port.
133
+ * Returns a Promise that resolves with the authorization code when the user
134
+ * completes the OAuth flow in their browser.
135
+ *
136
+ * @param onListening Optional callback fired when the server is ready (before opening browser)
137
+ */ waitForCallback(onListening) {
138
+ return new Promise((resolve, reject)=>{
139
+ const server = _http.createServer((req, res)=>{
140
+ try {
141
+ const url = new URL(req.url ?? '/', `http://127.0.0.1:${this.port}`);
142
+ const code = url.searchParams.get('code');
143
+ const error = url.searchParams.get('error');
144
+ const successHtml = `
145
+ <html><body style="font-family:sans-serif;text-align:center;padding:40px;background:#f0fdf4">
146
+ <h2 style="color:#16a34a">✅ Autenticação concluída!</h2>
147
+ <p>Pode fechar esta aba e voltar ao terminal.</p>
148
+ </body></html>`;
149
+ const errorHtml = `
150
+ <html><body style="font-family:sans-serif;text-align:center;padding:40px;background:#fef2f2">
151
+ <h2 style="color:#dc2626">❌ Erro na autenticação</h2>
152
+ <p>${error ?? 'Erro desconhecido'}</p>
153
+ </body></html>`;
154
+ res.writeHead(200, {
155
+ 'Content-Type': 'text/html; charset=utf-8'
156
+ });
157
+ if (code) {
158
+ res.end(successHtml);
159
+ server.close();
160
+ resolve(code);
161
+ } else {
162
+ res.end(errorHtml);
163
+ server.close();
164
+ reject(new Error(`OAuth error: ${error ?? 'unknown'}`));
165
+ }
166
+ } catch (e) {
167
+ server.close();
168
+ reject(e);
169
+ }
170
+ });
171
+ server.on('error', (err)=>reject(err));
172
+ server.listen(this.port, '127.0.0.1', ()=>{
173
+ if (onListening) onListening();
174
+ });
175
+ });
176
+ }
177
+ constructor(serverName, port = 18090){
178
+ this.serverName = serverName;
179
+ this.authDir = _path.join(CAST_AUTH_DIR, serverName);
180
+ this.port = port;
181
+ _fs.mkdirSync(this.authDir, {
182
+ recursive: true
183
+ });
184
+ }
185
+ };
186
+
187
+ //# sourceMappingURL=cast-oauth-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/modules/mcp/services/cast-oauth-provider.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as http from 'http';\nimport { homedir } from 'os';\nimport { spawn } from 'child_process';\nimport type {\n OAuthClientProvider,\n OAuthClientMetadata,\n OAuthClientInformationMixed,\n OAuthTokens,\n} from '@modelcontextprotocol/sdk/client/auth.js';\n\nconst CAST_AUTH_DIR = path.join(homedir(), '.cast', 'mcp-auth');\n\n/**\n * Implements OAuthClientProvider for cast-code CLI.\n * Stores tokens and client info in ~/.cast/mcp-auth/<serverName>/\n */\nexport class CastOAuthProvider implements OAuthClientProvider {\n private readonly authDir: string;\n private readonly port: number;\n\n constructor(\n private readonly serverName: string,\n port = 18090,\n ) {\n this.authDir = path.join(CAST_AUTH_DIR, serverName);\n this.port = port;\n fs.mkdirSync(this.authDir, { recursive: true });\n }\n\n get redirectUrl(): string {\n return `http://127.0.0.1:${this.port}/callback`;\n }\n\n get clientMetadata(): OAuthClientMetadata {\n return {\n client_name: 'Cast Code',\n redirect_uris: [this.redirectUrl],\n grant_types: ['authorization_code', 'refresh_token'],\n response_types: ['code'],\n token_endpoint_auth_method: 'none',\n };\n }\n\n clientInformation(): OAuthClientInformationMixed | undefined {\n const file = path.join(this.authDir, 'client.json');\n if (!fs.existsSync(file)) return undefined;\n try {\n return JSON.parse(fs.readFileSync(file, 'utf-8'));\n } catch {\n return undefined;\n }\n }\n\n saveClientInformation(info: OAuthClientInformationMixed): void {\n fs.writeFileSync(\n path.join(this.authDir, 'client.json'),\n JSON.stringify(info, null, 2),\n );\n }\n\n tokens(): OAuthTokens | undefined {\n const file = path.join(this.authDir, 'tokens.json');\n if (!fs.existsSync(file)) return undefined;\n try {\n return JSON.parse(fs.readFileSync(file, 'utf-8'));\n } catch {\n return undefined;\n }\n }\n\n saveTokens(tokens: OAuthTokens): void {\n fs.writeFileSync(\n path.join(this.authDir, 'tokens.json'),\n JSON.stringify(tokens, null, 2),\n );\n }\n\n redirectToAuthorization(url: URL): void {\n try {\n spawn('xdg-open', [url.toString()], { detached: true, stdio: 'ignore' }).unref();\n } catch {\n // Silently ignore if xdg-open is not available\n }\n }\n\n saveCodeVerifier(verifier: string): void {\n fs.writeFileSync(path.join(this.authDir, 'verifier.txt'), verifier);\n }\n\n codeVerifier(): string {\n const file = path.join(this.authDir, 'verifier.txt');\n if (!fs.existsSync(file)) throw new Error(`No PKCE code verifier saved for ${this.serverName}`);\n return fs.readFileSync(file, 'utf-8');\n }\n\n invalidateCredentials(scope: 'all' | 'client' | 'tokens' | 'verifier'): void {\n const remove = (name: string) => {\n const f = path.join(this.authDir, name);\n if (fs.existsSync(f)) fs.unlinkSync(f);\n };\n if (scope === 'all' || scope === 'tokens') remove('tokens.json');\n if (scope === 'all' || scope === 'client') remove('client.json');\n if (scope === 'all' || scope === 'verifier') remove('verifier.txt');\n }\n\n /**\n * Starts a local HTTP server on the callback port.\n * Returns a Promise that resolves with the authorization code when the user\n * completes the OAuth flow in their browser.\n *\n * @param onListening Optional callback fired when the server is ready (before opening browser)\n */\n waitForCallback(onListening?: () => void): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n const server = http.createServer((req, res) => {\n try {\n const url = new URL(req.url ?? '/', `http://127.0.0.1:${this.port}`);\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n\n const successHtml = `\n <html><body style=\"font-family:sans-serif;text-align:center;padding:40px;background:#f0fdf4\">\n <h2 style=\"color:#16a34a\">✅ Autenticação concluída!</h2>\n <p>Pode fechar esta aba e voltar ao terminal.</p>\n </body></html>`;\n\n const errorHtml = `\n <html><body style=\"font-family:sans-serif;text-align:center;padding:40px;background:#fef2f2\">\n <h2 style=\"color:#dc2626\">❌ Erro na autenticação</h2>\n <p>${error ?? 'Erro desconhecido'}</p>\n </body></html>`;\n\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });\n\n if (code) {\n res.end(successHtml);\n server.close();\n resolve(code);\n } else {\n res.end(errorHtml);\n server.close();\n reject(new Error(`OAuth error: ${error ?? 'unknown'}`));\n }\n } catch (e) {\n server.close();\n reject(e);\n }\n });\n\n server.on('error', (err) => reject(err));\n server.listen(this.port, '127.0.0.1', () => {\n if (onListening) onListening();\n });\n });\n }\n}\n"],"names":["CastOAuthProvider","CAST_AUTH_DIR","path","join","homedir","redirectUrl","port","clientMetadata","client_name","redirect_uris","grant_types","response_types","token_endpoint_auth_method","clientInformation","file","authDir","fs","existsSync","undefined","JSON","parse","readFileSync","saveClientInformation","info","writeFileSync","stringify","tokens","saveTokens","redirectToAuthorization","url","spawn","toString","detached","stdio","unref","saveCodeVerifier","verifier","codeVerifier","Error","serverName","invalidateCredentials","scope","remove","name","f","unlinkSync","waitForCallback","onListening","Promise","resolve","reject","server","http","createServer","req","res","URL","code","searchParams","get","error","successHtml","errorHtml","writeHead","end","close","e","on","err","listen","mkdirSync","recursive"],"mappings":"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"}
@@ -11,6 +11,8 @@ Object.defineProperty(exports, "McpClientService", {
11
11
  const _common = require("@nestjs/common");
12
12
  const _events = require("events");
13
13
  const _child_process = require("child_process");
14
+ const _auth = require("@modelcontextprotocol/sdk/client/auth.js");
15
+ const _castoauthprovider = require("./cast-oauth-provider");
14
16
  function _ts_decorate(decorators, target, key, desc) {
15
17
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
16
18
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -103,59 +105,88 @@ let McpClientService = class McpClientService extends _events.EventEmitter {
103
105
  }
104
106
  async connectHttp(name, connection) {
105
107
  const endpoint = connection.config.endpoint;
106
- const headers = {
107
- 'Content-Type': 'application/json'
108
- };
109
- if (connection.config.env?.AUTH_TOKEN) {
110
- headers['Authorization'] = `Bearer ${connection.config.env.AUTH_TOKEN}`;
111
- }
112
108
  try {
113
109
  new URL(endpoint);
114
110
  } catch {
115
111
  throw new Error(`Invalid MCP HTTP endpoint: ${endpoint}`);
116
112
  }
117
- const controller = new AbortController();
118
- const timeout = setTimeout(()=>controller.abort(), 10000);
119
- const initResponse = await fetch(endpoint, {
120
- method: 'POST',
121
- headers,
122
- body: JSON.stringify({
123
- jsonrpc: '2.0',
124
- id: this.nextId(),
125
- method: 'initialize',
126
- params: {
127
- protocolVersion: '2024-11-05',
128
- capabilities: {},
129
- clientInfo: {
130
- name: 'cast-code',
131
- version: '1.0.0'
132
- }
113
+ const headers = {
114
+ 'Content-Type': 'application/json'
115
+ };
116
+ // Restore cached Bearer token if available (avoids re-running OAuth on reconnect)
117
+ const provider = new _castoauthprovider.CastOAuthProvider(name);
118
+ const cachedTokens = provider.tokens();
119
+ if (cachedTokens?.access_token) {
120
+ headers['Authorization'] = `Bearer ${cachedTokens.access_token}`;
121
+ }
122
+ const doFetch = async (body, hdrs = headers, timeoutMs = 15000)=>{
123
+ const controller = new AbortController();
124
+ const timer = setTimeout(()=>controller.abort(), timeoutMs);
125
+ try {
126
+ return await fetch(endpoint, {
127
+ method: 'POST',
128
+ headers: hdrs,
129
+ body: JSON.stringify(body),
130
+ signal: controller.signal
131
+ });
132
+ } finally{
133
+ clearTimeout(timer);
134
+ }
135
+ };
136
+ const initBody = {
137
+ jsonrpc: '2.0',
138
+ id: this.nextId(),
139
+ method: 'initialize',
140
+ params: {
141
+ protocolVersion: '2024-11-05',
142
+ capabilities: {},
143
+ clientInfo: {
144
+ name: 'cast-code',
145
+ version: '1.0.0'
133
146
  }
134
- }),
135
- signal: controller.signal
136
- });
137
- clearTimeout(timeout);
147
+ }
148
+ };
149
+ let initResponse = await doFetch(initBody);
150
+ // If 401: run full OAuth flow, then retry once with the new token
151
+ if (initResponse.status === 401) {
152
+ provider.invalidateCredentials('tokens');
153
+ let authResult = await (0, _auth.auth)(provider, {
154
+ serverUrl: endpoint
155
+ });
156
+ if (authResult === 'REDIRECT') {
157
+ this.emit('oauth:browser-opened', name, provider.redirectUrl);
158
+ const code = await provider.waitForCallback();
159
+ authResult = await (0, _auth.auth)(provider, {
160
+ serverUrl: endpoint,
161
+ authorizationCode: code
162
+ });
163
+ }
164
+ if (authResult !== 'AUTHORIZED') {
165
+ throw new Error(`OAuth failed for ${name}`);
166
+ }
167
+ const tokens = provider.tokens();
168
+ if (!tokens?.access_token) {
169
+ throw new Error(`No access token for ${name} after OAuth`);
170
+ }
171
+ headers['Authorization'] = `Bearer ${tokens.access_token}`;
172
+ initResponse = await doFetch(initBody);
173
+ }
138
174
  if (!initResponse.ok) {
139
175
  throw new Error(`HTTP MCP init failed: ${initResponse.status} ${initResponse.statusText}`);
140
176
  }
141
- const toolsController = new AbortController();
142
- const toolsTimeout = setTimeout(()=>toolsController.abort(), 10000);
143
- const toolsResponse = await fetch(endpoint, {
144
- method: 'POST',
145
- headers,
146
- body: JSON.stringify({
147
- jsonrpc: '2.0',
148
- id: this.nextId(),
149
- method: 'tools/list',
150
- params: {}
151
- }),
152
- signal: toolsController.signal
177
+ const sessionId = initResponse.headers.get('mcp-session-id');
178
+ if (sessionId) headers['Mcp-Session-Id'] = sessionId;
179
+ const toolsResponse = await doFetch({
180
+ jsonrpc: '2.0',
181
+ id: this.nextId(),
182
+ method: 'tools/list',
183
+ params: {}
153
184
  });
154
- clearTimeout(toolsTimeout);
155
185
  if (toolsResponse.ok) {
156
186
  const data = await toolsResponse.json();
157
187
  connection.tools = data.result?.tools || data.tools || [];
158
188
  }
189
+ connection._httpHeaders = headers;
159
190
  }
160
191
  sendRequest(name, method, params) {
161
192
  const connection = this.connections.get(name);
@@ -202,12 +233,10 @@ let McpClientService = class McpClientService extends _events.EventEmitter {
202
233
  }
203
234
  if (connection.config.type === 'http') {
204
235
  const endpoint = connection.config.endpoint;
205
- const headers = {
236
+ // Use headers stored during connectHttp (includes Bearer token + session ID)
237
+ const headers = connection._httpHeaders ?? {
206
238
  'Content-Type': 'application/json'
207
239
  };
208
- if (connection.config.env?.AUTH_TOKEN) {
209
- headers['Authorization'] = `Bearer ${connection.config.env.AUTH_TOKEN}`;
210
- }
211
240
  const response = await fetch(endpoint, {
212
241
  method: 'POST',
213
242
  headers,
@@ -232,6 +261,9 @@ let McpClientService = class McpClientService extends _events.EventEmitter {
232
261
  getStatus(name) {
233
262
  return this.connections.get(name)?.status || 'unknown';
234
263
  }
264
+ getAuthUrl(name) {
265
+ return this.connections.get(name)?.authUrl;
266
+ }
235
267
  getAllStatuses() {
236
268
  const statuses = new Map();
237
269
  for (const [name, conn] of this.connections){