periodicos-capes-mcp
Version:
MCP server para consulta de periódicos científicos do Portal de Periódicos CAPES
93 lines (92 loc) • 3.38 kB
JavaScript
export class OpenAlexService {
static BASE_URL = 'https://api.openalex.org';
/**
* Get metrics for a single article by DOI
*/
static async getMetricsByDOI(doi) {
try {
const url = `${this.BASE_URL}/works/https://doi.org/${doi}`;
const response = await fetch(url);
if (!response.ok) {
if (response.status === 404) {
return null; // Article not found in OpenAlex
}
throw new Error(`OpenAlex API error: ${response.status}`);
}
const data = await response.json();
return this.parseOpenAlexWork(data);
}
catch (error) {
return null;
}
}
/**
* Get metrics for multiple articles by DOI (batch processing)
*/
static async getMetricsByDOIs(dois) {
const results = new Map();
// Process in batches of 50 (OpenAlex limit per request)
const BATCH_SIZE = 50;
for (let i = 0; i < dois.length; i += BATCH_SIZE) {
const batch = dois.slice(i, i + BATCH_SIZE);
const batchResults = await this.processBatch(batch);
// Merge results
for (const [doi, metrics] of batchResults) {
results.set(doi, metrics);
}
// Small delay between batches to be respectful
if (i + BATCH_SIZE < dois.length) {
await new Promise(resolve => setTimeout(resolve, 100));
}
}
return results;
}
/**
* Process a batch of DOIs using correct OpenAlex syntax
*/
static async processBatch(dois) {
const results = new Map();
try {
// Build filter with pipe-separated DOIs (correct OpenAlex syntax)
const doiFilter = `doi:${dois.join('|')}`;
const url = `${this.BASE_URL}/works?filter=${encodeURIComponent(doiFilter)}&per-page=${dois.length}`;
const response = await fetch(url);
if (!response.ok) {
const errorText = await response.text();
return results;
}
const data = await response.json();
// Process each work in the response
if (data.results && Array.isArray(data.results)) {
for (const work of data.results) {
const metrics = this.parseOpenAlexWork(work);
if (metrics && work.doi) {
// Extract DOI from OpenAlex format (https://doi.org/...)
const doi = work.doi.replace('https://doi.org/', '');
results.set(doi, metrics);
}
}
}
}
catch (error) {
}
return results;
}
/**
* Parse OpenAlex work object into ArticleMetrics
*/
static parseOpenAlexWork(work) {
try {
return {
cited_by_count: work.cited_by_count || 0,
fwci: work.fwci || undefined,
publication_year: work.publication_year || new Date().getFullYear(),
is_open_access: work.open_access?.is_oa || false,
open_access_oa_date: work.open_access?.oa_date || undefined,
};
}
catch (error) {
return null;
}
}
}