@mseep/mcp-codex-keeper
Version:
An intelligent MCP server that serves as a guardian of development knowledge, providing AI assistants with curated access to latest documentation and best practices
124 lines • 3.76 kB
JavaScript
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { InvalidDocUrlError, } from '../types/index.js';
/**
* Validates if a value is a valid DocCategory
* @param category - Value to check
* @returns Type guard for DocCategory
*/
export function isValidCategory(category) {
return (typeof category === 'string' &&
[
'Languages',
'Frameworks',
'Libraries',
'Tools',
'APIs',
'Guides',
'Reference',
'Standards',
'Other',
].includes(category));
}
/**
* Validates a URL string
* @param url - URL to validate
* @throws {InvalidDocUrlError} If URL is invalid
*/
function validateUrl(url) {
try {
new URL(url);
}
catch {
throw new InvalidDocUrlError(url);
}
}
/**
* Validates tags array
* @param tags - Array of tags to validate
* @returns Cleaned and validated tags array
*/
function validateTags(tags) {
if (!Array.isArray(tags)) {
return [];
}
return tags
.filter((tag) => typeof tag === 'string')
.map(tag => tag.trim())
.filter(tag => tag.length > 0);
}
/**
* Validates version string
* @param version - Version to validate
* @returns Cleaned version string or undefined
*/
function validateVersion(version) {
if (typeof version !== 'string') {
return undefined;
}
const cleaned = version.trim();
return cleaned.length > 0 ? cleaned : undefined;
}
/**
* Validates arguments for adding documentation
* @param args - Arguments to validate
* @throws {McpError} If validation fails
* @returns Validated AddDocArgs
*/
export function validateAddDocArgs(args) {
// Check required fields
if (typeof args.name !== 'string' ||
typeof args.url !== 'string' ||
!isValidCategory(args.category)) {
throw new McpError(ErrorCode.InvalidParams, 'Invalid parameters: name (string), url (string), and category (valid category) are required');
}
// Validate URL format
validateUrl(args.url);
// Validate description
if (args.description !== undefined && typeof args.description !== 'string') {
throw new McpError(ErrorCode.InvalidParams, 'Description must be a string if provided');
}
return {
name: args.name.trim(),
url: args.url.trim(),
description: args.description?.trim() || '',
category: args.category,
tags: validateTags(args.tags),
version: validateVersion(args.version),
};
}
/**
* Validates arguments for updating documentation
* @param args - Arguments to validate
* @throws {McpError} If validation fails
* @returns Validated UpdateDocArgs
*/
export function validateUpdateDocArgs(args) {
if (typeof args.name !== 'string') {
throw new McpError(ErrorCode.InvalidParams, 'Invalid parameters: name (string) is required');
}
return {
name: args.name.trim(),
force: args.force === true,
};
}
/**
* Validates arguments for searching documentation
* @param args - Arguments to validate
* @throws {McpError} If validation fails
* @returns Validated SearchDocArgs
*/
export function validateSearchDocArgs(args) {
if (typeof args.query !== 'string') {
throw new McpError(ErrorCode.InvalidParams, 'Invalid parameters: query (string) is required');
}
const category = args.category;
if (category !== undefined && !isValidCategory(category)) {
throw new McpError(ErrorCode.InvalidParams, 'Invalid category');
}
return {
query: args.query.trim(),
category: category,
tag: typeof args.tag === 'string' ? args.tag.trim() : undefined,
};
}
//# sourceMappingURL=index.js.map