Skip to main content
Glama
ukicar

Gallica/BnF MCP Server

by ukicar

natural_language_search

Search the Gallica digital library using natural language queries to find documents across all fields including titles, authors, subjects, and dates.

Instructions

Search the Gallica digital library using natural language. This is a simplified search that uses the "gallica all" operator to search across all fields.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesNatural language search query
max_resultsNoMaximum number of results to return (1-50)
start_recordNoStarting record for pagination

Implementation Reference

  • Main tool handler - createNaturalLanguageSearchTool function defines the 'natural_language_search' MCP tool with its name, description, inputSchema, and async handler that calls searchApi.naturalLanguageSearch().
    export function createNaturalLanguageSearchTool(searchApi: SearchAPI) {
      return {
        name: 'natural_language_search',
        description: 'Search the Gallica digital library using natural language. This is a simplified search that uses the "gallica all" operator to search across all fields.',
        inputSchema: {
          type: 'object',
          properties: {
            query: {
              type: 'string',
              description: 'Natural language search query',
            },
            max_results: {
              type: 'number',
              description: 'Maximum number of results to return (1-50)',
              default: config.defaultMaxRecords,
            },
            start_record: {
              type: 'number',
              description: 'Starting record for pagination',
              default: config.defaultStartRecord,
            },
          },
          required: ['query'],
        },
        handler: async (args: unknown) => {
          const parsed = searchParamsSchema.extend({ query: z.string() }).parse(args);
          return await searchApi.naturalLanguageSearch(
            parsed.query,
            parsed.max_results ?? config.defaultMaxRecords,
            parsed.start_record ?? config.defaultStartRecord
          );
        },
      };
  • Core search logic - naturalLanguageSearch method formats the query as 'gallica all "{query}"' and delegates to the base search method.
    naturalLanguageSearch(
      query: string,
      maxResults: number = config.defaultMaxRecords,
      startRecord: number = config.defaultStartRecord
    ): Promise<SearchResult> {
      const formattedQuery = `gallica all "${query}"`;
      return this.search(formattedQuery, startRecord, maxResults);
    }
  • Zod schema definition for search parameters (max_results and start_record) used for input validation in the handler.
    const searchParamsSchema = z.object({
      max_results: z.number().int().positive().max(50).optional(),
      start_record: z.number().int().positive().optional(),
    });
  • Tool registration - creates the naturalLanguageSearch tool instance and adds it to the tools array that is registered with the MCP server.
    const naturalLanguageSearch = createNaturalLanguageSearchTool(searchApi);
    
    // Register extended item tools (4 new tools)
    const getItemDetails = createGetItemDetailsTool(itemsClient);
    const getItemPages = createGetItemPagesTool(itemsClient);
    const getPageImage = createGetPageImageTool(iiifClient);
    const getPageText = createGetPageTextTool(textClient);
    
    // Register sequential reporting tool
    const sequentialReporting = createSequentialReportingTool(reportingServer);
    
    // Register all tools with error handling
    const tools = [
      searchByTitle,
      searchByAuthor,
      searchBySubject,
      searchByDate,
      searchByDocumentType,
      advancedSearch,
      naturalLanguageSearch,
      getItemDetails,
      getItemPages,
      getPageImage,
      getPageText,
      sequentialReporting,
    ];
  • CallTool handler registration - handles incoming tool call requests, finds the tool by name (e.g., 'natural_language_search'), and executes its handler.
    server.setRequestHandler(
      CallToolRequestSchema,
      async (request) => {
        logger.info(`[TOOL] Tool call requested: ${request.params.name}`);
        logger.info(`[TOOL] Tool arguments: ${JSON.stringify(request.params.arguments, null, 2)}`);
        
        const tool = tools.find((t) => t.name === request.params.name);
        if (!tool) {
          logger.error(`[TOOL] Tool not found: ${request.params.name || 'unknown'}`);
          logger.info(`[TOOL] Available tools: ${tools.map(t => t.name).join(', ')}`);
          throw new Error(`Tool not found: ${request.params.name || 'unknown'}`);
        }
    
        try {
          logger.info(`[TOOL] Executing tool: ${tool.name}`);
          logger.debug(`[TOOL] Tool handler called with arguments:`, request.params.arguments);
          const result = await tool.handler(request.params.arguments);
          logger.info(`[TOOL] Tool ${tool.name} completed successfully`);
          const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
          logger.debug(`[TOOL] Tool result type: ${typeof result}, length: ${resultStr.length}`);
          
          const response = {
            content: [
              {
Behavior3/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. It adds some context: it describes the search as 'simplified' and mentions the 'gallica all' operator, which gives insight into how the search works. However, it doesn't cover important behavioral aspects like rate limits, authentication needs, error handling, or what the results look like (since there's no output schema). The description provides basic operational context but lacks depth for a tool with no annotations.

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

Conciseness4/5

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

The description is concise and front-loaded, with two sentences that directly state the tool's purpose and key operational detail. There's no wasted text, and it efficiently conveys the essential information. It could be slightly improved by structuring it more explicitly (e.g., separating purpose from constraints), but it's well-sized and clear.

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

Completeness3/5

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

Given the tool's moderate complexity (a search function with 3 parameters), lack of annotations, and no output schema, the description is minimally adequate. It covers the basic purpose and method but lacks details on behavioral traits, result format, or explicit differentiation from siblings. For a search tool in a context with many sibling tools, more completeness would be helpful to guide the agent effectively, but it meets the minimum viable threshold.

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 input schema has 100% description coverage, with clear documentation for all three parameters (query, max_results, start_record). The description doesn't add any parameter-specific information beyond what's in the schema, such as examples of natural language queries or details on pagination behavior. Given the high schema coverage, the baseline score of 3 is appropriate, as the description doesn't compensate but also doesn't need to since the schema is comprehensive.

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

Purpose4/5

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

The description clearly states the tool's purpose: 'Search the Gallica digital library using natural language.' It specifies the verb ('search'), resource ('Gallica digital library'), and method ('natural language'). However, it doesn't explicitly distinguish this from sibling tools like 'advanced_search' or 'search_by_title' beyond mentioning it's 'simplified' and uses a specific operator, leaving some ambiguity about when to choose this over other search tools.

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

Usage Guidelines3/5

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

The description provides some usage context by stating this is a 'simplified search' and uses the 'gallica all' operator to search across all fields, which implies it's a broad, general-purpose search. However, it doesn't explicitly state when to use this tool versus alternatives like 'advanced_search' or field-specific searches (e.g., 'search_by_title'), nor does it mention any exclusions or prerequisites. The guidance is implied but not comprehensive.

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

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/ukicar/sweet-bnf'

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