jp_lit_search_kaken_projects
Search KAKEN-funded projects to retrieve research themes, keywords, report PDFs, and output lists for Japanese academic research.
Instructions
KAKEN から研究課題を検索し、研究テーマ・キーワード・報告書 PDF・成果リストの手がかりを返す補助 tool。論文・図書の文献確定は CiNii / J-STAGE / IRDB / NDL で再確認する
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| limit | No | ||
| page | No | ||
| detail_limit | No | ||
| researcher_name | No | ||
| from_fiscal_year | No | ||
| to_fiscal_year | No | ||
| include_outputs | No | ||
| force_refresh | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| page | Yes | ||
| limit | Yes | ||
| total | Yes | ||
| items | Yes | ||
| cache | No |
Implementation Reference
- The main handler function createJpLitSearchKakenProjectsTool that executes the tool logic. It parses input using searchKakenProjectsInputSchema, delegates to the KakenClient via runCachedTool, validates output with searchKakenProjectsOutputSchema, and returns structured content.
import { createFileCache } from "../lib/persistence/fileCache.js"; import type { FileCache } from "../lib/persistence/fileCache.js"; import { runCachedTool } from "../lib/persistence/runCachedTool.js"; import { createSessionStore } from "../lib/persistence/sessionStore.js"; import type { SessionStore } from "../lib/persistence/sessionStore.js"; import { withToolCache } from "../lib/toolCache.js"; import { searchKakenProjectsInputSchema, searchKakenProjectsOutputSchema } from "../lib/schemas.js"; import type { SearchKakenProjectsOutput } from "../lib/schemas.js"; import type { KakenClient } from "../sources/kaken/client.js"; export function createJpLitSearchKakenProjectsTool( client: KakenClient, cache: FileCache = createFileCache(), sessions: SessionStore = createSessionStore() ) { return async (input: unknown) => { const parsed = searchKakenProjectsInputSchema.parse(input); const { force_refresh, ...cacheableInput } = parsed; const result = await runCachedTool<SearchKakenProjectsOutput>({ tool: "jp_lit_search_kaken_projects", input: cacheableInput as Record<string, unknown>, cache, sessions, bypassCache: force_refresh, live: async () => searchKakenProjectsOutputSchema.parse(await client.searchProjects(cacheableInput)) }); const structuredContent = searchKakenProjectsOutputSchema.parse( withToolCache(result.structuredContent as Record<string, unknown>, result) ); return { content: [{ type: "text" as const, text: JSON.stringify(structuredContent, null, 2) }], structuredContent }; }; } - src/lib/schemas.ts:1111-1121 (schema)Input schema (searchKakenProjectsInputSchema) defining the Zod validation for the tool's input: query, limit, page, detail_limit, researcher_name, from_fiscal_year, to_fiscal_year, include_outputs, force_refresh.
export const searchKakenProjectsInputSchema = z.object({ query: z.string().trim().min(1), limit: z.number().int().positive().max(20).default(10), page: z.number().int().positive().default(1), detail_limit: z.number().int().nonnegative().max(10).default(5), researcher_name: z.string().trim().min(1).optional(), from_fiscal_year: z.number().int().optional(), to_fiscal_year: z.number().int().optional(), include_outputs: z.boolean().default(true), force_refresh: forceRefreshFieldSchema }); - src/lib/schemas.ts:1175-1182 (schema)Output schema (searchKakenProjectsOutputSchema) defining the structure of the tool's response: query, page, limit, total, items (array of kakenProjectSchema), and optional cache.
export const searchKakenProjectsOutputSchema = z.object({ query: z.string(), page: z.number().int().positive(), limit: z.number().int().positive(), total: z.number().int().nonnegative(), items: z.array(kakenProjectSchema), cache: toolCacheSchema.optional() }); - src/lib/schemas.ts:1131-1173 (schema)The kakenProjectSchema defining a project item: project_id, title, url, principal_investigator, fiscal_years, project_type, fields, keywords, summary, detail_fetched, report_pdf_status, report_pdfs, outputs_preview, search_hints.
const kakenProjectSchema = z.object({ project_id: z.string(), title: z.string(), url: z.string(), principal_investigator: z.object({ name: z.string(), affiliation: z.string().nullable(), researcher_number: z.string().nullable() }).nullable(), fiscal_years: z.string().nullable(), project_type: z.string().nullable(), fields: z.array(z.string()), keywords: z.array(z.string()), summary: z.string().nullable(), detail_fetched: z.boolean(), detail_omitted_reason: z.enum([ "detail_limit_exceeded", "include_outputs_false", "fetch_failed" ]).nullable(), report_pdf_status: z.enum(["found", "none_found", "not_checked", "fetch_failed"]), report_pdfs: z.array(z.object({ label: z.string(), fiscal_year: z.string().nullable(), url: z.string() })), outputs_preview: z.array(z.object({ type: kakenOutputTypeSchema, raw_type: z.string().nullable(), title: z.string(), authors: z.array(z.string()), year: z.string().nullable(), doi: z.string().nullable(), url: z.string().nullable(), note: z.string().nullable() })), search_hints: z.object({ project_terms: z.array(z.string()), researcher_terms: z.array(z.string()), keyword_terms: z.array(z.string()), caution: z.string() }) }); - src/server.ts:456-464 (registration)Registration of the tool 'jp_lit_search_kaken_projects' via server.registerTool with description, input/output schemas, and the handler function.
server.registerTool( "jp_lit_search_kaken_projects", { description: "KAKEN から研究課題を検索し、研究テーマ・キーワード・報告書 PDF・成果リストの手がかりを返す補助 tool。論文・図書の文献確定は CiNii / J-STAGE / IRDB / NDL で再確認する", inputSchema: searchKakenProjectsInputSchema, outputSchema: searchKakenProjectsOutputSchema }, searchKakenProjectsTool );