getFeatured.ts•2.22 kB
import ThingiversePuppeteer from '@/class/thingiverser.class';
import { mcpServer } from '@/index';
import { Thing } from '@/types/things';
import z from 'zod';
mcpServer.tool(
'get-featured-things',
'Get featured or popular 3D models from Thingiverse',
{
type: z
.enum(['featured', 'popular', 'newest', 'staff-picks'])
.default('featured')
.describe('Type of featured content to retrieve'),
page: z.number().optional().default(1).describe('Page number to retrieve'),
},
async ({ type, page }) => {
const thingiverser = new ThingiversePuppeteer(process.env.APP_TOKEN as string);
const perPage = 100;
await thingiverser.init();
try {
const featuredThings = await thingiverser.getFeaturedThings(type, page, perPage);
await thingiverser.close();
if (!featuredThings || featuredThings.length === 0) {
return {
content: [
{
type: 'text',
text: JSON.stringify(
{
success: true,
page,
perPage,
total: 0,
items: [],
},
null,
2,
),
},
],
};
}
// Format the response
const response = {
success: true,
page,
perPage,
total: featuredThings.length,
items: featuredThings.map((thing: Thing) => ({
id: thing.id,
name: thing.name,
url: thing.public_url,
thumbnail: thing.thumbnail,
likeCount: thing.like_count,
description: thing.description,
creator: {
id: thing.creator.id,
name: thing.creator.name,
},
added: thing.added,
downloadCount: thing.download_count,
tags: thing.tags,
})),
};
return {
content: [{ type: 'text', text: JSON.stringify(response, null, 2) }],
};
} catch (error) {
await thingiverser.close();
return {
isError: true,
content: [{ type: 'text', text: `Error fetching featured things: ${error}` }],
};
}
},
);