breathe-api
Version:
Model Context Protocol server for Breathe HR APIs with Swagger/OpenAPI support - also works with custom APIs
247 lines • 9.9 kB
JavaScript
import { z } from 'zod';
import { resourceManager } from '../utils/resource-manager.js';
export const listEnvironmentsTool = {
name: 'list_environments',
description: 'List all configured Breathe HR environments with their status and configuration',
inputSchema: z.object({}).strict(),
handler: async () => {
const environments = ['production', 'staging', 'development', 'sandbox'];
const activeEnv = resourceManager.getActiveEnvironment();
const envList = environments.map(name => {
const env = resourceManager.getEnvironment(name);
if (!env)
return null;
return {
name: env.name,
displayName: env.displayName,
description: env.description,
baseUrl: env.baseUrl,
isActive: env.name === activeEnv.name,
authType: env.auth.type,
hasCredentials: !!(env.auth.username || env.auth.token || env.auth.apiKey),
metadata: env.metadata
};
}).filter(Boolean);
return {
environments: envList,
activeEnvironment: activeEnv.name,
totalEnvironments: envList.length
};
}
};
export const switchEnvironmentTool = {
name: 'switch_environment',
description: 'Switch the active Breathe HR environment for API calls',
inputSchema: z.object({
environment: z.enum(['production', 'staging', 'development', 'sandbox'])
.describe('The environment to switch to')
}).strict(),
handler: async (input) => {
const previousEnv = resourceManager.getActiveEnvironment();
resourceManager.setActiveEnvironment(input.environment);
const newEnv = resourceManager.getActiveEnvironment();
return {
previousEnvironment: previousEnv.name,
currentEnvironment: newEnv.name,
baseUrl: newEnv.baseUrl,
authType: newEnv.auth.type,
message: `Switched from ${previousEnv.displayName} to ${newEnv.displayName}`
};
}
};
export const discoverEndpointsTool = {
name: 'discover_endpoints',
description: 'Discover available API endpoints for a specific Breathe HR environment by analyzing its Swagger/OpenAPI specification',
inputSchema: z.object({
environment: z.enum(['production', 'staging', 'development', 'sandbox'])
.describe('The environment to discover endpoints for')
.optional(),
filter: z.string()
.describe('Optional filter to search for specific endpoints')
.optional()
}).strict(),
handler: async (input) => {
const targetEnv = input.environment || resourceManager.getActiveEnvironment().name;
const discovery = await resourceManager.discoverEndpoints(targetEnv);
let endpoints = discovery.endpoints;
if (input.filter) {
const filterLower = input.filter.toLowerCase();
endpoints = endpoints.filter(ep => ep.path.toLowerCase().includes(filterLower) ||
ep.description?.toLowerCase().includes(filterLower) ||
ep.method.toLowerCase().includes(filterLower));
}
return {
environment: discovery.environment,
totalEndpoints: discovery.endpoints.length,
filteredEndpoints: endpoints.length,
endpoints: endpoints.slice(0, 50),
timestamp: discovery.timestamp,
filter: input.filter
};
}
};
export const readResourceTool = {
name: 'read_resource',
description: 'Read a resource from the Breathe HR API using a resource URI',
inputSchema: z.object({
uri: z.string()
.describe('Resource URI (e.g., breathe://production/employees, config://staging/environment)')
}).strict(),
handler: async (input) => {
const content = await resourceManager.readResource(input.uri);
let parsedContent;
try {
parsedContent = JSON.parse(content.text || '{}');
}
catch {
parsedContent = content.text;
}
return {
uri: content.uri,
mimeType: content.mimeType,
content: parsedContent,
size: content.text?.length || content.blob?.length || 0
};
}
};
export const configureEnvironmentTool = {
name: 'configure_environment',
description: 'Update configuration for a Breathe HR environment',
inputSchema: z.object({
environment: z.enum(['production', 'staging', 'development', 'sandbox'])
.describe('The environment to configure'),
baseUrl: z.string()
.describe('Base URL for the API')
.optional(),
authType: z.enum(['basic', 'bearer', 'api-key'])
.describe('Authentication type')
.optional(),
displayName: z.string()
.describe('Display name for the environment')
.optional(),
description: z.string()
.describe('Description of the environment')
.optional(),
metadata: z.object({
region: z.string().optional(),
version: z.string().optional(),
contact: z.string().optional()
}).optional()
}).strict(),
handler: async (input) => {
const { environment, ...updates } = input;
const envUpdates = {};
if (updates.baseUrl)
envUpdates.baseUrl = updates.baseUrl;
if (updates.displayName)
envUpdates.displayName = updates.displayName;
if (updates.description)
envUpdates.description = updates.description;
if (updates.metadata)
envUpdates.metadata = updates.metadata;
if (updates.authType) {
const currentEnv = resourceManager.getEnvironment(environment);
if (currentEnv) {
envUpdates.auth = {
...currentEnv.auth,
type: updates.authType
};
}
}
resourceManager.updateEnvironment(environment, envUpdates);
const updatedEnv = resourceManager.getEnvironment(environment);
return {
environment: environment,
updated: true,
configuration: {
displayName: updatedEnv?.displayName,
description: updatedEnv?.description,
baseUrl: updatedEnv?.baseUrl,
authType: updatedEnv?.auth.type,
metadata: updatedEnv?.metadata
}
};
}
};
export const testEnvironmentTool = {
name: 'test_environment',
description: 'Test connectivity and authentication for a Breathe HR environment',
inputSchema: z.object({
environment: z.enum(['production', 'staging', 'development', 'sandbox'])
.describe('The environment to test')
.optional()
}).strict(),
handler: async (input) => {
const targetEnv = input.environment || resourceManager.getActiveEnvironment().name;
const results = {
environment: targetEnv,
tests: {
configuration: { passed: false, message: '' },
authentication: { passed: false, message: '' },
swagger: { passed: false, message: '' },
apiAccess: { passed: false, message: '' }
}
};
try {
const env = resourceManager.getEnvironment(targetEnv);
if (env) {
results.tests.configuration.passed = true;
results.tests.configuration.message = 'Environment configured';
}
else {
results.tests.configuration.message = 'Environment not found';
}
}
catch (error) {
results.tests.configuration.message = error.message;
}
try {
const env = resourceManager.getEnvironment(targetEnv);
if (env?.auth) {
const hasAuth = !!((env.auth.username && env.auth.password) ||
env.auth.token ||
env.auth.apiKey);
results.tests.authentication.passed = hasAuth;
results.tests.authentication.message = hasAuth
? `${env.auth.type} authentication configured`
: 'No authentication credentials found';
}
}
catch (error) {
results.tests.authentication.message = error.message;
}
try {
await resourceManager.readResource(`swagger://${targetEnv}/spec`);
results.tests.swagger.passed = true;
results.tests.swagger.message = 'Swagger specification accessible';
}
catch (error) {
results.tests.swagger.message = `Failed to fetch Swagger: ${error.message}`;
}
try {
await resourceManager.readResource(`breathe://${targetEnv}/api/employees`);
results.tests.apiAccess.passed = true;
results.tests.apiAccess.message = 'API endpoints accessible';
}
catch (error) {
results.tests.apiAccess.message = `API access failed: ${error.message}`;
}
const allPassed = Object.values(results.tests).every(test => test.passed);
return {
...results,
overallStatus: allPassed ? 'healthy' : 'issues detected',
recommendation: allPassed
? 'Environment is properly configured and accessible'
: 'Check failed tests and ensure proper configuration'
};
}
};
export const resourceTools = [
listEnvironmentsTool,
switchEnvironmentTool,
discoverEndpointsTool,
readResourceTool,
configureEnvironmentTool,
testEnvironmentTool
];
//# sourceMappingURL=resource-tools.js.map