@scavio/mcp-server 0.13.1 → 0.14.1

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 (98) hide show
  1. package/README.md +23 -10
  2. package/dist/auth/cimd.d.ts +2 -0
  3. package/dist/auth/cimd.js +20 -0
  4. package/dist/auth/cimd.js.map +1 -0
  5. package/dist/auth/provider.d.ts +12 -0
  6. package/dist/auth/provider.js +43 -0
  7. package/dist/auth/provider.js.map +1 -0
  8. package/dist/auth/routes.d.ts +2 -0
  9. package/dist/auth/routes.js +214 -0
  10. package/dist/auth/routes.js.map +1 -0
  11. package/dist/auth/stores.d.ts +33 -0
  12. package/dist/auth/stores.js +69 -0
  13. package/dist/auth/stores.js.map +1 -0
  14. package/dist/index.js +15 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/client.js +4 -1
  17. package/dist/lib/client.js.map +1 -1
  18. package/dist/lib/env.d.ts +3 -0
  19. package/dist/lib/env.js +4 -0
  20. package/dist/lib/env.js.map +1 -1
  21. package/dist/lib/errors.d.ts +5 -1
  22. package/dist/lib/errors.js +5 -1
  23. package/dist/lib/errors.js.map +1 -1
  24. package/dist/lib/tool-error.js +10 -0
  25. package/dist/lib/tool-error.js.map +1 -1
  26. package/dist/lib/trim-response.d.ts +6 -0
  27. package/dist/lib/trim-response.js +26 -0
  28. package/dist/lib/trim-response.js.map +1 -0
  29. package/dist/tools/airbnb.js +30 -49
  30. package/dist/tools/airbnb.js.map +1 -1
  31. package/dist/tools/amazon.js +11 -18
  32. package/dist/tools/amazon.js.map +1 -1
  33. package/dist/tools/appstore.js +16 -15
  34. package/dist/tools/appstore.js.map +1 -1
  35. package/dist/tools/booking.js +28 -45
  36. package/dist/tools/booking.js.map +1 -1
  37. package/dist/tools/capterra.js +16 -15
  38. package/dist/tools/capterra.js.map +1 -1
  39. package/dist/tools/companieshouse.js +11 -10
  40. package/dist/tools/companieshouse.js.map +1 -1
  41. package/dist/tools/ebay.js +21 -30
  42. package/dist/tools/ebay.js.map +1 -1
  43. package/dist/tools/extract.js +6 -5
  44. package/dist/tools/extract.js.map +1 -1
  45. package/dist/tools/g2.js +23 -22
  46. package/dist/tools/g2.js.map +1 -1
  47. package/dist/tools/glassdoor.js +18 -17
  48. package/dist/tools/glassdoor.js.map +1 -1
  49. package/dist/tools/google.js +154 -153
  50. package/dist/tools/google.js.map +1 -1
  51. package/dist/tools/googleads.js +20 -19
  52. package/dist/tools/googleads.js.map +1 -1
  53. package/dist/tools/googleplay.js +14 -13
  54. package/dist/tools/googleplay.js.map +1 -1
  55. package/dist/tools/homedepot.js +15 -28
  56. package/dist/tools/homedepot.js.map +1 -1
  57. package/dist/tools/indeed.js +20 -39
  58. package/dist/tools/indeed.js.map +1 -1
  59. package/dist/tools/index.d.ts +5 -4
  60. package/dist/tools/index.js +5 -4
  61. package/dist/tools/index.js.map +1 -1
  62. package/dist/tools/instagram.js +59 -58
  63. package/dist/tools/instagram.js.map +1 -1
  64. package/dist/tools/kuaishou.js +47 -46
  65. package/dist/tools/kuaishou.js.map +1 -1
  66. package/dist/tools/linkedin.js +26 -25
  67. package/dist/tools/linkedin.js.map +1 -1
  68. package/dist/tools/metaads.js +21 -20
  69. package/dist/tools/metaads.js.map +1 -1
  70. package/dist/tools/reddit.js +48 -47
  71. package/dist/tools/reddit.js.map +1 -1
  72. package/dist/tools/redfin.js +29 -28
  73. package/dist/tools/redfin.js.map +1 -1
  74. package/dist/tools/sec.js +36 -35
  75. package/dist/tools/sec.js.map +1 -1
  76. package/dist/tools/target.js +19 -40
  77. package/dist/tools/target.js.map +1 -1
  78. package/dist/tools/threads.js +20 -19
  79. package/dist/tools/threads.js.map +1 -1
  80. package/dist/tools/tiktok-shop.js +38 -37
  81. package/dist/tools/tiktok-shop.js.map +1 -1
  82. package/dist/tools/tiktok.js +54 -53
  83. package/dist/tools/tiktok.js.map +1 -1
  84. package/dist/tools/tripadvisor.js +20 -43
  85. package/dist/tools/tripadvisor.js.map +1 -1
  86. package/dist/tools/usage.js +3 -2
  87. package/dist/tools/usage.js.map +1 -1
  88. package/dist/tools/walmart.js +35 -34
  89. package/dist/tools/walmart.js.map +1 -1
  90. package/dist/tools/x.js +44 -43
  91. package/dist/tools/x.js.map +1 -1
  92. package/dist/tools/yelp.js +21 -20
  93. package/dist/tools/yelp.js.map +1 -1
  94. package/dist/tools/youtube.js +77 -76
  95. package/dist/tools/youtube.js.map +1 -1
  96. package/dist/tools/zillow.js +38 -53
  97. package/dist/tools/zillow.js.map +1 -1
  98. package/package.json +1 -1
