UNPKG

@kimsungwhee/apple-docs-mcp

Version:

MCP server for Apple Developer Documentation - Search iOS/macOS/SwiftUI/UIKit docs, WWDC videos, Swift/Objective-C APIs & code examples in Claude, Cursor & AI assistants

174 lines 9.97 kB
/** * Tool handlers for Apple Developer Documentation MCP Server */ import { searchAppleDocsSchema, getAppleDocContentSchema, listTechnologiesSchema, searchFrameworkSymbolsSchema, getRelatedApisSchema, resolveReferencesBatchSchema, getPlatformCompatibilitySchema, findSimilarApisSchema, getDocumentationUpdatesSchema, getTechnologyOverviewsSchema, getSampleCodeSchema, } from '../schemas/index.js'; import { listWWDCVideosSchema, searchWWDCContentSchema, getWWDCVideoSchema, getWWDCCodeExamplesSchema, browseWWDCTopicsSchema, findRelatedWWDCVideosSchema, } from '../schemas/wwdc.schemas.js'; import { handleListWWDCVideos, handleSearchWWDCContent, handleGetWWDCVideo, handleGetWWDCCodeExamples, handleBrowseWWDCTopics, handleFindRelatedWWDCVideos, } from './wwdc/wwdc-handlers.js'; /** * Map of tool names to their handlers */ export const toolHandlers = { get_performance_report: async () => { const { httpClient } = await import('../utils/http-client.js'); const { getCacheWarmUpStatus } = await import('../utils/cache-warmer.js'); const { getPreloadStats } = await import('../utils/preloader.js'); const { globalRateLimiter } = await import('../utils/rate-limiter.js'); let report = '# Performance Report\n\n'; // HTTP Client Performance report += httpClient.getPerformanceReport(); report += '\n\n'; // Cache Warm-up Status const warmUpStatus = getCacheWarmUpStatus(); report += '## Cache Warm-up Status\n\n'; report += `- **Total Cache Entries:** ${warmUpStatus.totalCacheEntries}\n`; report += `- **API Cache:** ${warmUpStatus.apiCacheSize} entries\n`; report += `- **Technologies Cache:** ${warmUpStatus.technologiesCacheSize} entries\n`; report += `- **Updates Cache:** ${warmUpStatus.updatesCacheSize} entries\n`; report += `- **Overviews Cache:** ${warmUpStatus.overviewsCacheSize} entries\n\n`; // Framework Preload Status const preloadStats = getPreloadStats(); report += '## Framework Preload Status\n\n'; report += `- **Preloaded Frameworks:** ${preloadStats.preloadedFrameworks.join(', ')}\n`; report += `- **Index Cache Hit Rate:** ${preloadStats.cacheHitRate}\n\n`; // Rate Limiter Status const rateLimiterStats = globalRateLimiter.getStats(); report += '## Rate Limiter Status\n\n'; report += `- **Current Requests:** ${rateLimiterStats.currentRequests}/${rateLimiterStats.maxRequests}\n`; report += `- **Utilization:** ${rateLimiterStats.utilizationRate}\n`; report += `- **Window:** ${rateLimiterStats.windowMs / 1000}s\n`; return { content: [ { type: 'text', text: report, }, ], }; }, get_cache_stats: async () => { const { apiCache, searchCache, indexCache, technologiesCache, updatesCache, sampleCodeCache, technologyOverviewsCache } = await import('../utils/cache.js'); const stats = { apiCache: apiCache.getStats(), searchCache: searchCache.getStats(), indexCache: indexCache.getStats(), technologiesCache: technologiesCache.getStats(), updatesCache: updatesCache.getStats(), sampleCodeCache: sampleCodeCache.getStats(), technologyOverviewsCache: technologyOverviewsCache.getStats(), }; let report = '# Cache Statistics Report\n\n'; Object.entries(stats).forEach(([name, stat]) => { report += `## ${name}\n`; report += `- Size: ${stat.size}/${stat.maxSize}\n`; report += `- Hit Rate: ${stat.hitRate}\n`; report += `- Hits: ${stat.hits}\n`; report += `- Misses: ${stat.misses}\n\n`; }); return { content: [ { type: 'text', text: report, }, ], }; }, search_apple_docs: async (args, server) => { const validatedArgs = searchAppleDocsSchema.parse(args); return await server.searchAppleDocs(validatedArgs.query, validatedArgs.type); }, get_apple_doc_content: async (args, server) => { const validatedArgs = getAppleDocContentSchema.parse(args); return await server.getAppleDocContent(validatedArgs.url, validatedArgs.includeRelatedApis, validatedArgs.includeReferences, validatedArgs.includeSimilarApis, validatedArgs.includePlatformAnalysis); }, list_technologies: async (args, server) => { const validatedArgs = listTechnologiesSchema.parse(args); return await server.listTechnologies(validatedArgs.category, validatedArgs.language, validatedArgs.includeBeta, validatedArgs.limit); }, search_framework_symbols: async (args, server) => { const validatedArgs = searchFrameworkSymbolsSchema.parse(args); return await server.searchFrameworkSymbols(validatedArgs.framework, validatedArgs.symbolType, validatedArgs.namePattern, validatedArgs.language, validatedArgs.limit); }, get_related_apis: async (args, server) => { const validatedArgs = getRelatedApisSchema.parse(args); return await server.getRelatedApis(validatedArgs.apiUrl, validatedArgs.includeInherited, validatedArgs.includeConformance, validatedArgs.includeSeeAlso); }, resolve_references_batch: async (args, server) => { const validatedArgs = resolveReferencesBatchSchema.parse(args); return await server.resolveReferencesBatch(validatedArgs.sourceUrl, validatedArgs.maxReferences, validatedArgs.filterByType); }, get_platform_compatibility: async (args, server) => { const validatedArgs = getPlatformCompatibilitySchema.parse(args); return await server.getPlatformCompatibility(validatedArgs.apiUrl, validatedArgs.compareMode, validatedArgs.includeRelated); }, find_similar_apis: async (args, server) => { const validatedArgs = findSimilarApisSchema.parse(args); return await server.findSimilarApis(validatedArgs.apiUrl, validatedArgs.searchDepth, validatedArgs.filterByCategory, validatedArgs.includeAlternatives); }, get_documentation_updates: async (args, server) => { const validatedArgs = getDocumentationUpdatesSchema.parse(args); return await server.getDocumentationUpdates(validatedArgs.category, validatedArgs.technology, validatedArgs.year, validatedArgs.searchQuery, validatedArgs.includeBeta, validatedArgs.limit); }, get_technology_overviews: async (args, server) => { const validatedArgs = getTechnologyOverviewsSchema.parse(args); return await server.getTechnologyOverviews(validatedArgs.category, validatedArgs.platform, validatedArgs.searchQuery, validatedArgs.includeSubcategories, validatedArgs.limit); }, get_sample_code: async (args, server) => { const validatedArgs = getSampleCodeSchema.parse(args); return await server.getSampleCode(validatedArgs.framework, validatedArgs.beta, validatedArgs.searchQuery, validatedArgs.limit); }, // WWDC tools list_wwdc_videos: async (args, _server) => { const validatedArgs = listWWDCVideosSchema.parse(args); const result = await handleListWWDCVideos(validatedArgs.year, validatedArgs.topic, validatedArgs.hasCode, validatedArgs.limit); return { content: [{ type: 'text', text: result }] }; }, search_wwdc_content: async (args, _server) => { const validatedArgs = searchWWDCContentSchema.parse(args); const result = await handleSearchWWDCContent(validatedArgs.query, validatedArgs.searchIn, validatedArgs.year, validatedArgs.language, validatedArgs.limit); return { content: [{ type: 'text', text: result }] }; }, get_wwdc_video: async (args, _server) => { const validatedArgs = getWWDCVideoSchema.parse(args); const result = await handleGetWWDCVideo(validatedArgs.year, validatedArgs.videoId, validatedArgs.includeTranscript, validatedArgs.includeCode); return { content: [{ type: 'text', text: result }] }; }, get_wwdc_code_examples: async (args, _server) => { const validatedArgs = getWWDCCodeExamplesSchema.parse(args); const result = await handleGetWWDCCodeExamples(validatedArgs.framework, validatedArgs.topic, validatedArgs.year, validatedArgs.language, validatedArgs.limit); return { content: [{ type: 'text', text: result }] }; }, browse_wwdc_topics: async (args, _server) => { const validatedArgs = browseWWDCTopicsSchema.parse(args); const result = await handleBrowseWWDCTopics(validatedArgs.topicId, validatedArgs.includeVideos, validatedArgs.year, validatedArgs.limit); return { content: [{ type: 'text', text: result }] }; }, find_related_wwdc_videos: async (args, _server) => { const validatedArgs = findRelatedWWDCVideosSchema.parse(args); const result = await handleFindRelatedWWDCVideos(validatedArgs.videoId, validatedArgs.year, validatedArgs.includeExplicitRelated, validatedArgs.includeTopicRelated, validatedArgs.includeYearRelated, validatedArgs.limit); return { content: [{ type: 'text', text: result }] }; }, }; /** * Handle tool call with the appropriate handler */ export async function handleToolCall(toolName, args, server) { try { const handler = toolHandlers[toolName]; if (!handler) { throw new Error(`Unknown tool: ${toolName}`); } return await handler(args, server); } catch (error) { // Return error response for validation errors and unknown tools return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } //# sourceMappingURL=handlers.js.map