const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
const cheerio = require('cheerio');
/**
* Parse MEXC date strings → ISO string (UTC)
*/
function parseDate(str) {
if (!str) return null;
const cleaned = str
.replace(/\s*\(UTC\)$/, ' UTC')
.replace(/UTC$/, ' UTC');
const ts = Date.parse(cleaned);
return isNaN(ts) ? null : new Date(ts).toISOString();
}
/**
* Generic fetcher for any MEXC announcement page
* Returns array of {title, link, published_at, content_raw}
*/
async function fetchAnnouncements(url) {
const resp = await fetch(url, {
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Safari/537.36',
'Accept-Language': 'en-US,en;q=0.9',
},
});
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} – ${url}`);
}
const html = await resp.text();
const $ = cheerio.load(html);
const items = [];
$('[class*="SearchResultItem_searchResultItem-community"]').each((_, el) => {
const header = $(el).find('[class*="SearchResultItem_header-community"]');
const title = header.text();
const link = "https://www.mexc.com" + header.find('a').attr('href');
const content_raw = ""; //toto
const timeStr = header.find('[class*="SearchResultItem_time-community"]').attr('datetime');
const published_at = parseDate(timeStr);
items.push({title, link, published_at, content_raw});
});
return items;
}
// ---------------------------------------------------------------------------
// MCP Server
// ---------------------------------------------------------------------------
const server = new McpServer({
name: 'MEXC Announcements',
version: '1.0.0',
});
// get_latest – return ALL recent announcements from the main page
server.registerTool(
'get_latest',
{
title: 'Get Latest MEXC Announcements',
description: 'Returns all recent announcements (any category)',
inputSchema: {},
outputSchema: {
type: 'array',
items: {
title: 'string',
link: 'string',
published_at: 'string | null',
},
},
},
async () => {
const items = await fetchAnnouncements('https://www.mexc.com/en-GB/announcements/all');
return {
content: [{ type: 'text', text: JSON.stringify(items, null, 2) }],
structuredContent: items.length ? items : [],
};
}
);
//get_new_listings – all new-listing announcements
server.registerTool(
'get_new_listings',
{
title: 'Get New Listings',
description: 'Returns every new token/coin listing announcement from MEXC',
inputSchema: {},
outputSchema: {
type: 'array',
items: {
title: 'string',
link: 'string',
published_at: 'string | null',
},
},
},
async () => {
const items = await fetchAnnouncements('https://www.mexc.com/en-GB/announcements/new-listings');
return {
content: [{ type: 'text', text: JSON.stringify(items, null, 2) }],
structuredContent: items,
};
}
);
// get_delistings – all delisting announcements
server.registerTool(
'get_delistings',
{
title: 'Get Delistings',
description: 'Returns every token/coin delisting announcement from MEXC',
inputSchema: {},
outputSchema: {
type: 'array',
items: {
title: 'string',
link: 'string',
published_at: 'string | null',
},
},
},
async () => {
const items = await fetchAnnouncements('https://www.mexc.com/en-GB/announcements/delistings');
return {
content: [{ type: 'text', text: JSON.stringify(items, null, 2) }],
structuredContent: items,
};
}
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch(console.error);