import { z } from 'zod';
/**
* Spec source configuration - one of url, file, or inline
*/
export const specSchema = z.object({
/** URL to fetch OpenAPI spec from */
url: z.string().url().optional(),
/** Local file path to OpenAPI spec */
file: z.string().optional(),
/** Inline spec content (YAML or JSON string) */
inline: z.string().optional(),
}).refine(
(data) => data.url || data.file || data.inline,
{ message: 'One of spec.url, spec.file, or spec.inline must be provided' }
);
/**
* Upstream API configuration
*/
export const upstreamSchema = z.object({
/** Base URL for the upstream API */
baseUrl: z.string().url(),
/** Request timeout in milliseconds */
timeout: z.number().min(1000).max(300000).default(30000),
/** Additional headers to send with every request */
headers: z.record(z.string()).optional(),
});
/**
* Server configuration
*/
export const serverSchema = z.object({
/** Port to listen on */
port: z.number().min(1).max(65535).default(8080),
/** Host to bind to */
host: z.string().default('0.0.0.0'),
/** Base path for MCP endpoint */
basePath: z.string().default('/mcp'),
});
/**
* Tool filtering configuration
*/
export const toolsSchema = z.object({
/** Glob patterns to include tools (e.g., ["get_*", "list_*"]) */
include: z.array(z.string()).optional(),
/** Glob patterns to exclude tools (e.g., ["*_admin_*"]) */
exclude: z.array(z.string()).optional(),
/** Include only operations with these OpenAPI tags */
includeTags: z.array(z.string()).optional(),
/** Auto-disable configuration */
autoDisable: z.object({
/** HTTP methods to disable by default */
methods: z.array(z.enum(['DELETE', 'PUT', 'PATCH', 'POST'])).default(['DELETE']),
/** Disable deprecated operations */
deprecated: z.boolean().default(true),
}).default({}),
/** Warning thresholds */
warnings: z.object({
/** Enable/disable warnings */
enabled: z.boolean().default(true),
/** Warn if more than this many tools */
threshold: z.number().min(1).default(10),
/** Strong warning threshold */
strongThreshold: z.number().min(1).default(40),
/** Error threshold */
errorThreshold: z.number().min(1).default(100),
}).default({}),
/** @deprecated Use warnings.threshold instead */
maxToolsWarning: z.number().min(1).default(10),
});
/**
* Authentication configuration
*/
export const authSchema = z.object({
/** Auth type */
type: z.enum(['none', 'apiKey', 'bearer', 'basic']).default('none'),
/** Location for API key (header or query) */
in: z.enum(['header', 'query']).default('header'),
/** Header/query parameter name for API key */
name: z.string().default('X-API-Key'),
/** Static value (supports ${ENV_VAR} interpolation) */
value: z.string().optional(),
});
/**
* Logging configuration
*/
export const loggingSchema = z.object({
/** Log level */
level: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
/** Log format */
format: z.enum(['json', 'pretty']).default('json'),
});
/**
* Complete configuration schema
*/
export const configSchema = z.object({
/** Spec source */
spec: specSchema,
/** Spec format (auto-detected if not specified) */
format: z.enum(['openapi', 'postman']).optional(),
/** Upstream API config */
upstream: upstreamSchema,
/** Server config */
server: serverSchema.default({}),
/** Tool filtering */
tools: toolsSchema.default({}),
/** Auth config */
auth: authSchema.default({}),
/** Logging config */
logging: loggingSchema.default({}),
});
/**
* Inferred configuration type
*/
export type Config = z.infer<typeof configSchema>;
/**
* Partial config for merging
*/
export type PartialConfig = z.input<typeof configSchema>;