Skip to main content
Glama

searchByTitle

Search for scientific papers by title in Crossref to find academic publications and retrieve structured metadata about scholarly works.

Instructions

Search for scientific papers by title in Crossref

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
titleYesThe title to search for
rowsNoNumber of results to return

Implementation Reference

  • Primary handler implementation for the 'searchByTitle' tool. Fetches academic works from Crossref API using the provided title query, limits results with 'rows', formats them using formatWorkToJson helper, and returns structured JSON response or error.
    async ({ title, rows }) => { try { const url = `${CROSSREF_API_BASE}/works?query.title=${encodeURIComponent( title )}&rows=${rows}&select=${CROSSREF_SELECT_FIELDS}`; const response = await fetch(url, { headers: { "User-Agent": "Crossref MCP Server", }, }); if (!response.ok) { throw new Error(`API request failed with status ${response.status}`); } const data = await response.json(); const works = data.message?.items || []; if (works.length === 0) { return { content: [ { type: "text", text: JSON.stringify( { status: "no_results", query: { title, rows }, results: [], }, null, 2 ), }, ], }; } const formattedWorks = works.map((work) => formatWorkToJson(work)); return { content: [ { type: "text", text: JSON.stringify( { status: "success", query: { title, rows }, count: formattedWorks.length, results: formattedWorks, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text", text: JSON.stringify( { status: "error", message: error.message, query: { title, rows }, }, null, 2 ), }, ], }; } }
  • Input schema validation using Zod for the searchByTitle tool parameters.
    { title: z.string().describe("The title to search for"), rows: z .number() .optional() .default(5) .describe("Number of results to return"), },
  • mcp-server.js:21-107 (registration)
    Registration of the 'searchByTitle' tool on the MCP server, specifying name, description, input schema, and handler function.
    server.tool( "searchByTitle", "Search for scientific papers by title in Crossref", { title: z.string().describe("The title to search for"), rows: z .number() .optional() .default(5) .describe("Number of results to return"), }, async ({ title, rows }) => { try { const url = `${CROSSREF_API_BASE}/works?query.title=${encodeURIComponent( title )}&rows=${rows}&select=${CROSSREF_SELECT_FIELDS}`; const response = await fetch(url, { headers: { "User-Agent": "Crossref MCP Server", }, }); if (!response.ok) { throw new Error(`API request failed with status ${response.status}`); } const data = await response.json(); const works = data.message?.items || []; if (works.length === 0) { return { content: [ { type: "text", text: JSON.stringify( { status: "no_results", query: { title, rows }, results: [], }, null, 2 ), }, ], }; } const formattedWorks = works.map((work) => formatWorkToJson(work)); return { content: [ { type: "text", text: JSON.stringify( { status: "success", query: { title, rows }, count: formattedWorks.length, results: formattedWorks, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text", text: JSON.stringify( { status: "error", message: error.message, query: { title, rows }, }, null, 2 ), }, ], }; } } );
  • Helper function to format Crossref work data into a clean JSON structure, used by the searchByTitle handler to process API responses.
    export const formatWorkToJson = (work) => { if (!work) return { error: "No data available" }; return { title: work.title?.[0] || null, authors: work.author ? work.author.map((a) => ({ given: a.given || null, family: a.family || null, name: `${a.given || ""} ${a.family || ""}`.trim(), })) : [], published: work.published ? { dateParts: work.published["date-parts"]?.[0] || [], dateString: work.published["date-parts"]?.[0]?.join("-") || null, } : null, type: work.type || null, doi: work.DOI || null, url: work.URL || null, container: work["container-title"]?.[0] || null, publisher: work.publisher || null, issue: work.issue || null, volume: work.volume || null, abstract: work.abstract || null, }; };
  • Test or alternative handler implementation for searchByTitle in the test handlers file, nearly identical to the main handler.
    searchByTitle: async ({ title, rows = 5 }) => { try { const url = `https://api.crossref.org/works?query.title=${encodeURIComponent( title )}&rows=${rows}`; const response = await fetch(url, { headers: { "User-Agent": "Crossref MCP Server Test", }, }); if (!response.ok) { throw new Error(`API request failed with status ${response.status}`); } const data = await response.json(); const works = data.message?.items || []; if (works.length === 0) { return { content: [ { type: "text", text: JSON.stringify( { status: "no_results", query: { title, rows }, results: [], }, null, 2 ), }, ], }; } const formattedWorks = works.map((work) => formatWorkToJson(work)); return { content: [ { type: "text", text: JSON.stringify( { status: "success", query: { title, rows }, count: formattedWorks.length, results: formattedWorks, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: "text", text: JSON.stringify( { status: "error", message: error.message, query: { title, rows }, }, null, 2 ), }, ], }; } },

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/botanicastudios/crossref-mcp'

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