@chrisreedio/fontawesome-pro-mcp
Version:
Font Awesome Pro MCP Server for icon search and retrieval
120 lines • 4.01 kB
JavaScript
import { readFileSync } from 'fs';
import { join } from 'path';
import { load } from 'js-yaml';
class FontAwesomeLoader {
iconsMetadata = null;
faPath = null;
constructor() {
this.findFontAwesomePath();
}
findFontAwesomePath() {
// Try possible locations for Font Awesome Pro based on current working directory
const possiblePaths = [
join(process.cwd(), 'node_modules', '@fortawesome', 'fontawesome-pro')
];
for (const path of possiblePaths) {
try {
const packagePath = join(path, 'package.json');
readFileSync(packagePath, 'utf8');
this.faPath = path;
return;
}
catch {
// Continue to next path
}
}
// Provide more detailed error information
const debugInfo = {
cwd: process.cwd(),
searchedPaths: possiblePaths
};
throw new Error(`Font Awesome Pro not found. Make sure it is installed with your .npmrc token.\n` +
`Debug info: ${JSON.stringify(debugInfo, null, 2)}`);
}
loadMetadata() {
if (this.iconsMetadata) {
return this.iconsMetadata;
}
if (!this.faPath) {
throw new Error('Font Awesome path not initialized');
}
try {
const metadataPath = join(this.faPath, 'metadata', 'icons.yml');
const yamlContent = readFileSync(metadataPath, 'utf8');
const metadata = load(yamlContent);
this.iconsMetadata = metadata;
return metadata;
}
catch (error) {
throw new Error(`Failed to load Font Awesome metadata: ${error}`);
}
}
loadSvg(name, style) {
if (!this.faPath) {
throw new Error('Font Awesome path not initialized');
}
try {
const svgPath = join(this.faPath, 'svgs', style, `${name}.svg`);
return readFileSync(svgPath, 'utf8');
}
catch (error) {
return null;
}
}
getAllIcons() {
const metadata = this.loadMetadata();
const icons = [];
for (const [name, iconData] of Object.entries(metadata)) {
for (const style of iconData.styles) {
icons.push({
name,
style,
label: iconData.label,
search: iconData.search,
unicode: iconData.unicode
});
}
}
return icons;
}
getIcon(name, style) {
const metadata = this.loadMetadata();
const iconData = metadata[name];
if (!iconData || !iconData.styles.includes(style)) {
return null;
}
const svg = this.loadSvg(name, style);
return {
name,
style,
label: iconData.label,
search: iconData.search,
unicode: iconData.unicode,
svg: svg || undefined
};
}
searchIcons(query) {
const allIcons = this.getAllIcons();
if (!query.trim()) {
return allIcons.slice(0, 50); // Return first 50 icons if no query
}
const normalizedQuery = query.toLowerCase();
return allIcons.filter(icon => {
// Search in name
if (icon.name.toLowerCase().includes(normalizedQuery)) {
return true;
}
// Search in label
if (icon.label && icon.label.toLowerCase().includes(normalizedQuery)) {
return true;
}
// Search in terms
if (icon.search?.terms) {
return icon.search.terms.some(term => term.toLowerCase().includes(normalizedQuery));
}
return false;
}).slice(0, 50); // Limit results
}
}
export const faLoader = new FontAwesomeLoader();
//# sourceMappingURL=loader.js.map