Skip to main content
Glama
djalal

quran-mcp-server

by djalal

list-chapters

Retrieve Quran chapters in a specified language using the 'list-chapters' tool from the quran-mcp-server. Simplify Quran navigation by accessing chapter details in your preferred language.

Instructions

List Chapters

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
languageYesParameter language (e.g., 'en', 'ar', 'fr-CA')

Implementation Reference

  • MCP tool handler for 'list-chapters': validates input args using Zod schema, delegates to chaptersService.listChapters, formats JSON response as text content, handles errors with verbose logging.
    export async function handleListChapters(args: any) {
      try {
        // Validate arguments
        const validatedArgs = listChaptersSchema.parse(args);
        
        // Call the service
        const result = await chaptersService.listChapters(validatedArgs);
        
        // Log the response in verbose mode
        verboseLog('response', {
          tool: 'list-chapters',
          result
        });
        
        return {
          content: [
            {
              type: "text",
              text: JSON.stringify(result, null, 2)
            }
          ]
        };
      } catch (error) {
        verboseLog('error', {
          tool: 'list-chapters',
          error: error instanceof Error ? error.message : String(error)
        });
        
        if (error instanceof z.ZodError) {
          return {
            content: [{ 
              type: "text", 
              text: `Validation error: ${error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`
            }],
            isError: true,
          };
        }
        
        return {
          content: [{ 
            type: "text", 
            text: `Error: ${error instanceof Error ? error.message : "Unknown error"}`
          }],
          isError: true,
        };
      }
    }
  • Zod input validation schema for 'list-chapters' tool defining the required 'language' parameter with constraints and description.
    export const listChaptersSchema = z.object({
      language: z.string()
        .trim()
        .min(2, "Language code must be at least 2 characters")
        .max(10, "Language code must not exceed 10 characters")
        .regex(/^[a-zA-Z-]+$/, "Language code must contain only letters and hyphens")
        .describe("Parameter language (e.g., 'en', 'ar', 'fr-CA')"),
    });
  • src/server.ts:124-128 (registration)
    Registration of 'list-chapters' tool in the MCP server's listTools handler: specifies name, description, input schema (converted from Zod), and usage examples.
      name: ApiTools.list_chapters,
      description: "List Chapters",
      inputSchema: zodToJsonSchema(chaptersSchemas.listChapters),
      examples: toolExamples['list-chapters'],
    },
  • src/server.ts:257-258 (registration)
    Dispatch registration in MCP server's callTool handler: routes 'list-chapters' tool calls to the handleListChapters function.
    case ApiTools.list_chapters:
      return await handleListChapters(request.params.arguments);
  • Helper service method implementing core 'list-chapters' logic: parameter validation, caching, API call to Quran.com /chapters endpoint, data reduction, verbose logging, fallback to mock data on API failure or errors.
    async listChapters(params: z.infer<typeof listChaptersSchema>): Promise<ListChaptersResponse> {
      try {
        // Validate parameters
        const validatedParams = listChaptersSchema.parse(params);
        
        // Generate cache key based on parameters
        const cacheKey = `chapters_${validatedParams.language || 'en'}`;
        
        // Check cache first
        const cachedData = this.chaptersCache.get(cacheKey);
        if (cachedData) {
          verboseLog('response', {
            method: 'listChapters',
            source: 'cache',
            cacheSize: this.chaptersCache.size()
          });
          
          return {
            success: true,
            message: "list-chapters executed successfully (from cache)",
            data: cachedData
          };
        }
        
        try {
          // Make request to Quran.com API
          const url = `${API_BASE_URL}/chapters`;
          const response = await makeApiRequest(url, {
            language: validatedParams.language
          });
          
          // Process and reduce the data to only essential fields
          const reducedData = {
            chapters: response.chapters.map((chapter: any) => ({
              id: chapter.id,
              name_arabic: chapter.name_arabic,
              name_simple: chapter.name_simple,
              translated_name: { 
                name: chapter.translated_name?.name || "" 
              }
              // Only include essential fields
            }))
          };
          
          verboseLog('response', {
            method: 'listChapters',
            source: 'api',
            dataSize: JSON.stringify(reducedData).length
          });
          
          // Update cache with the new data
          this.chaptersCache.set(cacheKey, reducedData);
          
          return {
            success: true,
            message: "list-chapters executed successfully",
            data: reducedData
          };
        } catch (axiosError) {
          verboseLog('error', {
            method: 'listChapters',
            error: axiosError instanceof Error ? axiosError.message : String(axiosError)
          });
          
          // If the API call fails, return mock data
          verboseLog('response', {
            method: 'listChapters',
            source: 'mock',
            reason: 'API unavailable'
          });
          
          const mockData = this.getChaptersMockData();
          
          return {
            success: true,
            message: "list-chapters executed with mock data (API unavailable)",
            data: mockData
          };
        }
      } catch (error) {
        verboseLog('error', {
          method: 'listChapters',
          error: error instanceof Error ? error.message : String(error)
        });
        
        if (error instanceof z.ZodError) {
          throw new ApiError(`Validation error: ${error.errors.map(e => `${e.path.join('.')}: ${e.message}`).join(', ')}`, 400);
        }
        
        // Return mock data as a fallback for any error
        verboseLog('response', {
          method: 'listChapters',
          source: 'mock',
          reason: 'error occurred'
        });
        
        const mockData = this.getChaptersMockData();
        
        return {
          success: true,
          message: "list-chapters executed with mock data (error occurred)",
          data: mockData
        };
      }
    }
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure but provides none. 'List Chapters' doesn't indicate whether this is a read-only operation, whether it requires authentication, whether it's paginated, what format the output takes, or any rate limits. For a tool with no annotation coverage, this complete lack of behavioral information is inadequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

While technically concise with just two words, this represents under-specification rather than effective conciseness. The description doesn't front-load important information or provide any structure - it's simply the tool name repeated. Every sentence should earn its place, but here there's essentially no sentence to evaluate for value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of having many sibling tools, no annotations, and no output schema, the description is completely inadequate. It doesn't explain what the tool returns, how to interpret results, or how it differs from similar tools. For a listing operation in a domain with multiple related tools, this minimal description fails to provide the necessary context for an agent to use it effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, with the single parameter 'language' well-documented in the schema itself. The description adds no parameter information beyond what the schema provides. According to the scoring rules, when schema_description_coverage is high (>80%), the baseline is 3 even with no param info in the description, which applies here.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'List Chapters' is a tautology that essentially restates the tool name without providing meaningful context. It doesn't specify what resource is being listed (e.g., Quran chapters, book chapters) or what the scope of the listing includes. While the name implies chapters of something, the description fails to add any clarifying information beyond the name itself.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides absolutely no guidance on when to use this tool versus the many sibling tools available. There's no mention of alternatives like 'GET-chapter' (which might retrieve a single chapter) or 'verses-by_chapter_number' (which might get verses within a chapter). The agent receives no help in determining when this list operation is appropriate versus other listing or retrieval operations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

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