breathe-api
Version:
Model Context Protocol server for Breathe HR APIs with Swagger/OpenAPI support - also works with custom APIs
81 lines • 2.44 kB
JavaScript
import { z } from 'zod';
import fs from 'fs/promises';
import path from 'path';
const ApiConfigSchema = z.object({
name: z.string(),
baseUrl: z.string().url(),
auth: z.object({
type: z.enum(['none', 'bearer', 'api-key', 'oauth']),
config: z.any().optional(),
}).optional(),
headers: z.record(z.string()).optional(),
timeout: z.number().optional(),
});
const ConfigSchema = z.object({
apis: z.array(ApiConfigSchema),
defaults: z.object({
timeout: z.number().default(30000),
retries: z.number().default(3),
headers: z.record(z.string()).optional(),
}).optional(),
});
export class ConfigManager {
config = null;
configPath;
constructor(configPath) {
this.configPath = configPath || path.join(process.cwd(), 'api-mcp.config.json');
}
async load() {
try {
const content = await fs.readFile(this.configPath, 'utf-8');
const rawConfig = JSON.parse(content);
this.config = ConfigSchema.parse(rawConfig);
return this.config;
}
catch (error) {
if (error.code === 'ENOENT') {
this.config = {
apis: [],
defaults: {
timeout: 30000,
retries: 3,
},
};
await this.save();
return this.config;
}
throw error;
}
}
async save() {
if (!this.config) {
throw new Error('No config loaded');
}
await fs.writeFile(this.configPath, JSON.stringify(this.config, null, 2), 'utf-8');
}
getApi(name) {
return this.config?.apis.find(api => api.name === name);
}
async addApi(api) {
if (!this.config) {
await this.load();
}
const existing = this.config.apis.findIndex(a => a.name === api.name);
if (existing !== -1) {
this.config.apis[existing] = api;
}
else {
this.config.apis.push(api);
}
await this.save();
}
async removeApi(name) {
if (!this.config) {
await this.load();
}
this.config.apis = this.config.apis.filter(api => api.name !== name);
await this.save();
}
}
export const configManager = new ConfigManager();
//# sourceMappingURL=index.js.map