jp_lit_search_kokusho_fulltext
Search Japanese book database transcription and OCR snippets by keyword. Retrieve bid, frame number, snippet, and official URL without fetching full texts or images.
Instructions
国書データベースの翻刻/OCR系スニペッ���をキーワード検索する。本文全体・manifest 本体・画像本体は取得せず、bid、コマ番号、スニペット、公式確認 URL を返す。国書DB Web アプリの公開 JSON endpoint に依存するため、採用時は公式画面で最終確認する
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | Yes | ||
| limit | No | ||
| page | No | ||
| force_refresh | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| keyword | Yes | ||
| page | Yes | ||
| limit | Yes | ||
| total | Yes | ||
| items | Yes | ||
| raw | Yes | ||
| cache | No |
Implementation Reference
- Main handler function `createJpLitSearchKokushoFulltextTool`. Parses input using searchKokushoFulltextInputSchema, calls `client.searchFulltext(parsed.keyword)` to fetch from the Kokusho API, maps the response with `mapKokushoFulltextResponse`, caches via `runCachedTool`, and returns structured JSON content with cache info.
export function createJpLitSearchKokushoFulltextTool( client: KokushoClient, cache: FileCache = createFileCache(), sessions: SessionStore = createSessionStore() ) { return async (input: unknown) => { const parsed = searchKokushoFulltextInputSchema.parse(input); const { force_refresh, ...cacheableInput } = parsed; const result = await runCachedTool<SearchKokushoFulltextOutput>({ tool: "jp_lit_search_kokusho_fulltext", input: cacheableInput, cache, sessions, bypassCache: force_refresh, live: async () => { try { const payload = await client.searchFulltext(parsed.keyword); const mapped = mapKokushoFulltextResponse(payload, parsed.page, parsed.limit); if (!mapped) { throw new NotFoundError("国書DB全文検索結果が取得できませんでした"); } return searchKokushoFulltextOutputSchema.parse({ keyword: parsed.keyword, page: parsed.page, limit: parsed.limit, total: mapped.total, items: mapped.items, raw: mapped.raw }); } catch (error) { if (error instanceof NotFoundError) { throw error; } throw networkRestrictionError(error); } } }); const structuredContent = addCacheInfo(result.structuredContent, result); return { content: [{ type: "text" as const, text: JSON.stringify(structuredContent, null, 2) }], structuredContent }; }; } - Helper `mapKokushoFulltextResponse` transforms the raw Kokusho API response into structured items with bid, title, authors, koma, line, snippet, viewer_url, source_metadata. Handles pagination via page/limit offset.
export function mapKokushoFulltextResponse(payload: unknown, page: number, limit: number) { if (!Array.isArray(payload)) { return null; } const offset = (page - 1) * limit; const selected = payload.slice(offset, offset + limit); const items = selected.map((item) => { const record = item as Record<string, unknown>; const bid = readString(record.bid) ?? "missing-kokusho-id"; const koma = readNumber(record.koma); const line = readNumber(record.line); const context = readString(record.context); return { bid, source_id: bid, title: readString(record.title), work_title: readString(record.wname), authors: readStringArray(record.authorlist).map((name) => ({ name, role: "author" })), koma, line, snippet: context ? snippetText(context) : null, viewer_url: buildViewerUrl(bid, koma), biblio_url: buildBiblioUrl(bid), source_metadata: { satsu: record.satsu ?? null, line, totalkoma: record.totalkoma ?? null, kansha: record.kansha ?? null, shubetsu: record.shubetsu ?? null, wkeyword: record.wkeyword ?? null, authorhead: record.authorhead ?? null } }; }); return { total: payload.length, items, raw: { endpoint: "fulltextSearch", upstream_total: payload.length, returned_count: items.length } }; } - src/sources/kokusho/client.ts:32-45 (helper)KokushoClient method `searchFulltext(keyword)` calls the Kokusho API endpoint `/api/fulltextSearch?keyword=...` and returns the raw JSON payload.
async searchFulltext(keyword) { const url = new URL(withBase(baseUrl, "/api/fulltextSearch")); url.searchParams.set("keyword", keyword); return fetchJson<unknown>(url.toString()); }, async searchImageTags(keyword, page) { const url = new URL(withBase(baseUrl, "/api/tagSearch")); url.searchParams.set("searchkbn", "simple"); url.searchParams.set("keyword", keyword); url.searchParams.set("page", String(page)); return fetchJson<unknown>(url.toString()); } }; }