package/dist/tools/g2.js CHANGED
@@ -1,65 +1,66 @@
1
1
  import { z } from "zod";
2
2
  import { handleApiError } from "../lib/tool-error.js";
3
+ import { trimResponse } from "../lib/trim-response.js";
3
4
  export function registerG2Tools(server, getClient) {
4
- server.tool("search_g2_software", `G2, the B2B software review site. Search it for business software products and get ranked rows back as JSON: product name, star rating, review count, vendor, categories, seller description and logo. Every row carries the product_id and slug that get_g2_product and get_g2_reviews take, so this is the entry point when you only have a product name or a category ("CRM", "project management"). Also returns total_results - G2's Products-tab headline, capped at 10000 - and total_by_type, which breaks the same query across products, sellers, categories and discussions. Paginate with the page parameter; limit is capped at 100 results per request. Pass query or url - at least one is required. COSTS 5 CREDITS PER CALL: G2 is the most expensive platform Scavio serves, so search once with a good query rather than probing. A G2 bot wall comes back as an error that was still billed upstream, so retry sparingly.`, {
5
+ server.tool("search_g2_software", `Search G2 B2B software products. 5 credits/call (most expensive platform). Query or url required.`, {
5
6
  query: z.string().min(1).max(200).optional()
6
- .describe("Software search term, e.g. 'project management' or 'notion'. Either this or url is required."),
7
+ .describe("Search term, e.g. 'project management'."),
7
8
  url: z.string().min(1).max(1000).optional()
8
- .describe("Full g2.com search URL to run verbatim, e.g. 'https://www.g2.com/search?query=crm'. Either this or query is required."),
9
+ .describe("g2.com search URL instead of query."),
9
10
  page: z.number().int().min(1).optional()
10
- .describe("Page number (1-indexed). 20 results per page unless limit says otherwise."),
11
+ .describe("Page, 1-based."),
11
12
  limit: z.number().int().min(1).max(100).optional()
12
- .describe("Results per page, 1-100 (default 20). 100 is our hard cap so a single request cannot ask for a multi-megabyte page; G2 itself keeps paginating at any size, so use page to go deeper."),
13
+ .describe("Per page, 1-100. Default 20."),
13
14
  sort: z.enum(["relevance", "popular", "alphabetical", "rating"]).optional()
14
- .describe("Sort order (default 'relevance'). Closed enum on purpose: G2 silently accepts an unknown sort and answers 200 in some unstated order, so an invalid value would look like it worked."),
15
+ .describe("Sort order."),
15
16
  rating: z.number().int().min(1).max(5).optional()
16
- .describe("Only products at or above this star rating (1-5)."),
17
+ .describe("Min star rating."),
17
18
  }, async (params) => {
18
19
  try {
19
20
  const data = await getClient().post("/api/v1/g2/search", params);
20
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
21
+ return trimResponse(data);
21
22
  }
22
23
  catch (err) {
23
24
  return handleApiError(err);
24
25
  }
25
26
  });
26
- server.tool("get_g2_product", `G2, the B2B software review site. Get one software product's full G2 profile as JSON: overall rating with the per-star histogram, review count, vendor, description and seller website, pricing editions with parsed amounts, feature groups, categories and breadcrumbs, supported languages, integrations, alternatives, head-to-head comparisons, media, community discussions, and G2's AI-derived pros and cons. THIS ENDPOINT CARRIES NO REVIEW TEXT AT ALL - G2 loads review bodies in a separate frame, so call get_g2_reviews for the actual written reviews. No pagination: one call returns the whole profile. product_id accepts either the slug ('notion') or the numeric G2 id ('82623') as a string; both resolve. Pass product_id or url - at least one is required. COSTS 5 CREDITS PER CALL, the most expensive platform Scavio serves. A G2 bot wall comes back as an error that was still billed upstream, so retry sparingly.`, {
27
+ server.tool("get_g2_product", `Get G2 product profile: ratings, pricing, features, alternatives. No review text; use get_g2_reviews. 5 credits.`, {
27
28
  product_id: z.string().min(1).max(200).optional()
28
- .describe("G2 product slug ('notion') or numeric G2 id as a string ('82623') - both resolve on the same upstream path. Either this or url is required."),
29
+ .describe("Product slug ('notion') or numeric id ('82623')."),
29
30
  url: z.string().min(1).max(1000).optional()
30
- .describe("Full g2.com product URL, e.g. 'https://www.g2.com/products/notion/reviews'. Either this or product_id is required."),
31
+ .describe("g2.com product URL instead of product_id."),
31
32
  }, async (params) => {
32
33
  try {
33
34
  const data = await getClient().post("/api/v1/g2/product", params);
34
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
35
+ return trimResponse(data);
35
36
  }
36
37
  catch (err) {
37
38
  return handleApiError(err);
38
39
  }
39
40
  });
40
- server.tool("get_g2_reviews", `G2, the B2B software review site. Get one page of written reviews for a software product as JSON: star rating, title, what the reviewer likes and dislikes, problems solved, reviewer job title, industry and company size, and validated/incentivized flags. This is the ONLY G2 tool that returns review text - get_g2_product deliberately has none. It also carries what the profile page has no form of: exact per-star review counts, pros and cons with per-theme counts, and company_size / role / industry / region / category facets with counts. Reviews are FIXED AT 10 PER PAGE and paginate well past the 10 pages G2's own widget links to, so walk page upward. The rating filter is HALF-STAR-INCLUSIVE: rating=1 returns 0, 0.5 and 1-star reviews. Every filter is a closed enum because an unrecognised filter value MATCHES NOTHING upstream and returns "Reviews (0)", which reads like the product genuinely has no such reviews. Pass product_id or url - at least one is required. COSTS 5 CREDITS PER PAGE, the most expensive platform Scavio serves, so filter down rather than paging blindly.`, {
41
+ server.tool("get_g2_reviews", `Get G2 review text for a product. 10 per page. rating filter is half-star-inclusive. 5 credits/page.`, {
41
42
  product_id: z.string().min(1).max(200).optional()
42
- .describe("G2 product slug ('notion') or numeric G2 id as a string ('82623'). Either this or url is required."),
43
+ .describe("Product slug or numeric id."),
43
44
  url: z.string().min(1).max(1000).optional()
44
- .describe("Full g2.com reviews URL. Either this or product_id is required."),
45
+ .describe("g2.com reviews URL instead of product_id."),
45
46
  page: z.number().int().min(1).optional()
46
- .describe("Page number (1-indexed). Fixed at 10 reviews per page; pages continue well past the 10 G2's own widget links to."),
47
+ .describe("Page, 1-based. 10 per page."),
47
48
  sort: z.enum(["relevance", "newest", "most_helpful", "rating_high", "rating_low"]).optional()
48
- .describe("Review sort order (default 'relevance'). Closed enum: G2 silently accepts an unknown sort and returns a full result set in some unstated order."),
49
+ .describe("Sort order."),
49
50
  rating: z.number().int().min(1).max(5).optional()
50
- .describe("Star bucket, 1-5. HALF-STAR-INCLUSIVE: 1 returns 0, 0.5 and 1-star reviews."),
51
+ .describe("Star bucket. Half-star-inclusive: 1 includes 0-1 stars."),
51
52
  company_size: z.enum(["small_business", "mid_market", "enterprise"]).optional()
52
- .describe("Reviewer company size: small_business (<=50 employees), mid_market (51-1000), enterprise (>1000). An unrecognised value would silently match nothing, hence the closed enum."),
53
+ .describe("small_business <=50, mid_market 51-1000, enterprise >1000."),
53
54
  role: z.enum(["user", "administrator", "executive_sponsor", "internal_consultant", "consultant", "agency", "industry_analyst"]).optional()
54
- .describe("Reviewer's relationship to the product."),
55
+ .describe("Reviewer role."),
55
56
  region: z.enum(["north_america", "europe", "asia", "latin_america", "anz", "middle_east", "africa"]).optional()
56
57
  .describe("Reviewer region."),
57
58
  query: z.string().min(1).max(200).optional()
58
- .describe("Full-text search within this product's reviews. Narrows the review list AND every facet count."),
59
+ .describe("Text search within reviews."),
59
60
  }, async (params) => {
60
61
  try {
61
62
  const data = await getClient().post("/api/v1/g2/reviews", params);
62
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
63
+ return trimResponse(data);
63
64
  }
64
65
  catch (err) {
65
66
  return handleApiError(err);
@@ -1 +1 @@
1
- {"version":3,"file":"g2.js","sourceRoot":"","sources":["../../src/tools/g2.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"g2.js","sourceRoot":"","sources":["../../src/tools/g2.ts"],"names":[],"mappings":"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"}
@@ -1,68 +1,69 @@
1
1
  import { z } from "zod";
2
2
  import { handleApiError } from "../lib/tool-error.js";
3
+ import { trimResponse } from "../lib/trim-response.js";
3
4
  // employer_id / company / url repeat on three of the four endpoints. `company`
4
5
  // is cosmetic on all of them and does NOT satisfy the identifier requirement —
5
6
  // the backend refine takes employer_id or url only.
6
7
  const employerIdField = z.string().min(1).max(50).optional()
7
- .describe("Glassdoor employer id as a STRING, in any form Glassdoor writes it: '1699', 'E1699' or 'IE1699'. A JSON number is rejected. Get one from resolve_glassdoor_company. Either this or url is required.");
8
+ .describe("Employer id as string, e.g. '1699' or 'E1699'. Not a number. Either this or url required.");
8
9
  const companyField = z.string().min(1).max(200).optional()
9
- .describe("Employer name as it appears in a Glassdoor slug, e.g. 'NIKE'. COSMETIC ONLY - the profile resolves on employer_id alone, and this is ignored entirely when url is set. It does NOT satisfy the employer_id-or-url requirement.");
10
+ .describe("Employer slug name, e.g. 'NIKE'. Cosmetic only.");
10
11
  export function registerGlassdoorTools(server, getClient) {
11
- server.tool("resolve_glassdoor_company", `START HERE for Glassdoor. Search Glassdoor for a company by name and resolve it to the employer_id that every other Glassdoor tool requires. Returns data with ranked, de-duplicated employer matches, each carrying its employer_id, name and profile URL. The employer_id lives only inside Glassdoor's /Overview/ URLs, so call this first unless you already hold one. No pagination - one ranked set per query. Glassdoor is slow and flaky: expect seconds to tens of seconds, and an occasional 502 after as long as ~3 minutes; retry once before giving up. Costs 1 credit.`, {
12
+ server.tool("resolve_glassdoor_company", `Resolve a company name to a Glassdoor employer_id. Start here. Slow (seconds-minutes), retry on 502. 1 credit.`, {
12
13
  query: z.string().min(1).max(120)
13
- .describe("Company name to resolve, e.g. 'Nike'."),
14
+ .describe("Company name, e.g. 'Nike'."),
14
15
  }, async (params) => {
15
16
  try {
16
17
  const data = await getClient().post("/api/v1/glassdoor/companies", params);
17
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
18
+ return trimResponse(data);
18
19
  }
19
20
  catch (err) {
20
21
  return handleApiError(err);
21
22
  }
22
23
  });
23
- server.tool("get_glassdoor_company", `Get a Glassdoor employer profile as JSON: description, mission, industry, sector, HQ, size band, revenue band, stock symbol, year founded, overall and per-category ratings, star distribution, CEO approval, awards, FAQ, the five server-rendered reviews, plus reviews_url and salaries_url. THE CHAINING STEP: pass reviews_url or salaries_url back as the url parameter of get_glassdoor_reviews / get_glassdoor_salaries to halve the upstream work those calls do. Requires employer_id or url - company alone is NOT an address and is rejected. Use resolve_glassdoor_company to turn a name into an employer_id. No pagination. Slow (roughly 3-47 seconds) and occasionally 502s; retry once. Costs 1 credit.`, {
24
+ server.tool("get_glassdoor_company", `Get Glassdoor employer profile with ratings, reviews, and reviews_url/salaries_url for chaining. employer_id or url required. Slow; retry on 502. 1 credit.`, {
24
25
  employer_id: employerIdField,
25
26
  company: companyField,
26
27
  url: z.string().min(1).max(500).optional()
27
- .describe("Any glassdoor.com employer URL - /Overview/, /Reviews/ or /Salary/, e.g. 'https://www.glassdoor.com/Overview/Working-at-NIKE-EI_IE1699.11,15.htm'. A non-glassdoor.com host is rejected. Either this or employer_id is required."),
28
+ .describe("Glassdoor employer URL. Either this or employer_id required."),
28
29
  }, async (params) => {
29
30
  try {
30
31
  const data = await getClient().post("/api/v1/glassdoor/company", params);
31
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
32
+ return trimResponse(data);
32
33
  }
33
34
  catch (err) {
34
35
  return handleApiError(err);
35
36
  }
36
37
  });
37
- server.tool("get_glassdoor_reviews", `Get Glassdoor employee reviews for one employer as JSON: up to THREE full reviews with per-axis scores, pros, cons, advice to management, job title, location, employment status and employer response - plus complete rating statistics, star distribution, aggregate pro/con highlight terms and per-job-title review counts. HARD CAP OF THREE REVIEWS per call (Glassdoor's login wall) and there is deliberately NO page parameter, so do not attempt to paginate. Move the window with category and employment_status instead, and read filtered_review_count on the response to see how many reviews match. Requires employer_id or url - company alone is NOT an address. Passing the reviews_url from get_glassdoor_company as url skips a fetch. Slow (~75 seconds); retry once on a 502. Costs 1 credit.`, {
38
+ server.tool("get_glassdoor_reviews", `Get Glassdoor reviews (max 3 per call, login wall). No pagination. Use category/employment_status to shift window. Pass reviews_url from get_glassdoor_company as url to skip a fetch. Slow (~75s). 1 credit.`, {
38
39
  employer_id: employerIdField,
39
40
  company: companyField,
40
41
  url: z.string().min(1).max(500).optional()
41
- .describe("Any glassdoor.com employer URL. Preferably the reviews_url returned by get_glassdoor_company, which skips the resolve fetch. A non-glassdoor.com host is rejected. Either this or employer_id is required."),
42
+ .describe("Glassdoor URL. Prefer reviews_url from get_glassdoor_company. Either this or employer_id."),
42
43
  category: z.enum(["career_development", "compensation", "culture", "diversity_and_inclusion", "management", "work_life_balance"]).optional()
43
- .describe("Restrict to reviews Glassdoor files under one topic. Closed set: Glassdoor silently IGNORES an unknown value and serves the unfiltered set under a 200."),
44
+ .describe("Review topic filter."),
44
45
  employment_status: z.enum(["full_time", "part_time", "contract", "intern"]).optional()
45
- .describe("Restrict to one kind of employment. Closed set: Glassdoor silently IGNORES an unknown value and serves the unfiltered set under a 200."),
46
+ .describe("Employment type filter."),
46
47
  }, async (params) => {
47
48
  try {
48
49
  const data = await getClient().post("/api/v1/glassdoor/reviews", params);
49
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
50
+ return trimResponse(data);
50
51
  }
51
52
  catch (err) {
52
53
  return handleApiError(err);
53
54
  }
54
55
  });
55
- server.tool("get_glassdoor_salaries", `Get Glassdoor salary data for one employer as JSON, broken down by job title: base-pay and total-pay percentiles P10-P90 with medians called out, sample counts, currency, pay period and last-reported date. These are Glassdoor's ESTIMATES for each job title, not individual reported salaries. Ten job titles per page - pass page for the next ten and read page_count on the response for how many pages exist. Requires employer_id or url - company alone is NOT an address. Passing the salaries_url from get_glassdoor_company as url skips a fetch. Slow (~41 seconds); retry once on a 502. Costs 1 credit per page.`, {
56
+ server.tool("get_glassdoor_salaries", `Get Glassdoor salary estimates by job title (P10-P90 percentiles). 10 titles/page. Pass salaries_url from get_glassdoor_company to skip a fetch. Slow (~41s). 1 credit/page.`, {
56
57
  employer_id: employerIdField,
57
58
  company: companyField,
58
59
  url: z.string().min(1).max(500).optional()
59
- .describe("Any glassdoor.com employer URL. Preferably the salaries_url returned by get_glassdoor_company, which skips the resolve fetch. A non-glassdoor.com host is rejected. Either this or employer_id is required."),
60
+ .describe("Glassdoor URL. Prefer salaries_url from get_glassdoor_company. Either this or employer_id."),
60
61
  page: z.number().int().min(1).optional()
61
- .describe("Results page, 1-based. Ten job titles per page; page_count on the response is how many pages there are. Defaults to 1."),
62
+ .describe("Page, 1-based. 10 titles/page."),
62
63
  }, async (params) => {
63
64
  try {
64
65
  const data = await getClient().post("/api/v1/glassdoor/salaries", params);
65
- return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
66
+ return trimResponse(data);
66
67
  }
67
68
  catch (err) {
68
69
  return handleApiError(err);
@@ -1 +1 @@
1
- {"version":3,"file":"glassdoor.js","sourceRoot":"","sources":["../../src/tools/glassdoor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"glassdoor.js","sourceRoot":"","sources":["../../src/tools/glassdoor.ts"],"names":[],"mappings":"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"}