Skip to main content
Glama

jp_lit_search_illustrations

Search for illustrations and pictures in NDL Digital Collection using text keywords. Retrieve IIIF image URLs for full pages and cropped illustrations.

Instructions

NDL デジタルコレクション全資料の図版・挿絵をテキストキーワードで検索する(公開範囲のみ)。結果には IIIF 画像 URL(ページ全体・図版トリミング)を含む

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
keywordYes
sizeNo
fromNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
keywordYes
totalYes
fromYes
itemsYes
rawYes

Implementation Reference

  • Main handler function that creates the jp_lit_search_illustrations tool. Accepts keyword, size, from parameters; delegates to NextDigitalLibraryClient.searchIllustrations; maps results to include IIIF image URLs (page and region); outputs structured content with items, total, from.
    export function createJpLitSearchIllustrationsTool(
      nextDlClient: NextDigitalLibraryClient,
      cache: FileCache = createFileCache(),
      sessions: SessionStore = createSessionStore()
    ) {
      return async (input: unknown) => {
        const parsed = searchIllustrationsInputSchema.parse(input);
    
        const { structuredContent } = await runCachedTool<SearchIllustrationsOutput>({
          tool: "jp_lit_search_illustrations",
          input: parsed as Record<string, unknown>,
          cache,
          sessions,
          live: async () => {
            const result = await nextDlClient.searchIllustrations(parsed.keyword, {
              size: parsed.size,
              from: parsed.from
            });
    
            if (!result) {
              throw new NotFoundError("検索結果が取得できませんでした");
            }
    
            const rawList = Array.isArray(result.list) ? result.list : [];
            const items = rawList.map((item: unknown) => {
              const r = item as Record<string, unknown>;
              const pid = String(r["pid"] ?? "");
              const page = Number(r["page"] ?? 0);
              const x = Number(r["x"] ?? 0);
              const y = Number(r["y"] ?? 0);
              const w = Number(r["w"] ?? 0);
              const h = Number(r["h"] ?? 0);
              const rawTags = Array.isArray(r["graphictags"]) ? r["graphictags"] : [];
              const graphictags = rawTags.map((t: unknown) => {
                const tag = t as Record<string, unknown>;
                return {
                  tagname: String(tag["tagname"] ?? ""),
                  confidence: Number(tag["confidence"] ?? 0)
                };
              });
    
              return {
                id: String(r["id"] ?? ""),
                pid,
                viewer_url: `https://dl.ndl.go.jp/pid/${pid}`,
                page,
                x,
                y,
                w,
                h,
                graphictags,
                page_image_url: buildIiifPageUrl(pid, page),
                illustration_image_url: buildIiifRegionUrl(pid, page, x, y, w, h)
              };
            });
    
            const total = (result.hit ?? result.total ?? 0) as number;
    
            return searchIllustrationsOutputSchema.parse({
              keyword: parsed.keyword,
              total,
              from: parsed.from,
              items,
              raw: result
            });
          }
        });
    
        return {
          content: [{ type: "text" as const, text: JSON.stringify(structuredContent, null, 2) }],
          structuredContent
        };
      };
    }
  • Input schema for the tool: keyword (required), size (default 20, max 100), from (default 0).
    export const searchIllustrationsInputSchema = z.object({
      keyword: z.string().trim().min(1),
      size: z.number().int().positive().max(100).default(20),
      from: z.number().int().nonnegative().default(0)
    });
  • Output schema with keyword, total, from, items (array of illustrationItemSchema), raw results.
    export const searchIllustrationsOutputSchema = z.object({
      keyword: z.string(),
      total: z.number().int().nonnegative(),
      from: z.number().int().nonnegative(),
      items: z.array(illustrationItemSchema),
      raw: z.record(z.unknown())
    });
  • Schema for each illustration item including pid, page coordinates, IIF image URLs, and graphic tags with confidence scores.
    const illustrationItemSchema = z.object({
      id: z.string(),
      pid: z.string(),
      viewer_url: z.string(),
      page: z.number().int().positive(),
      x: z.number(),
      y: z.number(),
      w: z.number(),
      h: z.number(),
      graphictags: z.array(z.object({
        tagname: z.string(),
        confidence: z.number()
      })),
      page_image_url: z.string(),
      illustration_image_url: z.string()
    });
  • src/server.ts:547-555 (registration)
    Registration of the tool with the MCP server under the name 'jp_lit_search_illustrations'.
    server.registerTool(
      "jp_lit_search_illustrations",
      {
        description: "NDL デジタルコレクション全資料の図版・挿絵をテキストキーワードで検索する(公開範囲のみ)。結果には IIIF 画像 URL(ページ全体・図版トリミング)を含む",
        inputSchema: searchIllustrationsInputSchema,
        outputSchema: searchIllustrationsOutputSchema
      },
      searchIllustrationsTool
    );
Behavior4/5

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

With no annotations, the description adds key behavioral cues: 'public domain only' and inclusion of IIIF image URLs. However, it does not cover rate limits, authentication, or other potential behaviors.

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

Conciseness5/5

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

Single sentence, front-loaded with key information, no wasted words.

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?

Output schema exists but not shown; description mentions IIIF URLs. However, parameter details are lacking, and no guidance on how output relates to input parameters.

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

Parameters2/5

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

The description only mentions 'text keyword' corresponding to the keyword parameter, leaving size and from unexplained. With 0% schema coverage, additional parameter guidance would be helpful.

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

Purpose5/5

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

The description clearly states it searches for illustrations in NDL Digital Collection by keyword, specifying public domain only. It effectively distinguishes from sibling tools like jp_lit_search and jp_lit_search_pages.

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 implies use for illustration searches but does not explicitly state when to use this tool versus alternatives or provide exclusion criteria.

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/itarunnn/jp-lit-mcp'

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