Skip to main content
Glama

quran-mcp-server

by djalal
server.ts10.8 kB
#!/usr/bin/env node /** * Quran.com API MCP Server * * This server provides tools for interacting with the Quran.com API. * * @version 1.0.0 */ const { Server } = require('@modelcontextprotocol/sdk/server/index.js'); const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js'); const { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, RequestSchema, } = require('@modelcontextprotocol/sdk/types.js'); const { zodToJsonSchema } = require('zod-to-json-schema'); const { z } = require('zod'); // Import configuration const { VERBOSE_MODE } = require('./config'); // Import tools const { ApiTools } = require('./tools'); // Import schemas const { chaptersSchemas, versesSchemas, juzsSchemas, searchSchemas, translationsSchemas, tafsirsSchemas, audioSchemas, languagesSchemas, } = require('./schemas'); // Import handlers const { handleListChapters, handleGetChapter, handleChapterInfo, handleVersesByChapterNumber, handleVersesByPageNumber, handleVersesByJuzNumber, handleVersesByHizbNumber, handleVersesByRubElHizbNumber, handleVersesByVerseKey, handleRandomVerse, handleSearch, handleJuzs, handleTranslations, handleTranslationInfo, handleTafsirs, handleTafsirInfo, handleTafsir, handleChapterReciters, handleRecitationStyles, handleLanguages, } = require('./handlers'); // Import utilities const { verboseLog } = require('./utils/logger'); const { createErrorResponse } = require('./utils/error-handler'); // Import examples const { toolExamples } = require('./examples'); // Define custom request schemas for prompts methods using Zod const PromptsListRequestSchema = z.object({ method: z.literal('prompts/list'), params: z.object({}).optional() }); const PromptsGetRequestSchema = z.object({ method: z.literal('prompts/get'), params: z.object({ id: z.string() }) }); // Server configuration const server = new Server( { name: "Quran.com API", version: "1.0.0", }, { capabilities: { tools: {}, resources: {}, prompts: {}, // Add support for prompts }, }, ); /** * Handle prompts/list method */ server.setRequestHandler(PromptsListRequestSchema, async (request: any) => { console.error("Handling prompts/list request"); return { prompts: [] // Return an empty array of prompts }; }); /** * Handle prompts/get method */ server.setRequestHandler(PromptsGetRequestSchema, async (request: any) => { console.error("Handling prompts/get request for id:", request.params.id); // Since we don't have any prompts, we'll return a not found error throw new McpError(ErrorCode.NotFound, `Prompt with id ${request.params.id} not found`); }); /** * List available tools */ server.setRequestHandler(ListToolsRequestSchema, async (request: any) => ({ tools: [ { name: ApiTools.list_chapters, description: "List Chapters", inputSchema: zodToJsonSchema(chaptersSchemas.listChapters), examples: toolExamples['list-chapters'], }, { name: ApiTools.GET_chapter, description: "Get Chapter", inputSchema: zodToJsonSchema(chaptersSchemas.getChapter), examples: toolExamples['GET-chapter'], }, { name: ApiTools.info, description: "Get Chapter Info", inputSchema: zodToJsonSchema(chaptersSchemas.chapterInfo), }, { name: ApiTools.verses_by_chapter_number, description: "Get verses by Chapter / Surah number", inputSchema: zodToJsonSchema(versesSchemas.versesByChapterNumber), examples: toolExamples['verses-by_chapter_number'], }, { name: ApiTools.verses_by_page_number, description: "Get all verses of a specific Madani Mushaf page", inputSchema: zodToJsonSchema(versesSchemas.versesByPageNumber), }, { name: ApiTools.verses_by_juz_number, description: "Get verses by Juz number", inputSchema: zodToJsonSchema(versesSchemas.versesByJuzNumber), }, { name: ApiTools.verses_by_hizb_number, description: "Get verses by Hizb number", inputSchema: zodToJsonSchema(versesSchemas.versesByHizbNumber), }, { name: ApiTools.verses_by_rub_el_hizb_number, description: "Get verses by Rub el Hizb number", inputSchema: zodToJsonSchema(versesSchemas.versesByRubElHizbNumber), }, { name: ApiTools.verses_by_verse_key, description: "Get verse by key", inputSchema: zodToJsonSchema(versesSchemas.versesByVerseKey), examples: toolExamples['verses-by_verse_key'], }, { name: ApiTools.random_verse, description: "Get a random verse", inputSchema: zodToJsonSchema(versesSchemas.randomVerse), examples: toolExamples['random_verse'], }, { name: ApiTools.juzs, description: "Get list of all juzs", inputSchema: zodToJsonSchema(juzsSchemas.juzs), examples: toolExamples['juzs'], }, { name: ApiTools.search, description: "Search the Quran for specific terms", inputSchema: zodToJsonSchema(searchSchemas.search), examples: toolExamples['search'], }, // Translation-related tools { name: ApiTools.translations, description: "Get list of available translations", inputSchema: zodToJsonSchema(translationsSchemas.translations), examples: toolExamples['translations'], }, { name: ApiTools.translation_info, description: "Get information of a specific translation", inputSchema: zodToJsonSchema(translationsSchemas.translationInfo), }, // Tafsir-related tools { name: ApiTools.tafsirs, description: "Get list of available tafsirs", inputSchema: zodToJsonSchema(tafsirsSchemas.tafsirs), examples: toolExamples['tafsirs'], }, { name: ApiTools.tafsir_info, description: "Get the information of a specific tafsir", inputSchema: zodToJsonSchema(tafsirsSchemas.tafsirInfo), }, { name: ApiTools.tafsir, description: "Get a single tafsir", inputSchema: zodToJsonSchema(tafsirsSchemas.tafsir), }, // Audio-related tools { name: ApiTools.chapter_reciters, description: "List of Chapter Reciters", inputSchema: zodToJsonSchema(audioSchemas.chapterReciters), }, { name: ApiTools.recitation_styles, description: "Get the available recitation styles", inputSchema: zodToJsonSchema(audioSchemas.recitationStyles), }, // Language-related tools { name: ApiTools.languages, description: "Get all languages", inputSchema: zodToJsonSchema(languagesSchemas.languages), examples: toolExamples['languages'], }, ], })); /** * Handle tool calls */ server.setRequestHandler(CallToolRequestSchema, async (request: any) => { try { if (!request.params.arguments) { throw new McpError(ErrorCode.InvalidParams, "Arguments are required"); } // Log the incoming request in verbose mode verboseLog('request', { tool: request.params.name, arguments: request.params.arguments }); switch (request.params.name) { // Chapter-related tools case ApiTools.list_chapters: return await handleListChapters(request.params.arguments); case ApiTools.GET_chapter: return await handleGetChapter(request.params.arguments); case ApiTools.info: return await handleChapterInfo(request.params.arguments); // Verse-related tools case ApiTools.verses_by_chapter_number: return await handleVersesByChapterNumber(request.params.arguments); case ApiTools.verses_by_page_number: return await handleVersesByPageNumber(request.params.arguments); case ApiTools.verses_by_juz_number: return await handleVersesByJuzNumber(request.params.arguments); case ApiTools.verses_by_hizb_number: return await handleVersesByHizbNumber(request.params.arguments); case ApiTools.verses_by_rub_el_hizb_number: return await handleVersesByRubElHizbNumber(request.params.arguments); case ApiTools.verses_by_verse_key: return await handleVersesByVerseKey(request.params.arguments); case ApiTools.random_verse: return await handleRandomVerse(request.params.arguments); // Juzs-related tools case ApiTools.juzs: return await handleJuzs(request.params.arguments); // Search-related tools case ApiTools.search: return await handleSearch(request.params.arguments); // Translation-related tools case ApiTools.translations: return await handleTranslations(request.params.arguments); case ApiTools.translation_info: return await handleTranslationInfo(request.params.arguments); // Tafsir-related tools case ApiTools.tafsirs: return await handleTafsirs(request.params.arguments); case ApiTools.tafsir_info: return await handleTafsirInfo(request.params.arguments); case ApiTools.tafsir: return await handleTafsir(request.params.arguments); // Audio-related tools case ApiTools.chapter_reciters: return await handleChapterReciters(request.params.arguments); case ApiTools.recitation_styles: return await handleRecitationStyles(request.params.arguments); // Language-related tools case ApiTools.languages: return await handleLanguages(request.params.arguments); default: throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`); } } catch (error) { console.error("Error processing request:", error); if (error instanceof McpError) { throw error; // Let the MCP SDK handle MCP-specific errors } // Use the error handler utility to create a standardized error response // This logs detailed error info but returns a generic message to clients return createErrorResponse(error, request.params.name); } }); /** * Start the server */ async function runServer() { try { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Quran.com API MCP Server running on stdio"); } catch (error) { console.error("Fatal error starting server:", error); process.exit(1); } } // Handle uncaught exceptions process.on('uncaughtException', (error) => { console.error('Uncaught exception:', error); process.exit(1); }); // Handle unhandled promise rejections process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled promise rejection:', reason); process.exit(1); }); // Run the server runServer().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/djalal/quran-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server