mallmaverick-store-scraper 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/mcp-server.js +46 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mallmaverick-store-scraper",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "MCP server + CLI for scraping shopping mall store directories. Hours-first layered pipeline + image classification.",
5
5
  "main": "src/main.js",
6
6
  "type": "commonjs",
package/src/mcp-server.js CHANGED
@@ -59,7 +59,12 @@ const TOOLS = [
59
59
  'Scrape a shopping-mall store directory and return per-store records ' +
60
60
  '(name, hours, phone, logo, brand image, categories, etc.). Use this ' +
61
61
  'when the user wants to capture a directory like ' +
62
- 'https://grasslands.ca/store-directory/.',
62
+ 'https://grasslands.ca/store-directory/.\n\n' +
63
+ 'AFTER RUNNING THIS TOOL: give a short summary — how many stores were ' +
64
+ 'extracted, hours-layer breakdown, and the saved file path. The CSV is ' +
65
+ 'attached as a resource in the tool response (the user can download/' +
66
+ 'preview it from there) — do NOT paste the CSV text into your reply. ' +
67
+ 'Keep your text reply short.',
63
68
  inputSchema: {
64
69
  type: 'object',
65
70
  properties: {
@@ -124,8 +129,10 @@ const TOOLS = [
124
129
  },
125
130
  ];
126
131
 
132
+ const PACKAGE_VERSION = '0.1.3';
133
+
127
134
  const server = new Server(
128
- { name: 'mall-scraper-mcp', version: '0.1.1' },
135
+ { name: 'mall-scraper-mcp', version: PACKAGE_VERSION },
129
136
  { capabilities: { tools: {} } }
130
137
  );
131
138
 
@@ -221,13 +228,47 @@ async function handleScrapeDirectory({ directory_url, max_stores = 10, concurren
221
228
  written_files: writtenPaths,
222
229
  write_error: writeError,
223
230
  auth_mode: creds.mode,
231
+ mcp_version: PACKAGE_VERSION,
224
232
  };
225
233
 
234
+ // Build a short brief + return the CSV as an embedded resource so
235
+ // Claude Desktop can render it as an attachment card instead of inline
236
+ // text. Falls back to inline-rendering if the client doesn't support
237
+ // resources, but most clients (including Claude Desktop) do.
238
+ const host = new URL(directory_url).hostname.replace(/^www\./, '');
239
+ const csvFilename = writtenPaths
240
+ ? path.basename(writtenPaths.csv)
241
+ : `stores_v5_${host}.csv`;
242
+ const csvUri = writtenPaths
243
+ ? `file://${writtenPaths.csv}`
244
+ : `file:///tmp/${csvFilename}`;
245
+
246
+ const brief =
247
+ `mall-scraper-mcp v${PACKAGE_VERSION}\n` +
248
+ `Scraped ${stores.length} store${stores.length === 1 ? '' : 's'} from ${host}.\n` +
249
+ `Hours-layer breakdown: ${Object.entries(bySource).map(([k, v]) => `${k}=${v}`).join(', ')}.\n` +
250
+ (writtenPaths
251
+ ? `Saved to: ${writtenPaths.csv}`
252
+ : `⚠ disk write failed (${writeError}); CSV is in the attached resource only.`);
253
+
226
254
  return {
227
255
  content: [
228
- { type: 'text', text: JSON.stringify(summary, null, 2) },
229
- { type: 'text', text: '\n--- CSV (paste this into your CMS) ---\n' + csvText },
230
- { type: 'text', text: '\n--- Stores (JSON) ---\n' + JSON.stringify(stores, null, 2) },
256
+ { type: 'text', text: brief },
257
+ {
258
+ type: 'resource',
259
+ resource: {
260
+ uri: csvUri,
261
+ name: csvFilename,
262
+ mimeType: 'text/csv',
263
+ text: csvText,
264
+ },
265
+ },
266
+ // Keep the JSON summary at the end for any debugging the user asks for,
267
+ // but it's far enough down that it doesn't dominate the chat.
268
+ {
269
+ type: 'text',
270
+ text: '\n--- Run summary ---\n' + JSON.stringify(summary, null, 2),
271
+ },
231
272
  ],
232
273
  };
233
274
  } finally {