@cite42/mcp 0.6.2 → 0.7.0

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.
package/README.md CHANGED
@@ -149,7 +149,7 @@ Cite42 exposes 29 MCP tools: 4 free account tools (including the compatibility a
149
149
  - `cite42_rankings`: measure how brands rank in AI answers, including mention rate, average position, and per-model breakdown.
150
150
  - `cite42_compare`: compare one brand against competitors in AI answers.
151
151
  - `cite42_sentiment`: score positive, neutral, and negative sentiment for a brand, with supporting phrases.
152
- - `cite42_recommendations`: request an optional paid next-step report using saved results or supplied evidence, with business context. Insufficient evidence and rule-only fallback are free.
152
+ - `cite42_recommendations`: page-level recommendations. A page URL alone gets a free technical check with suggested buyer questions; with a buyer question it measures citations and compares your page with up to two pages the AI surfaces cited, charged only when it includes verified page-comparison advice (plus the citations check it ran).
153
153
 
154
154
  ### SEO & trend data
155
155
 
@@ -245,11 +245,17 @@ the complete prompt/configuration set, methodology and complete coverage to matc
245
245
  Individual prompts remain small samples (at most five surfaces); percentage-point changes are withheld
246
246
  below 10 answers per group in each run. This guardrail does not establish statistical significance.
247
247
 
248
- `cite42_recommendations` is a separate, optional paid report. Use exactly one `requestId` returned by
249
- an earlier call, a user-owned `trackerRunId`, or a structured `evidence` array. Optional `context`
250
- accepts brand, domain, audience and goal for this request only. Check `cite42_pricing` for the current
251
- flat report price and obtain the user's agreement before running the add-on. Insufficient evidence
252
- and rule-only fallback are free.
248
+ `cite42_recommendations` is a separate, optional report. With no saved result, `url` alone runs a free
249
+ technical check (robots.txt crawler access, indexing, rendering) and suggests buyer questions, and `url`
250
+ with `query` first runs a citations check, priced like `cite42_citations`. Otherwise use one `requestId`
251
+ returned by an earlier call, a user-owned `trackerRunId`, or a structured `evidence` array. Pass `url` for the page
252
+ that should answer the prompt, or `context.domain` to look for a match in that site's sitemap, and
253
+ `query` to choose a prompt when the evidence covers several. Optional `context` also accepts brand,
254
+ audience and goal for this request only. The report fetches that page, its robots.txt and up to two
255
+ pages the AI surfaces cited, as returned HTML without JavaScript. Check `cite42_pricing` for the
256
+ current report price and obtain the user's agreement before running the add-on. It is charged only
257
+ when the report includes page-comparison recommendations backed by quotes from the inspected pages;
258
+ everything else is free.
253
259
 
254
260
  For rankings evidence, provide `context.brand` to identify the tracked brand you want advice for.
255
261
  Without it, the measurements remain available but the tool asks which brand to focus on for free;
package/dist/stdio.cjs CHANGED
@@ -178,7 +178,7 @@ var SHORT_TEXT_MAX_CHARS = 200;
178
178
  var TIMEFRAME_MAX_CHARS = 80;
179
179
  var MODEL_SELECTION_DESCRIPTION = 'Optional model subset. Omit to query the default surfaces (chatgpt, perplexity, gemini). Pass ["perplexity"] or ["perplexity","claude"] when the user names specific surfaces or wants to reduce cost. The full set is chatgpt, claude, perplexity, gemini, google_ai_overview \u2014 to query all of them, set fullSweep instead of listing them.';
180
180
  var FULL_SWEEP_DESCRIPTION = "Query all five AI surfaces instead of the three default ones, adding claude and google_ai_overview. Costs more per call. Use it when the user wants complete cross-model coverage, is comparing surfaces against each other, or asks specifically about Claude or Google AI Overviews. Ignored when models is given.";
181
- var MCP_USAGE_GUIDANCE = "Covers AI-search, citation, SEO, keyword, trend, and market-research data. If a plan needs more than 20 endpoint calls or may use more than $5 USD, estimate the cost in USD and ask the user before continuing. Quote Cite42 costs and balances in USD using cite42Billing or the USD pricing table. Legacy credit fields are for compatibility only. These funds belong to Cite42, not the host or model provider. AI visibility metrics include counts; quote them with percentages, not as a market-wide score. Optional recommendations are a separate paid call, never automatic. After a visibility result, offer recommendations using its requestId; run only when the user requests advice and knows the additional cost. Free: cite42_balance for the remaining balance, cite42_pricing for exact per-tool prices and cost estimates, cite42_usage for recent calls.";
181
+ var MCP_USAGE_GUIDANCE = "Covers AI-search, citation, SEO, keyword, trend, and market-research data. If a plan needs more than 20 endpoint calls or may use more than $5 USD, estimate the cost in USD and ask the user before continuing. Quote Cite42 costs and balances in USD using cite42Billing or the USD pricing table. Legacy credit fields are for compatibility only. These funds belong to Cite42, not the host or model provider. AI visibility metrics include counts; quote them with percentages, not as a market-wide score. Optional recommendations are a separate paid call, never automatic. Recommendations take the requestId of a visibility result and the page URL, or a page URL alone for a free technical check; they run only when the user requests advice and knows any additional cost. Free: cite42_balance for the remaining balance, cite42_pricing for exact per-tool prices and cost estimates, cite42_usage for recent calls.";
182
182
  var MODEL_PRICING = "Pricing is per selected AI surface. Omitting models queries the three default surfaces (chatgpt, perplexity, gemini); fullSweep: true queries all five, adding claude and google_ai_overview at a higher cost. Use the models field when the user names a surface or asks to reduce spending, and call cite42_pricing for exact current rates.";
183
183
  var DATA_PRICING = "Data tools have flat per-call prices; call cite42_pricing for exact current rates.";
184
184
  var KEYWORDS_PRICING = "Pricing: billed by outcome \u2014 cheapest when the seed has no search volume, more when it has metrics, most with ideas:true. Call cite42_pricing for exact current rates.";
@@ -209,7 +209,7 @@ function shortText(description) {
209
209
  var aivRecommendations = (0, import_tools.createTool)({
210
210
  id: "cite42_recommendations",
211
211
  mcp: readOnly("Recommend AI visibility next steps"),
212
- description: "Optional evidence-backed AI visibility recommendations. Flat price from cite42_pricing per completed AI report; insufficient evidence and rule-only fallback are free. Supports rankings, compare, citations and sentiment, including usable workflow steps. No crawling, fresh research, keyword advice or tracker activation. " + MCP_USAGE_GUIDANCE,
212
+ description: "Page-level AI visibility recommendations. With a saved result (requestId, trackerRunId or evidence) it reports on one measured prompt, charged only when the report includes page-comparison advice backed by quotes from inspected pages. Without one: url alone runs a free technical check of the page (robots.txt crawler access, indexing, rendering) and returns suggested buyer questions; url with query first runs a citations check, priced like cite42_citations, then the report. Prices are in cite42_pricing. Fetches the page, its robots.txt and up to two pages the AI surfaces cited, as returned HTML without JavaScript. No site-wide crawl, keyword advice or tracker activation. " + MCP_USAGE_GUIDANCE,
213
213
  inputSchema: import_zod.z.object({
214
214
  requestId: import_zod.z.string().trim().min(1).max(128).optional().describe("A requestId from your own successful Cite42 call within the last 30 days."),
215
215
  trackerRunId: import_zod.z.string().trim().min(1).max(128).optional().describe("A specific finished run of your own tracker within the last 30 days."),
@@ -219,6 +219,9 @@ var aivRecommendations = (0, import_tools.createTool)({
219
219
  result: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()),
220
220
  measuredAt: import_zod.z.string().datetime()
221
221
  })).min(1).max(20).optional(),
222
+ url: import_zod.z.string().trim().url().max(2e3).optional().describe("Your page that should answer the prompt. Without a saved result, url alone runs a free technical check; url with query runs a citations check first."),
223
+ query: import_zod.z.string().trim().min(1).max(2e3).optional().describe("A buyer question. With a saved result it picks one measured prompt; without one it is the question measured."),
224
+ models: import_zod.z.array(modelEnum).nonempty().optional().describe("AI surfaces for the citations check that runs without a saved result. Ignored with a saved result."),
222
225
  context: import_zod.z.object({
223
226
  brand: import_zod.z.string().trim().min(1).max(200).optional(),
224
227
  domain: import_zod.z.string().trim().min(1).max(250).optional(),
@@ -226,8 +229,13 @@ var aivRecommendations = (0, import_tools.createTool)({
226
229
  goal: import_zod.z.string().trim().min(1).max(400).optional()
227
230
  }).optional()
228
231
  }).superRefine((input, ctx) => {
229
- if ([input.requestId, input.trackerRunId, input.evidence].filter((value) => value !== void 0).length !== 1) {
230
- ctx.addIssue({ code: "custom", message: "Provide exactly one of requestId, trackerRunId or evidence." });
232
+ const sources = [input.requestId, input.trackerRunId, input.evidence].filter((value) => value !== void 0).length;
233
+ if (sources > 1) ctx.addIssue({ code: "custom", message: "Provide at most one of requestId, trackerRunId or evidence." });
234
+ if (sources === 0 && !input.url) {
235
+ ctx.addIssue({ code: "custom", message: "Provide requestId, trackerRunId or evidence, or url for a page without saved results." });
236
+ }
237
+ if (sources === 0 && input.query && (input.url?.length ?? 0) > 500) {
238
+ ctx.addIssue({ code: "custom", message: "url must be at most 500 characters to run a citations check." });
231
239
  }
232
240
  if (new TextEncoder().encode(JSON.stringify(input)).length > 64 * 1024) {
233
241
  ctx.addIssue({ code: "custom", message: "Recommendation input must fit within 64KB." });
@@ -695,7 +703,7 @@ if (!resolveApiKey()) {
695
703
  );
696
704
  process.exit(1);
697
705
  }
698
- buildCite42Server("0.6.2").startStdio().catch((error) => {
706
+ buildCite42Server("0.7.0").startStdio().catch((error) => {
699
707
  console.error("[@cite42/mcp] Fatal error:", error);
700
708
  process.exit(1);
701
709
  });
package/dist/stdio.mjs CHANGED
@@ -177,7 +177,7 @@ var SHORT_TEXT_MAX_CHARS = 200;
177
177
  var TIMEFRAME_MAX_CHARS = 80;
178
178
  var MODEL_SELECTION_DESCRIPTION = 'Optional model subset. Omit to query the default surfaces (chatgpt, perplexity, gemini). Pass ["perplexity"] or ["perplexity","claude"] when the user names specific surfaces or wants to reduce cost. The full set is chatgpt, claude, perplexity, gemini, google_ai_overview \u2014 to query all of them, set fullSweep instead of listing them.';
179
179
  var FULL_SWEEP_DESCRIPTION = "Query all five AI surfaces instead of the three default ones, adding claude and google_ai_overview. Costs more per call. Use it when the user wants complete cross-model coverage, is comparing surfaces against each other, or asks specifically about Claude or Google AI Overviews. Ignored when models is given.";
180
- var MCP_USAGE_GUIDANCE = "Covers AI-search, citation, SEO, keyword, trend, and market-research data. If a plan needs more than 20 endpoint calls or may use more than $5 USD, estimate the cost in USD and ask the user before continuing. Quote Cite42 costs and balances in USD using cite42Billing or the USD pricing table. Legacy credit fields are for compatibility only. These funds belong to Cite42, not the host or model provider. AI visibility metrics include counts; quote them with percentages, not as a market-wide score. Optional recommendations are a separate paid call, never automatic. After a visibility result, offer recommendations using its requestId; run only when the user requests advice and knows the additional cost. Free: cite42_balance for the remaining balance, cite42_pricing for exact per-tool prices and cost estimates, cite42_usage for recent calls.";
180
+ var MCP_USAGE_GUIDANCE = "Covers AI-search, citation, SEO, keyword, trend, and market-research data. If a plan needs more than 20 endpoint calls or may use more than $5 USD, estimate the cost in USD and ask the user before continuing. Quote Cite42 costs and balances in USD using cite42Billing or the USD pricing table. Legacy credit fields are for compatibility only. These funds belong to Cite42, not the host or model provider. AI visibility metrics include counts; quote them with percentages, not as a market-wide score. Optional recommendations are a separate paid call, never automatic. Recommendations take the requestId of a visibility result and the page URL, or a page URL alone for a free technical check; they run only when the user requests advice and knows any additional cost. Free: cite42_balance for the remaining balance, cite42_pricing for exact per-tool prices and cost estimates, cite42_usage for recent calls.";
181
181
  var MODEL_PRICING = "Pricing is per selected AI surface. Omitting models queries the three default surfaces (chatgpt, perplexity, gemini); fullSweep: true queries all five, adding claude and google_ai_overview at a higher cost. Use the models field when the user names a surface or asks to reduce spending, and call cite42_pricing for exact current rates.";
182
182
  var DATA_PRICING = "Data tools have flat per-call prices; call cite42_pricing for exact current rates.";
183
183
  var KEYWORDS_PRICING = "Pricing: billed by outcome \u2014 cheapest when the seed has no search volume, more when it has metrics, most with ideas:true. Call cite42_pricing for exact current rates.";
@@ -208,7 +208,7 @@ function shortText(description) {
208
208
  var aivRecommendations = createTool({
209
209
  id: "cite42_recommendations",
210
210
  mcp: readOnly("Recommend AI visibility next steps"),
211
- description: "Optional evidence-backed AI visibility recommendations. Flat price from cite42_pricing per completed AI report; insufficient evidence and rule-only fallback are free. Supports rankings, compare, citations and sentiment, including usable workflow steps. No crawling, fresh research, keyword advice or tracker activation. " + MCP_USAGE_GUIDANCE,
211
+ description: "Page-level AI visibility recommendations. With a saved result (requestId, trackerRunId or evidence) it reports on one measured prompt, charged only when the report includes page-comparison advice backed by quotes from inspected pages. Without one: url alone runs a free technical check of the page (robots.txt crawler access, indexing, rendering) and returns suggested buyer questions; url with query first runs a citations check, priced like cite42_citations, then the report. Prices are in cite42_pricing. Fetches the page, its robots.txt and up to two pages the AI surfaces cited, as returned HTML without JavaScript. No site-wide crawl, keyword advice or tracker activation. " + MCP_USAGE_GUIDANCE,
212
212
  inputSchema: z.object({
213
213
  requestId: z.string().trim().min(1).max(128).optional().describe("A requestId from your own successful Cite42 call within the last 30 days."),
214
214
  trackerRunId: z.string().trim().min(1).max(128).optional().describe("A specific finished run of your own tracker within the last 30 days."),
@@ -218,6 +218,9 @@ var aivRecommendations = createTool({
218
218
  result: z.record(z.string(), z.unknown()),
219
219
  measuredAt: z.string().datetime()
220
220
  })).min(1).max(20).optional(),
221
+ url: z.string().trim().url().max(2e3).optional().describe("Your page that should answer the prompt. Without a saved result, url alone runs a free technical check; url with query runs a citations check first."),
222
+ query: z.string().trim().min(1).max(2e3).optional().describe("A buyer question. With a saved result it picks one measured prompt; without one it is the question measured."),
223
+ models: z.array(modelEnum).nonempty().optional().describe("AI surfaces for the citations check that runs without a saved result. Ignored with a saved result."),
221
224
  context: z.object({
222
225
  brand: z.string().trim().min(1).max(200).optional(),
223
226
  domain: z.string().trim().min(1).max(250).optional(),
@@ -225,8 +228,13 @@ var aivRecommendations = createTool({
225
228
  goal: z.string().trim().min(1).max(400).optional()
226
229
  }).optional()
227
230
  }).superRefine((input, ctx) => {
228
- if ([input.requestId, input.trackerRunId, input.evidence].filter((value) => value !== void 0).length !== 1) {
229
- ctx.addIssue({ code: "custom", message: "Provide exactly one of requestId, trackerRunId or evidence." });
231
+ const sources = [input.requestId, input.trackerRunId, input.evidence].filter((value) => value !== void 0).length;
232
+ if (sources > 1) ctx.addIssue({ code: "custom", message: "Provide at most one of requestId, trackerRunId or evidence." });
233
+ if (sources === 0 && !input.url) {
234
+ ctx.addIssue({ code: "custom", message: "Provide requestId, trackerRunId or evidence, or url for a page without saved results." });
235
+ }
236
+ if (sources === 0 && input.query && (input.url?.length ?? 0) > 500) {
237
+ ctx.addIssue({ code: "custom", message: "url must be at most 500 characters to run a citations check." });
230
238
  }
231
239
  if (new TextEncoder().encode(JSON.stringify(input)).length > 64 * 1024) {
232
240
  ctx.addIssue({ code: "custom", message: "Recommendation input must fit within 64KB." });
@@ -694,7 +702,7 @@ if (!resolveApiKey()) {
694
702
  );
695
703
  process.exit(1);
696
704
  }
697
- buildCite42Server("0.6.2").startStdio().catch((error) => {
705
+ buildCite42Server("0.7.0").startStdio().catch((error) => {
698
706
  console.error("[@cite42/mcp] Fatal error:", error);
699
707
  process.exit(1);
700
708
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cite42/mcp",
3
3
  "mcpName": "dev.cite42/mcp",
4
- "version": "0.6.2",
4
+ "version": "0.7.0",
5
5
  "description": "Cite42 MCP server: AI visibility and SEO data for AI agents. See how the AI models behind ChatGPT, Claude, Perplexity and Gemini, plus Google AI Overviews, mention your brand and which sources they cite, with SEO keyword data, Google, Reddit and YouTube trends, and weekly or monthly trackers that watch a list of prompts over time. Works with Claude Code, Claude Desktop, Codex CLI, Cursor, and any MCP client.",
6
6
  "license": "MIT",
7
7
  "type": "module",