#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { RequestPayloadSchema } from "./types.js";
import { Fetcher } from "./Fetcher.js";
import { SuperstoreSitemapParser } from "./Sitemap.js";
import { SuperstoreAuth } from "./Auth.js";
import { SuperstoreOrders } from "./Orders.js";
import { SessionManager } from "./SessionManager.js";
import { exportOrdersToCSV, exportOrderDetailsToCSV, exportOrdersToJSON } from "./exportOrders.js";
import process from "process";
import { downloadLimit } from "./types.js";
const server = new Server(
{
name: "zcaceres/fetch",
version: "0.1.0",
},
{
capabilities: {
resources: {},
tools: {},
},
},
);
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "fetch_txt",
description:
"Fetch a website, convert the content to plain text (no HTML)",
inputSchema: {
type: "object",
properties: {
url: {
type: "string",
description: "URL of the website to fetch",
},
headers: {
type: "object",
description: "Optional headers to include in the request",
},
max_length: {
type: "number",
description: `Maximum number of characters to return (default: ${downloadLimit})`,
},
start_index: {
type: "number",
description: "Start content from this character index (default: 0)",
},
},
required: ["url"],
},
},
{
name: "parse_sitemap",
description: "Parse Superstore sitemap and extract category URLs",
inputSchema: {
type: "object",
properties: {
sitemap_url: {
type: "string",
description: "URL of the sitemap to parse (default: Superstore sitemap)",
},
},
required: [],
},
},
{
name: "get_categories",
description: "Get all categories from Superstore sitemap",
inputSchema: {
type: "object",
properties: {
sitemap_url: {
type: "string",
description: "URL of the sitemap to parse (default: Superstore sitemap)",
},
},
required: [],
},
},
{
name: "get_products",
description: "Get all products from multiple Superstore categories",
inputSchema: {
type: "object",
properties: {
category_ids: {
type: "array",
items: { type: "string" },
description: "Array of category IDs to get products from",
},
max_pages_per_category: {
type: "number",
description: "Maximum number of pages to fetch per category (default: 2)",
},
},
required: ["category_ids"],
},
},
{
name: "get_category",
description: "Get a single category by ID from Superstore sitemap",
inputSchema: {
type: "object",
properties: {
category_id: {
type: "string",
description: "Category ID to get information for",
},
sitemap_url: {
type: "string",
description: "URL of the sitemap to parse (default: Superstore sitemap)",
},
},
required: ["category_id"],
},
},
{
name: "get_product",
description: "Get a single product by searching for it in a specific category",
inputSchema: {
type: "object",
properties: {
category_id: {
type: "string",
description: "Category ID to search in",
},
product_name: {
type: "string",
description: "Name or partial name of the product to find",
},
max_pages: {
type: "number",
description: "Maximum number of pages to search (default: 1)",
},
},
required: ["category_id", "product_name"],
},
},
{
name: "get_product_details",
description: "Get detailed product information from individual product page",
inputSchema: {
type: "object",
properties: {
product_url: {
type: "string",
description: "URL of the product page to get details from",
},
},
required: ["product_url"],
},
},
{
name: "get_product_details_by_name",
description: "Get detailed product information by searching for a product name in a category",
inputSchema: {
type: "object",
properties: {
category_id: {
type: "string",
description: "Category ID to search in",
},
product_name: {
type: "string",
description: "Name or partial name of the product to find",
},
},
required: ["category_id", "product_name"],
},
},
{
name: "login",
description: "Authenticate user session with Superstore account",
inputSchema: {
type: "object",
properties: {},
required: [],
},
},
{
name: "logout",
description: "End session and clear cookies",
inputSchema: {
type: "object",
properties: {},
required: [],
},
},
{
name: "check_auth_status",
description: "Verify current authentication state",
inputSchema: {
type: "object",
properties: {},
required: [],
},
},
{
name: "get_orders",
description: "Retrieve order history with pagination",
inputSchema: {
type: "object",
properties: {
limit: {
type: "number",
description: "Number of orders to fetch (default: 10)",
},
offset: {
type: "number",
description: "Offset for pagination (default: 0)",
},
},
required: [],
},
},
{
name: "get_order_details",
description: "Get detailed information for a specific order",
inputSchema: {
type: "object",
properties: {
order_id: {
type: "string",
description: "Order ID to get details for",
},
},
required: ["order_id"],
},
},
{
name: "get_recent_orders",
description: "Get orders from recent period",
inputSchema: {
type: "object",
properties: {
days: {
type: "number",
description: "Number of days to look back (default: 30)",
},
},
required: [],
},
},
{
name: "export_orders_csv",
description: "Export all orders to CSV file with full details",
inputSchema: {
type: "object",
properties: {
include_items: {
type: "boolean",
description: "Include individual items (one row per item) or just order summaries (default: false)",
},
filepath: {
type: "string",
description: "Optional custom output filepath (default: auto-generated in current directory)",
},
},
required: [],
},
},
{
name: "export_orders_json",
description: "Export all orders to JSON file with full details",
inputSchema: {
type: "object",
properties: {
include_items: {
type: "boolean",
description: "Include full item details for each order (default: true)",
},
filepath: {
type: "string",
description: "Optional custom output filepath (default: auto-generated in current directory)",
},
},
required: [],
},
},
],
};
});
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
if (request.params.name === "fetch_txt") {
const validatedArgs = RequestPayloadSchema.parse(args);
const fetchResult = await Fetcher.txt(validatedArgs);
return fetchResult;
}
if (request.params.name === "parse_sitemap") {
const sitemapParser = new SuperstoreSitemapParser();
const sitemapUrl = (args as any)?.sitemap_url || "https://www.realcanadiansuperstore.ca/sitemap.xml";
try {
const sitemapUrls = await sitemapParser.parseSitemap(sitemapUrl);
const categories = sitemapParser.extractCategoriesFromSitemap(sitemapUrls);
return {
content: [{
type: "text",
text: JSON.stringify({
total_urls: sitemapUrls.length,
categories_found: categories.length,
categories: categories.slice(0, 20), // First 20 categories
sample_urls: sitemapUrls.slice(0, 10).map(u => u.loc)
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error parsing sitemap: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_categories") {
const sitemapParser = new SuperstoreSitemapParser();
const sitemapUrl = (args as any)?.sitemap_url || "https://www.realcanadiansuperstore.ca/sitemap.xml";
try {
const sitemapUrls = await sitemapParser.parseSitemap(sitemapUrl);
const categories = sitemapParser.extractCategoriesFromSitemap(sitemapUrls);
return {
content: [{
type: "text",
text: JSON.stringify({
total_urls: sitemapUrls.length,
categories_found: categories.length,
categories: categories
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error getting categories: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_products") {
const sitemapParser = new SuperstoreSitemapParser();
const categoryIds = (args as any)?.category_ids;
const maxPagesPerCategory = (args as any)?.max_pages_per_category || 2;
if (!categoryIds || !Array.isArray(categoryIds)) {
return {
content: [{ type: "text", text: "Error: category_ids must be an array of category IDs" }],
isError: true
};
}
try {
const allProducts: any[] = [];
for (const categoryId of categoryIds) {
try {
const products = await sitemapParser.getCategoryProducts(categoryId, maxPagesPerCategory);
allProducts.push(...products);
} catch (error) {
console.error(`Failed to get products for category ${categoryId}: ${error}`);
}
}
return {
content: [{
type: "text",
text: JSON.stringify({
categories_processed: categoryIds.length,
products_found: allProducts.length,
products: allProducts
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error getting products: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_category") {
const sitemapParser = new SuperstoreSitemapParser();
const categoryId = (args as any)?.category_id;
const sitemapUrl = (args as any)?.sitemap_url || "https://www.realcanadiansuperstore.ca/sitemap.xml";
if (!categoryId) {
return {
content: [{ type: "text", text: "Error: category_id is required" }],
isError: true
};
}
try {
const sitemapUrls = await sitemapParser.parseSitemap(sitemapUrl);
const categories = sitemapParser.extractCategoriesFromSitemap(sitemapUrls);
// Find the specific category
const category = categories.find(c => c.id === categoryId);
if (!category) {
return {
content: [{
type: "text",
text: JSON.stringify({
category_id: categoryId,
found: false,
message: "Category not found in sitemap"
}, null, 2)
}],
isError: false
};
}
return {
content: [{
type: "text",
text: JSON.stringify({
category_id: categoryId,
found: true,
category: category
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error getting category: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_product") {
const sitemapParser = new SuperstoreSitemapParser();
const categoryId = (args as any)?.category_id;
const productName = (args as any)?.product_name;
const maxPages = (args as any)?.max_pages || 1;
if (!categoryId || !productName) {
return {
content: [{ type: "text", text: "Error: category_id and product_name are required" }],
isError: true
};
}
try {
const products = await sitemapParser.getCategoryProducts(categoryId, maxPages);
// Search for products matching the name (case-insensitive)
const searchTerm = productName.toLowerCase();
const matchingProducts = products.filter(product =>
product.name.toLowerCase().includes(searchTerm)
);
return {
content: [{
type: "text",
text: JSON.stringify({
category_id: categoryId,
search_term: productName,
products_found: matchingProducts.length,
total_products_searched: products.length,
products: matchingProducts
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error getting product: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "search_products") {
const sitemapParser = new SuperstoreSitemapParser();
const searchTerm = (args as any)?.search_term;
const maxCategories = (args as any)?.max_categories || 20;
const maxPagesPerCategory = (args as any)?.max_pages_per_category || 1;
const sitemapUrl = (args as any)?.sitemap_url || "https://www.realcanadiansuperstore.ca/sitemap.xml";
if (!searchTerm) {
return {
content: [{ type: "text", text: "Error: search_term is required" }],
isError: true
};
}
try {
// Get all categories from sitemap
const sitemapUrls = await sitemapParser.parseSitemap(sitemapUrl);
const categories = sitemapParser.extractCategoriesFromSitemap(sitemapUrls);
// Limit categories to search
const categoriesToSearch = categories.slice(0, maxCategories);
const allMatchingProducts: any[] = [];
const searchResults: any[] = [];
// Search through each category
for (const category of categoriesToSearch) {
try {
const products = await sitemapParser.getCategoryProducts(category.id, maxPagesPerCategory);
// Search for products matching the term (case-insensitive)
const matchingProducts = products.filter(product =>
product.name.toLowerCase().includes(searchTerm.toLowerCase())
);
if (matchingProducts.length > 0) {
searchResults.push({
category_id: category.id,
category_name: category.name,
products_found: matchingProducts.length,
products: matchingProducts
});
allMatchingProducts.push(...matchingProducts);
}
} catch (error) {
console.error(`Failed to search category ${category.id}: ${error}`);
}
}
return {
content: [{
type: "text",
text: JSON.stringify({
search_term: searchTerm,
categories_searched: categoriesToSearch.length,
categories_with_matches: searchResults.length,
total_products_found: allMatchingProducts.length,
search_results: searchResults
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error searching products: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_product_details") {
const sitemapParser = new SuperstoreSitemapParser();
const productUrl = (args as any)?.product_url;
if (!productUrl) {
return {
content: [{ type: "text", text: "Error: product_url is required" }],
isError: true
};
}
try {
const productDetails = await sitemapParser.getProductDetails(productUrl);
return {
content: [{
type: "text",
text: JSON.stringify(productDetails, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error getting product details: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_product_details_by_name") {
const sitemapParser = new SuperstoreSitemapParser();
const categoryId = (args as any)?.category_id;
const productName = (args as any)?.product_name;
if (!categoryId || !productName) {
return {
content: [{ type: "text", text: "Error: category_id and product_name are required" }],
isError: true
};
}
try {
const productDetails = await sitemapParser.getProductDetailsByName(categoryId, productName);
if (productDetails) {
return {
content: [{
type: "text",
text: JSON.stringify(productDetails, null, 2)
}],
isError: false
};
} else {
return {
content: [{ type: "text", text: `Product "${productName}" not found in category ${categoryId}` }],
isError: true
};
}
} catch (error) {
return {
content: [{ type: "text", text: `Error getting product details by name: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
// Authentication and Order Management Tools
if (request.params.name === "login") {
const sessionManager = SessionManager.getInstance();
try {
const auth = await sessionManager.getAuthenticatedSession();
const sessionInfo = sessionManager.getSessionInfo();
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: "Successfully logged in",
session_info: sessionInfo
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Login error: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "logout") {
const sessionManager = SessionManager.getInstance();
try {
await sessionManager.logout();
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: "Successfully logged out"
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Logout error: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "check_auth_status") {
const sessionManager = SessionManager.getInstance();
try {
const isAuthenticated = await sessionManager.isAuthenticated();
const sessionInfo = sessionManager.getSessionInfo();
const stats = sessionManager.getSessionStats();
return {
content: [{
type: "text",
text: JSON.stringify({
isAuthenticated,
session_info: sessionInfo,
session_stats: stats
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Auth status check error: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_orders") {
const sessionManager = SessionManager.getInstance();
const limit = (args as any)?.limit || 10;
const offset = (args as any)?.offset || 0;
try {
const auth = await sessionManager.getAuthenticatedSession();
const orders = new SuperstoreOrders(auth);
const result = await orders.getOrders(limit, offset);
return {
content: [{
type: "text",
text: JSON.stringify(result, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error getting orders: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_order_details") {
const sessionManager = SessionManager.getInstance();
const orderId = (args as any)?.order_id;
if (!orderId) {
return {
content: [{ type: "text", text: "Error: order_id is required" }],
isError: true
};
}
try {
const auth = await sessionManager.getAuthenticatedSession();
const orders = new SuperstoreOrders(auth);
const orderDetails = await orders.getOrderDetails(orderId);
if (orderDetails) {
return {
content: [{
type: "text",
text: JSON.stringify(orderDetails, null, 2)
}],
isError: false
};
} else {
return {
content: [{ type: "text", text: `Order ${orderId} not found` }],
isError: true
};
}
} catch (error) {
return {
content: [{ type: "text", text: `Error getting order details: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "get_recent_orders") {
const sessionManager = SessionManager.getInstance();
const days = (args as any)?.days || 30;
try {
const auth = await sessionManager.getAuthenticatedSession();
const orders = new SuperstoreOrders(auth);
const recentOrders = await orders.getRecentOrders(days);
return {
content: [{
type: "text",
text: JSON.stringify({
days,
orders_found: recentOrders.length,
orders: recentOrders
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error getting recent orders: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "export_orders_csv") {
const sessionManager = SessionManager.getInstance();
const includeItems = (args as any)?.include_items || false;
const filepath = (args as any)?.filepath;
try {
const auth = await sessionManager.getAuthenticatedSession();
const orders = new SuperstoreOrders(auth);
const allOrders = await orders.getOrders(100, 0);
let outputPath: string;
if (includeItems) {
// Fetch full details for each order
const orderDetailsPromises = allOrders.orders.map(o => orders.getOrderDetails(o.id));
const orderDetails = (await Promise.all(orderDetailsPromises)).filter(Boolean) as any[];
outputPath = exportOrderDetailsToCSV(orderDetails, filepath);
} else {
outputPath = exportOrdersToCSV(allOrders.orders, filepath);
}
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
filepath: outputPath,
orders_exported: allOrders.orders.length,
include_items: includeItems
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error exporting orders to CSV: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
if (request.params.name === "export_orders_json") {
const sessionManager = SessionManager.getInstance();
const includeItems = (args as any)?.include_items !== false;
const filepath = (args as any)?.filepath;
try {
const auth = await sessionManager.getAuthenticatedSession();
const orders = new SuperstoreOrders(auth);
const allOrders = await orders.getOrders(100, 0);
let dataToExport: any[];
if (includeItems) {
// Fetch full details for each order
const orderDetailsPromises = allOrders.orders.map(o => orders.getOrderDetails(o.id));
dataToExport = (await Promise.all(orderDetailsPromises)).filter(Boolean) as any[];
} else {
dataToExport = allOrders.orders;
}
const outputPath = exportOrdersToJSON(dataToExport, filepath);
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
filepath: outputPath,
orders_exported: dataToExport.length,
include_items: includeItems
}, null, 2)
}],
isError: false
};
} catch (error) {
return {
content: [{ type: "text", text: `Error exporting orders to JSON: ${error instanceof Error ? error.message : 'Unknown error'}` }],
isError: true
};
}
}
throw new Error("Tool not found");
});
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});