@cite42/mcp 0.1.2 → 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.
- package/README.md +105 -36
- package/dist/stdio.cjs +148 -30
- package/dist/stdio.mjs +148 -30
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,23 +1,39 @@
|
|
|
1
1
|
# @cite42/mcp
|
|
2
2
|
|
|
3
|
-
MCP (Model Context Protocol) server for the [Cite42](https://cite42.dev)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
MCP (Model Context Protocol) server for the [Cite42](https://cite42.dev) API, built on
|
|
4
|
+
[Mastra](https://mastra.ai).
|
|
5
|
+
|
|
6
|
+
Cite42 lets Claude Desktop, Cursor, Claude Code, VS Code, Windsurf, and other MCP clients query
|
|
7
|
+
AI-search visibility, citations, SEO keyword data, Google Trends, Reddit/YouTube signals, and
|
|
8
|
+
creator/agency workflow contracts.
|
|
9
|
+
|
|
10
|
+
This package is a thin MCP client. It forwards tool calls to the hosted Cite42 REST API, so billing,
|
|
11
|
+
metering, provider keys, caching, and rate limits stay server-side.
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- Node.js 18 or newer
|
|
16
|
+
- A Cite42 API key
|
|
17
|
+
- Prepaid Cite42 credits
|
|
18
|
+
|
|
19
|
+
Get an API key from [cite42.dev/app/keys](https://cite42.dev/app/keys). Top up credits at
|
|
20
|
+
[cite42.dev/app/billing](https://cite42.dev/app/billing).
|
|
21
|
+
|
|
22
|
+
Without an API key, the MCP server starts but tool calls cannot reach the Cite42 API.
|
|
8
23
|
|
|
9
24
|
## Install
|
|
10
25
|
|
|
11
|
-
You
|
|
26
|
+
You do not need to install this package globally. Use `npx`; your MCP client will fetch and run the
|
|
27
|
+
latest published version.
|
|
12
28
|
|
|
13
29
|
## Configure Claude Desktop
|
|
14
30
|
|
|
15
31
|
Open your Claude Desktop config:
|
|
16
32
|
|
|
17
|
-
-
|
|
18
|
-
-
|
|
33
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
34
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
19
35
|
|
|
20
|
-
Add the Cite42 MCP server
|
|
36
|
+
Add the Cite42 MCP server:
|
|
21
37
|
|
|
22
38
|
```json
|
|
23
39
|
{
|
|
@@ -30,7 +46,7 @@ Add the Cite42 MCP server (pass your key as an arg — one flat line):
|
|
|
30
46
|
}
|
|
31
47
|
```
|
|
32
48
|
|
|
33
|
-
|
|
49
|
+
You can also pass the key as an environment variable:
|
|
34
50
|
|
|
35
51
|
```json
|
|
36
52
|
{
|
|
@@ -44,44 +60,97 @@ Prefer an environment variable instead? This form works too:
|
|
|
44
60
|
}
|
|
45
61
|
```
|
|
46
62
|
|
|
47
|
-
|
|
48
|
-
key from [cite42.dev/app/keys](https://cite42.dev/app/keys).
|
|
63
|
+
Restart your MCP client after editing the config.
|
|
49
64
|
|
|
50
|
-
|
|
65
|
+
## Configuration
|
|
51
66
|
|
|
52
|
-
|
|
67
|
+
| Setting | Flag | Env var | Default |
|
|
68
|
+
| --- | --- | --- | --- |
|
|
69
|
+
| API key | `--api-key=cite42_live_...` | `CITE42_API_KEY` | Required |
|
|
70
|
+
| API base URL | `--api-base=...` | `CITE42_API_BASE` | `https://api.cite42.dev/v1` |
|
|
53
71
|
|
|
54
|
-
|
|
55
|
-
Run a search query against the AI models and get each model's answer plus the sources it cited.
|
|
72
|
+
Flags win over environment variables when both are set.
|
|
56
73
|
|
|
57
|
-
|
|
58
|
-
Look up which sources the AI models cite for a query — useful for tracking which sites get referenced in AI answers. Optionally check whether a specific URL is cited.
|
|
74
|
+
## Tools
|
|
59
75
|
|
|
60
|
-
|
|
61
|
-
|
|
76
|
+
| Tool | What it does |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| `cite42_search` | Runs a query across ChatGPT, Claude, Perplexity, Gemini, and Google AI Overview, returning answers and cited sources. |
|
|
79
|
+
| `cite42_citations` | Aggregates cited URLs for a query and can check whether a specific URL is cited. |
|
|
80
|
+
| `cite42_rankings` | Measures competitor/brand mention rate, average position, and per-model ranking breakdown. |
|
|
81
|
+
| `cite42_compare` | Compares one brand against competitors, including co-mention data. |
|
|
82
|
+
| `cite42_sentiment` | Scores positive/neutral/negative brand sentiment with supporting phrases. |
|
|
83
|
+
| `cite42_keywords` | Returns search volume, CPC, competition, competition level, and optional curated keyword ideas. |
|
|
84
|
+
| `cite42_trends` | Returns Google Trends interest, related/rising queries, and trend direction. |
|
|
85
|
+
| `cite42_reddit_trends` | Returns Reddit audience questions, pain points, threads, phrases, mentioned products, and URLs. |
|
|
86
|
+
| `cite42_youtube_trends` | Returns YouTube rising videos, creator angles, title patterns, channels, and opportunities. |
|
|
87
|
+
| `cite42_find_content_opportunities` | Combines AI search, SEO keywords, trends, Reddit, YouTube, and citations. |
|
|
88
|
+
| `cite42_analyze_topic_demand` | Combines SEO demand, trends, AI answers, and audience conversations for a topic. |
|
|
89
|
+
| `cite42_map_ai_prompts` | Discovers buyer prompts worth tracking from AI, SEO, trend, Reddit, and YouTube data. |
|
|
90
|
+
| `cite42_analyze_competitor_content` | Combines AI rankings, comparisons, citations, keyword demand, and topic coverage. |
|
|
91
|
+
| `cite42_find_ai_citation_gaps` | Finds AI queries where competitors are cited but your brand/domain/URL is not. |
|
|
92
|
+
| `cite42_generate_content_brief` | Builds brief-ready data from AI answers, citations, SEO demand, trends, Reddit, and YouTube. |
|
|
93
|
+
|
|
94
|
+
## Model Selection
|
|
95
|
+
|
|
96
|
+
The AI-search tools accept an optional `models` array:
|
|
62
97
|
|
|
63
|
-
|
|
64
|
-
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"query": "best customer support software for B2B SaaS",
|
|
101
|
+
"models": ["perplexity", "gemini"]
|
|
102
|
+
}
|
|
103
|
+
```
|
|
65
104
|
|
|
66
|
-
|
|
67
|
-
|
|
105
|
+
Omit `models` to query all five surfaces: `chatgpt`, `claude`, `perplexity`, `gemini`, and
|
|
106
|
+
`google_ai_overview`.
|
|
68
107
|
|
|
69
|
-
|
|
70
|
-
Classic keyword data for a seed term: monthly search volume, CPC, competition, and (optionally) related keyword ideas.
|
|
108
|
+
## Keyword Ideas
|
|
71
109
|
|
|
72
|
-
|
|
73
|
-
Google Trends interest-over-time, related/rising queries, and a rising/falling/stable label for a term.
|
|
110
|
+
`cite42_keywords` can return curated keyword ideas when `ideas` is true:
|
|
74
111
|
|
|
75
|
-
|
|
112
|
+
```json
|
|
113
|
+
{
|
|
114
|
+
"seed": "customer service software",
|
|
115
|
+
"country": "us",
|
|
116
|
+
"ideas": true
|
|
117
|
+
}
|
|
118
|
+
```
|
|
76
119
|
|
|
77
|
-
|
|
78
|
-
wins when both are set.
|
|
120
|
+
Each idea includes provider-backed metrics:
|
|
79
121
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"keyword": "customer support software",
|
|
125
|
+
"volume": 1900,
|
|
126
|
+
"cpc": 116.7,
|
|
127
|
+
"competition": 0.15,
|
|
128
|
+
"competitionLevel": "LOW"
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The curation step selects from provider candidates only; it does not invent new keyword strings.
|
|
84
133
|
|
|
85
134
|
## Pricing
|
|
86
135
|
|
|
87
|
-
Each tool call consumes credits from your Cite42 balance.
|
|
136
|
+
Each successful tool call consumes credits from your Cite42 balance.
|
|
137
|
+
|
|
138
|
+
| Tool group | Price |
|
|
139
|
+
| --- | --- |
|
|
140
|
+
| Search, citations, rankings, compare | Google AI Overview $0.01, Gemini $0.02, ChatGPT/Claude $0.04, Perplexity $0.05 per selected model |
|
|
141
|
+
| Sentiment | Google AI Overview $0.03, Gemini $0.04, ChatGPT/Claude $0.06, Perplexity $0.07 per selected model |
|
|
142
|
+
| Keywords | $0.15 per call |
|
|
143
|
+
| Google Trends | $0.01 per call |
|
|
144
|
+
| Reddit trends | $0.05 per call |
|
|
145
|
+
| YouTube trends | $0.05 per call |
|
|
146
|
+
|
|
147
|
+
Workflow tools are priced from the primitive tools they run. Check the Cite42 dashboard for current
|
|
148
|
+
usage and balance.
|
|
149
|
+
|
|
150
|
+
## Usage Guidance
|
|
151
|
+
|
|
152
|
+
Use Cite42 for AI-search, citation, SEO, keyword, trend, and market-research data. It is not a
|
|
153
|
+
general coding or writing assistant. Code-related research is fine when the goal is to compare what
|
|
154
|
+
AI models recommend or cite.
|
|
155
|
+
|
|
156
|
+
If a task may require many calls or may cost more than a few dollars, ask the user before continuing.
|
package/dist/stdio.cjs
CHANGED
|
@@ -51,83 +51,193 @@ async function aivPost(path, body) {
|
|
|
51
51
|
|
|
52
52
|
// src/tools.ts
|
|
53
53
|
var modelEnum = import_zod.z.enum(["chatgpt", "claude", "perplexity", "gemini", "google_ai_overview"]);
|
|
54
|
+
var QUERY_MAX_CHARS = 2e3;
|
|
55
|
+
var SHORT_TEXT_MAX_CHARS = 200;
|
|
56
|
+
var TIMEFRAME_MAX_CHARS = 80;
|
|
57
|
+
var MODEL_SELECTION_DESCRIPTION = 'Optional model subset. Omit to query all five AI surfaces (chatgpt, claude, perplexity, gemini, google_ai_overview). Pass ["perplexity"] or ["perplexity","claude"] when the user asks for specific surfaces or wants to reduce cost.';
|
|
58
|
+
var MCP_USAGE_GUIDANCE = "Use Cite42 for AI-search, citation, SEO, keyword, trend, and market-research data. Do not use it as a general coding or writing assistant; code-related research is fine when the goal is to compare what AI models recommend or cite. If a plan needs more than 20 endpoint calls or may cost over $5, estimate the cost and ask the user before continuing.";
|
|
59
|
+
var MODEL_PRICING = "Pricing: search/citations/rankings/compare are model-specific: Google AI Overview $0.01, Gemini $0.02, ChatGPT/Claude $0.04, Perplexity $0.05 per selected model. Sentiment: Google AI Overview $0.03, Gemini $0.04, ChatGPT/Claude $0.06, Perplexity $0.07. Omitting models queries all five AI surfaces. Use the models field when the user names a specific surface or asks to reduce cost.";
|
|
60
|
+
var DATA_PRICING = "Pricing: keywords $0.15/call, trends $0.01/call, Reddit trends $0.05/call, YouTube trends $0.05/call.";
|
|
61
|
+
function queryText(description) {
|
|
62
|
+
return import_zod.z.string().trim().min(1).max(QUERY_MAX_CHARS).describe(description);
|
|
63
|
+
}
|
|
64
|
+
function shortText(description) {
|
|
65
|
+
return import_zod.z.string().trim().min(1).max(SHORT_TEXT_MAX_CHARS).describe(description);
|
|
66
|
+
}
|
|
67
|
+
function optionalShortText(description) {
|
|
68
|
+
return import_zod.z.string().trim().min(1).max(SHORT_TEXT_MAX_CHARS).optional().describe(description);
|
|
69
|
+
}
|
|
70
|
+
var modelsInput = import_zod.z.array(modelEnum).nonempty().optional().describe(MODEL_SELECTION_DESCRIPTION);
|
|
71
|
+
var competitorList = import_zod.z.array(shortText("Competitor brand/domain name.")).nonempty().max(20);
|
|
54
72
|
var aivSearch = (0, import_tools.createTool)({
|
|
55
73
|
id: "cite42_search",
|
|
56
|
-
description:
|
|
74
|
+
description: `Run a query against AI models (ChatGPT, Claude, Perplexity, Gemini, and Google AI Overviews) and return each model's answer along with the sources it cited. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
57
75
|
inputSchema: import_zod.z.object({
|
|
58
|
-
query:
|
|
59
|
-
models:
|
|
76
|
+
query: queryText("The concise AI-search/market-research query to run against the selected models."),
|
|
77
|
+
models: modelsInput
|
|
60
78
|
}),
|
|
61
79
|
execute: async (input) => aivPost("/search", input)
|
|
62
80
|
});
|
|
63
81
|
var aivCitations = (0, import_tools.createTool)({
|
|
64
82
|
id: "cite42_citations",
|
|
65
|
-
description:
|
|
83
|
+
description: `Find which sources AI models cite for a query. Aggregates cited URLs across models with per-model counts; optionally checks whether a specific URL is cited. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
66
84
|
inputSchema: import_zod.z.object({
|
|
67
|
-
query:
|
|
68
|
-
url: import_zod.z.string().optional().describe("Optional URL to check whether it was cited."),
|
|
69
|
-
models:
|
|
85
|
+
query: queryText("The concise query to look up cited sources for."),
|
|
86
|
+
url: import_zod.z.string().trim().max(500).optional().describe("Optional URL to check whether it was cited."),
|
|
87
|
+
models: modelsInput
|
|
70
88
|
}),
|
|
71
89
|
execute: async (input) => aivPost("/citations", input)
|
|
72
90
|
});
|
|
73
91
|
var aivRankings = (0, import_tools.createTool)({
|
|
74
92
|
id: "cite42_rankings",
|
|
75
|
-
description:
|
|
93
|
+
description: `Measure how a set of brands/competitors rank in AI answers for a query: mention rate, average position, and a per-model breakdown across ChatGPT, Claude, Perplexity, Gemini, and Google AI Overviews. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
76
94
|
inputSchema: import_zod.z.object({
|
|
77
|
-
query:
|
|
78
|
-
competitors:
|
|
79
|
-
models:
|
|
95
|
+
query: queryText("The concise query to measure brand/competitor visibility on."),
|
|
96
|
+
competitors: competitorList.describe("Brand or domain names to track within the AI-generated answers."),
|
|
97
|
+
models: modelsInput
|
|
80
98
|
}),
|
|
81
99
|
execute: async (input) => aivPost("/rankings", input)
|
|
82
100
|
});
|
|
83
101
|
var aivCompare = (0, import_tools.createTool)({
|
|
84
102
|
id: "cite42_compare",
|
|
85
|
-
description:
|
|
103
|
+
description: `Compare one primary brand head-to-head against a competitor set in AI answers: per-brand rankings plus a co-mention graph of which brands the models name together. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
86
104
|
inputSchema: import_zod.z.object({
|
|
87
|
-
query:
|
|
88
|
-
brand:
|
|
89
|
-
competitors: import_zod.z.array(
|
|
90
|
-
models:
|
|
105
|
+
query: queryText("The concise query to compare the brand and competitors on."),
|
|
106
|
+
brand: shortText("Your brand, ranked alongside the competitors."),
|
|
107
|
+
competitors: import_zod.z.array(shortText("Competitor brand/domain name.")).nonempty().max(10).describe("Competitor brand/domain names (up to 10) to rank against your brand."),
|
|
108
|
+
models: modelsInput
|
|
91
109
|
}),
|
|
92
110
|
execute: async (input) => aivPost("/compare", input)
|
|
93
111
|
});
|
|
94
112
|
var aivSentiment = (0, import_tools.createTool)({
|
|
95
113
|
id: "cite42_sentiment",
|
|
96
|
-
description:
|
|
114
|
+
description: `Score how each AI model talks about a brand for a query: a positive/neutral/negative split per model with the verbatim phrases driving the tone, plus an aggregate across models. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
97
115
|
inputSchema: import_zod.z.object({
|
|
98
|
-
query:
|
|
99
|
-
brand:
|
|
100
|
-
models:
|
|
116
|
+
query: queryText("The concise query whose answers are scored for brand sentiment."),
|
|
117
|
+
brand: shortText("The brand to score sentiment for in each model answer."),
|
|
118
|
+
models: modelsInput
|
|
101
119
|
}),
|
|
102
120
|
execute: async (input) => aivPost("/sentiment", input)
|
|
103
121
|
});
|
|
104
122
|
var aivKeywords = (0, import_tools.createTool)({
|
|
105
123
|
id: "cite42_keywords",
|
|
106
|
-
description:
|
|
124
|
+
description: `Classic keyword data for a seed term: monthly search volume, CPC, competition, and (optionally) LLM-curated related keyword ideas with volume, CPC, competition, and competition level from provider candidates. A flat-priced data tool, not a multi-model AI-search query. ${DATA_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
107
125
|
inputSchema: import_zod.z.object({
|
|
108
|
-
seed:
|
|
109
|
-
country: import_zod.z.string().optional().describe('ISO-2 country code for localized metrics. Defaults to "us".'),
|
|
110
|
-
ideas: import_zod.z.boolean().optional().describe("When true, also return related keyword ideas with
|
|
126
|
+
seed: queryText("Seed keyword or concise topic to fetch search volume, CPC, and competition for."),
|
|
127
|
+
country: import_zod.z.string().trim().max(8).optional().describe('ISO-2 country code for localized metrics. Defaults to "us".'),
|
|
128
|
+
ideas: import_zod.z.boolean().optional().describe("When true, also return LLM-curated related keyword ideas with volume, CPC, competition, and competition level.")
|
|
111
129
|
}),
|
|
112
130
|
execute: async (input) => aivPost("/keywords", input)
|
|
113
131
|
});
|
|
114
132
|
var aivTrends = (0, import_tools.createTool)({
|
|
115
133
|
id: "cite42_trends",
|
|
116
|
-
description:
|
|
134
|
+
description: `Google Trends interest-over-time, related and rising queries, and a rising/falling/stable label for a term. A flat-priced data tool, not an AI-model query. ${DATA_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
117
135
|
inputSchema: import_zod.z.object({
|
|
118
|
-
term:
|
|
119
|
-
timeframe: import_zod.z.string().optional().describe('Trends window, e.g. "past_12_months", "past_30_days", "past_5_years".'),
|
|
120
|
-
geo: import_zod.z.string().optional().describe('Optional location name (e.g. "United States"). Worldwide when omitted.')
|
|
136
|
+
term: queryText("Search term or concise topic to pull Google Trends interest-over-time for."),
|
|
137
|
+
timeframe: import_zod.z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Trends window, e.g. "past_12_months", "past_30_days", "past_5_years".'),
|
|
138
|
+
geo: import_zod.z.string().trim().max(SHORT_TEXT_MAX_CHARS).optional().describe('Optional location name (e.g. "United States"). Worldwide when omitted.')
|
|
121
139
|
}),
|
|
122
140
|
execute: async (input) => aivPost("/trends", input)
|
|
123
141
|
});
|
|
142
|
+
var aivRedditTrends = (0, import_tools.createTool)({
|
|
143
|
+
id: "cite42_reddit_trends",
|
|
144
|
+
description: `Reddit trend data for audience questions, pain points, rising threads, repeated phrases, mentioned products, and source URLs around a topic. ${DATA_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
145
|
+
inputSchema: import_zod.z.object({
|
|
146
|
+
topic: queryText("Topic, category, product, or audience to research on Reddit."),
|
|
147
|
+
subreddits: import_zod.z.array(shortText("Subreddit name without r/.")).max(20).optional().describe("Optional subreddit names, without r/."),
|
|
148
|
+
timeframe: import_zod.z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Conversation window, e.g. "past_7_days", "past_30_days", "past_90_days".')
|
|
149
|
+
}),
|
|
150
|
+
execute: async (input) => aivPost("/reddit/trends", input)
|
|
151
|
+
});
|
|
152
|
+
var aivYoutubeTrends = (0, import_tools.createTool)({
|
|
153
|
+
id: "cite42_youtube_trends",
|
|
154
|
+
description: `YouTube trend data for rising videos, creator angles, title patterns, channel examples, and video-market opportunities around a topic. ${DATA_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
155
|
+
inputSchema: import_zod.z.object({
|
|
156
|
+
topic: queryText("Topic, keyword, niche, or audience to research on YouTube."),
|
|
157
|
+
region: import_zod.z.string().trim().max(8).optional().describe('ISO-2 country/region code. Defaults to "US".'),
|
|
158
|
+
timeframe: import_zod.z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Video-market window, e.g. "past_7_days", "past_30_days", "past_90_days".')
|
|
159
|
+
}),
|
|
160
|
+
execute: async (input) => aivPost("/youtube/trends", input)
|
|
161
|
+
});
|
|
162
|
+
var channelEnum = import_zod.z.enum(["ai_search", "seo_keywords", "google_trends", "reddit", "youtube"]);
|
|
163
|
+
var aivFindContentOpportunities = (0, import_tools.createTool)({
|
|
164
|
+
id: "cite42_find_content_opportunities",
|
|
165
|
+
description: `Run the content-opportunities workflow: fans out across AI search, SEO keywords, trends, Reddit, YouTube, and citations and returns the aggregated data in one response. ${MCP_USAGE_GUIDANCE}`,
|
|
166
|
+
inputSchema: import_zod.z.object({
|
|
167
|
+
topic: queryText("Market, niche, product category, or audience to research."),
|
|
168
|
+
audience: optionalShortText("Optional target audience or ICP."),
|
|
169
|
+
brand: optionalShortText("Optional brand/domain to account for."),
|
|
170
|
+
competitors: competitorList.optional().describe("Competitor brands/domains."),
|
|
171
|
+
country: import_zod.z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".'),
|
|
172
|
+
channels: import_zod.z.array(channelEnum).optional().describe("Optional data sources to include.")
|
|
173
|
+
}),
|
|
174
|
+
execute: async (input) => aivPost("/workflows/content-opportunities", input)
|
|
175
|
+
});
|
|
176
|
+
var aivAnalyzeTopicDemand = (0, import_tools.createTool)({
|
|
177
|
+
id: "cite42_analyze_topic_demand",
|
|
178
|
+
description: `Run the topic-demand workflow: SEO keyword data, Google Trends, AI answers, and audience conversations, aggregated in one response. ${MCP_USAGE_GUIDANCE}`,
|
|
179
|
+
inputSchema: import_zod.z.object({
|
|
180
|
+
topic: queryText("Topic, keyword, category, or audience demand to analyze."),
|
|
181
|
+
country: import_zod.z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".'),
|
|
182
|
+
timeframe: import_zod.z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Trend window. Defaults to "past_12_months".')
|
|
183
|
+
}),
|
|
184
|
+
execute: async (input) => aivPost("/workflows/topic-demand", input)
|
|
185
|
+
});
|
|
186
|
+
var aivMapAiPrompts = (0, import_tools.createTool)({
|
|
187
|
+
id: "cite42_map_ai_prompts",
|
|
188
|
+
description: `Run the AI-prompt-map workflow: discover and cluster buyer prompts worth tracking from AI search, SEO demand, trends, citations, Reddit, and YouTube data. ${MCP_USAGE_GUIDANCE}`,
|
|
189
|
+
inputSchema: import_zod.z.object({
|
|
190
|
+
topic: queryText("Market, product category, buyer problem, or audience to map prompts for."),
|
|
191
|
+
audience: optionalShortText("Optional target audience or ICP."),
|
|
192
|
+
brand: optionalShortText("Optional brand/domain to include in prompt tracking recommendations."),
|
|
193
|
+
competitors: competitorList.optional().describe("Competitor brands/domains."),
|
|
194
|
+
country: import_zod.z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".'),
|
|
195
|
+
timeframe: import_zod.z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Trend window. Defaults to "past_12_months".')
|
|
196
|
+
}),
|
|
197
|
+
execute: async (input) => aivPost("/workflows/ai-prompt-map", input)
|
|
198
|
+
});
|
|
199
|
+
var aivAnalyzeCompetitorContent = (0, import_tools.createTool)({
|
|
200
|
+
id: "cite42_analyze_competitor_content",
|
|
201
|
+
description: `Run the competitor-content workflow: AI rankings, head-to-head comparison, citations, keyword demand, and topic coverage, aggregated in one response. ${MCP_USAGE_GUIDANCE}`,
|
|
202
|
+
inputSchema: import_zod.z.object({
|
|
203
|
+
competitors: competitorList.describe("Competitor brands, domains, or channels to analyze."),
|
|
204
|
+
topic: import_zod.z.string().trim().min(1).max(QUERY_MAX_CHARS).optional().describe("Optional topic/category to constrain the analysis."),
|
|
205
|
+
brand: optionalShortText("Optional primary brand/domain to compare against."),
|
|
206
|
+
country: import_zod.z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".')
|
|
207
|
+
}),
|
|
208
|
+
execute: async (input) => aivPost("/workflows/competitor-content", input)
|
|
209
|
+
});
|
|
210
|
+
var aivFindAiCitationGaps = (0, import_tools.createTool)({
|
|
211
|
+
id: "cite42_find_ai_citation_gaps",
|
|
212
|
+
description: `Run the AI-citation-gaps workflow: find queries where AI answers cite others but not your brand, domain, or URL, with the supporting data. ${MCP_USAGE_GUIDANCE}`,
|
|
213
|
+
inputSchema: import_zod.z.object({
|
|
214
|
+
query: queryText("AI-search query to inspect for citation gaps."),
|
|
215
|
+
brand: shortText("Brand or domain that should earn citations."),
|
|
216
|
+
url: import_zod.z.string().trim().max(500).optional().describe("Optional exact URL to check for citations."),
|
|
217
|
+
competitors: competitorList.optional().describe("Competitor brands/domains."),
|
|
218
|
+
models: modelsInput
|
|
219
|
+
}),
|
|
220
|
+
execute: async (input) => aivPost("/workflows/ai-citation-gaps", input)
|
|
221
|
+
});
|
|
222
|
+
var aivGenerateContentBrief = (0, import_tools.createTool)({
|
|
223
|
+
id: "cite42_generate_content_brief",
|
|
224
|
+
description: `Run the content-brief workflow: AI answers, citations, SEO keyword demand, trends, Reddit, and YouTube signals aggregated into brief-ready data. ${MCP_USAGE_GUIDANCE}`,
|
|
225
|
+
inputSchema: import_zod.z.object({
|
|
226
|
+
topic: queryText("Topic, keyword, or content idea to brief."),
|
|
227
|
+
audience: optionalShortText("Optional target audience or ICP."),
|
|
228
|
+
brand: optionalShortText("Optional brand/domain the brief is for."),
|
|
229
|
+
goal: optionalShortText("Optional content goal, e.g. rank, earn citations, convert."),
|
|
230
|
+
country: import_zod.z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".')
|
|
231
|
+
}),
|
|
232
|
+
execute: async (input) => aivPost("/workflows/content-brief", input)
|
|
233
|
+
});
|
|
124
234
|
|
|
125
235
|
// src/stdio.ts
|
|
126
236
|
var server = new import_mcp.MCPServer({
|
|
127
237
|
id: "cite42",
|
|
128
238
|
name: "Cite42",
|
|
129
239
|
version: "0.1.0",
|
|
130
|
-
description: "AI
|
|
240
|
+
description: "AI market data API: AI search, citations, SEO keywords, trends, and workflows.",
|
|
131
241
|
tools: {
|
|
132
242
|
cite42_search: aivSearch,
|
|
133
243
|
cite42_rankings: aivRankings,
|
|
@@ -135,7 +245,15 @@ var server = new import_mcp.MCPServer({
|
|
|
135
245
|
cite42_citations: aivCitations,
|
|
136
246
|
cite42_sentiment: aivSentiment,
|
|
137
247
|
cite42_keywords: aivKeywords,
|
|
138
|
-
cite42_trends: aivTrends
|
|
248
|
+
cite42_trends: aivTrends,
|
|
249
|
+
cite42_reddit_trends: aivRedditTrends,
|
|
250
|
+
cite42_youtube_trends: aivYoutubeTrends,
|
|
251
|
+
cite42_find_content_opportunities: aivFindContentOpportunities,
|
|
252
|
+
cite42_analyze_topic_demand: aivAnalyzeTopicDemand,
|
|
253
|
+
cite42_map_ai_prompts: aivMapAiPrompts,
|
|
254
|
+
cite42_analyze_competitor_content: aivAnalyzeCompetitorContent,
|
|
255
|
+
cite42_find_ai_citation_gaps: aivFindAiCitationGaps,
|
|
256
|
+
cite42_generate_content_brief: aivGenerateContentBrief
|
|
139
257
|
}
|
|
140
258
|
});
|
|
141
259
|
server.startStdio().catch((error) => {
|
package/dist/stdio.mjs
CHANGED
|
@@ -50,83 +50,193 @@ async function aivPost(path, body) {
|
|
|
50
50
|
|
|
51
51
|
// src/tools.ts
|
|
52
52
|
var modelEnum = z.enum(["chatgpt", "claude", "perplexity", "gemini", "google_ai_overview"]);
|
|
53
|
+
var QUERY_MAX_CHARS = 2e3;
|
|
54
|
+
var SHORT_TEXT_MAX_CHARS = 200;
|
|
55
|
+
var TIMEFRAME_MAX_CHARS = 80;
|
|
56
|
+
var MODEL_SELECTION_DESCRIPTION = 'Optional model subset. Omit to query all five AI surfaces (chatgpt, claude, perplexity, gemini, google_ai_overview). Pass ["perplexity"] or ["perplexity","claude"] when the user asks for specific surfaces or wants to reduce cost.';
|
|
57
|
+
var MCP_USAGE_GUIDANCE = "Use Cite42 for AI-search, citation, SEO, keyword, trend, and market-research data. Do not use it as a general coding or writing assistant; code-related research is fine when the goal is to compare what AI models recommend or cite. If a plan needs more than 20 endpoint calls or may cost over $5, estimate the cost and ask the user before continuing.";
|
|
58
|
+
var MODEL_PRICING = "Pricing: search/citations/rankings/compare are model-specific: Google AI Overview $0.01, Gemini $0.02, ChatGPT/Claude $0.04, Perplexity $0.05 per selected model. Sentiment: Google AI Overview $0.03, Gemini $0.04, ChatGPT/Claude $0.06, Perplexity $0.07. Omitting models queries all five AI surfaces. Use the models field when the user names a specific surface or asks to reduce cost.";
|
|
59
|
+
var DATA_PRICING = "Pricing: keywords $0.15/call, trends $0.01/call, Reddit trends $0.05/call, YouTube trends $0.05/call.";
|
|
60
|
+
function queryText(description) {
|
|
61
|
+
return z.string().trim().min(1).max(QUERY_MAX_CHARS).describe(description);
|
|
62
|
+
}
|
|
63
|
+
function shortText(description) {
|
|
64
|
+
return z.string().trim().min(1).max(SHORT_TEXT_MAX_CHARS).describe(description);
|
|
65
|
+
}
|
|
66
|
+
function optionalShortText(description) {
|
|
67
|
+
return z.string().trim().min(1).max(SHORT_TEXT_MAX_CHARS).optional().describe(description);
|
|
68
|
+
}
|
|
69
|
+
var modelsInput = z.array(modelEnum).nonempty().optional().describe(MODEL_SELECTION_DESCRIPTION);
|
|
70
|
+
var competitorList = z.array(shortText("Competitor brand/domain name.")).nonempty().max(20);
|
|
53
71
|
var aivSearch = createTool({
|
|
54
72
|
id: "cite42_search",
|
|
55
|
-
description:
|
|
73
|
+
description: `Run a query against AI models (ChatGPT, Claude, Perplexity, Gemini, and Google AI Overviews) and return each model's answer along with the sources it cited. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
56
74
|
inputSchema: z.object({
|
|
57
|
-
query:
|
|
58
|
-
models:
|
|
75
|
+
query: queryText("The concise AI-search/market-research query to run against the selected models."),
|
|
76
|
+
models: modelsInput
|
|
59
77
|
}),
|
|
60
78
|
execute: async (input) => aivPost("/search", input)
|
|
61
79
|
});
|
|
62
80
|
var aivCitations = createTool({
|
|
63
81
|
id: "cite42_citations",
|
|
64
|
-
description:
|
|
82
|
+
description: `Find which sources AI models cite for a query. Aggregates cited URLs across models with per-model counts; optionally checks whether a specific URL is cited. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
65
83
|
inputSchema: z.object({
|
|
66
|
-
query:
|
|
67
|
-
url: z.string().optional().describe("Optional URL to check whether it was cited."),
|
|
68
|
-
models:
|
|
84
|
+
query: queryText("The concise query to look up cited sources for."),
|
|
85
|
+
url: z.string().trim().max(500).optional().describe("Optional URL to check whether it was cited."),
|
|
86
|
+
models: modelsInput
|
|
69
87
|
}),
|
|
70
88
|
execute: async (input) => aivPost("/citations", input)
|
|
71
89
|
});
|
|
72
90
|
var aivRankings = createTool({
|
|
73
91
|
id: "cite42_rankings",
|
|
74
|
-
description:
|
|
92
|
+
description: `Measure how a set of brands/competitors rank in AI answers for a query: mention rate, average position, and a per-model breakdown across ChatGPT, Claude, Perplexity, Gemini, and Google AI Overviews. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
75
93
|
inputSchema: z.object({
|
|
76
|
-
query:
|
|
77
|
-
competitors:
|
|
78
|
-
models:
|
|
94
|
+
query: queryText("The concise query to measure brand/competitor visibility on."),
|
|
95
|
+
competitors: competitorList.describe("Brand or domain names to track within the AI-generated answers."),
|
|
96
|
+
models: modelsInput
|
|
79
97
|
}),
|
|
80
98
|
execute: async (input) => aivPost("/rankings", input)
|
|
81
99
|
});
|
|
82
100
|
var aivCompare = createTool({
|
|
83
101
|
id: "cite42_compare",
|
|
84
|
-
description:
|
|
102
|
+
description: `Compare one primary brand head-to-head against a competitor set in AI answers: per-brand rankings plus a co-mention graph of which brands the models name together. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
85
103
|
inputSchema: z.object({
|
|
86
|
-
query:
|
|
87
|
-
brand:
|
|
88
|
-
competitors: z.array(
|
|
89
|
-
models:
|
|
104
|
+
query: queryText("The concise query to compare the brand and competitors on."),
|
|
105
|
+
brand: shortText("Your brand, ranked alongside the competitors."),
|
|
106
|
+
competitors: z.array(shortText("Competitor brand/domain name.")).nonempty().max(10).describe("Competitor brand/domain names (up to 10) to rank against your brand."),
|
|
107
|
+
models: modelsInput
|
|
90
108
|
}),
|
|
91
109
|
execute: async (input) => aivPost("/compare", input)
|
|
92
110
|
});
|
|
93
111
|
var aivSentiment = createTool({
|
|
94
112
|
id: "cite42_sentiment",
|
|
95
|
-
description:
|
|
113
|
+
description: `Score how each AI model talks about a brand for a query: a positive/neutral/negative split per model with the verbatim phrases driving the tone, plus an aggregate across models. ${MODEL_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
96
114
|
inputSchema: z.object({
|
|
97
|
-
query:
|
|
98
|
-
brand:
|
|
99
|
-
models:
|
|
115
|
+
query: queryText("The concise query whose answers are scored for brand sentiment."),
|
|
116
|
+
brand: shortText("The brand to score sentiment for in each model answer."),
|
|
117
|
+
models: modelsInput
|
|
100
118
|
}),
|
|
101
119
|
execute: async (input) => aivPost("/sentiment", input)
|
|
102
120
|
});
|
|
103
121
|
var aivKeywords = createTool({
|
|
104
122
|
id: "cite42_keywords",
|
|
105
|
-
description:
|
|
123
|
+
description: `Classic keyword data for a seed term: monthly search volume, CPC, competition, and (optionally) LLM-curated related keyword ideas with volume, CPC, competition, and competition level from provider candidates. A flat-priced data tool, not a multi-model AI-search query. ${DATA_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
106
124
|
inputSchema: z.object({
|
|
107
|
-
seed:
|
|
108
|
-
country: z.string().optional().describe('ISO-2 country code for localized metrics. Defaults to "us".'),
|
|
109
|
-
ideas: z.boolean().optional().describe("When true, also return related keyword ideas with
|
|
125
|
+
seed: queryText("Seed keyword or concise topic to fetch search volume, CPC, and competition for."),
|
|
126
|
+
country: z.string().trim().max(8).optional().describe('ISO-2 country code for localized metrics. Defaults to "us".'),
|
|
127
|
+
ideas: z.boolean().optional().describe("When true, also return LLM-curated related keyword ideas with volume, CPC, competition, and competition level.")
|
|
110
128
|
}),
|
|
111
129
|
execute: async (input) => aivPost("/keywords", input)
|
|
112
130
|
});
|
|
113
131
|
var aivTrends = createTool({
|
|
114
132
|
id: "cite42_trends",
|
|
115
|
-
description:
|
|
133
|
+
description: `Google Trends interest-over-time, related and rising queries, and a rising/falling/stable label for a term. A flat-priced data tool, not an AI-model query. ${DATA_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
116
134
|
inputSchema: z.object({
|
|
117
|
-
term:
|
|
118
|
-
timeframe: z.string().optional().describe('Trends window, e.g. "past_12_months", "past_30_days", "past_5_years".'),
|
|
119
|
-
geo: z.string().optional().describe('Optional location name (e.g. "United States"). Worldwide when omitted.')
|
|
135
|
+
term: queryText("Search term or concise topic to pull Google Trends interest-over-time for."),
|
|
136
|
+
timeframe: z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Trends window, e.g. "past_12_months", "past_30_days", "past_5_years".'),
|
|
137
|
+
geo: z.string().trim().max(SHORT_TEXT_MAX_CHARS).optional().describe('Optional location name (e.g. "United States"). Worldwide when omitted.')
|
|
120
138
|
}),
|
|
121
139
|
execute: async (input) => aivPost("/trends", input)
|
|
122
140
|
});
|
|
141
|
+
var aivRedditTrends = createTool({
|
|
142
|
+
id: "cite42_reddit_trends",
|
|
143
|
+
description: `Reddit trend data for audience questions, pain points, rising threads, repeated phrases, mentioned products, and source URLs around a topic. ${DATA_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
144
|
+
inputSchema: z.object({
|
|
145
|
+
topic: queryText("Topic, category, product, or audience to research on Reddit."),
|
|
146
|
+
subreddits: z.array(shortText("Subreddit name without r/.")).max(20).optional().describe("Optional subreddit names, without r/."),
|
|
147
|
+
timeframe: z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Conversation window, e.g. "past_7_days", "past_30_days", "past_90_days".')
|
|
148
|
+
}),
|
|
149
|
+
execute: async (input) => aivPost("/reddit/trends", input)
|
|
150
|
+
});
|
|
151
|
+
var aivYoutubeTrends = createTool({
|
|
152
|
+
id: "cite42_youtube_trends",
|
|
153
|
+
description: `YouTube trend data for rising videos, creator angles, title patterns, channel examples, and video-market opportunities around a topic. ${DATA_PRICING} ${MCP_USAGE_GUIDANCE}`,
|
|
154
|
+
inputSchema: z.object({
|
|
155
|
+
topic: queryText("Topic, keyword, niche, or audience to research on YouTube."),
|
|
156
|
+
region: z.string().trim().max(8).optional().describe('ISO-2 country/region code. Defaults to "US".'),
|
|
157
|
+
timeframe: z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Video-market window, e.g. "past_7_days", "past_30_days", "past_90_days".')
|
|
158
|
+
}),
|
|
159
|
+
execute: async (input) => aivPost("/youtube/trends", input)
|
|
160
|
+
});
|
|
161
|
+
var channelEnum = z.enum(["ai_search", "seo_keywords", "google_trends", "reddit", "youtube"]);
|
|
162
|
+
var aivFindContentOpportunities = createTool({
|
|
163
|
+
id: "cite42_find_content_opportunities",
|
|
164
|
+
description: `Run the content-opportunities workflow: fans out across AI search, SEO keywords, trends, Reddit, YouTube, and citations and returns the aggregated data in one response. ${MCP_USAGE_GUIDANCE}`,
|
|
165
|
+
inputSchema: z.object({
|
|
166
|
+
topic: queryText("Market, niche, product category, or audience to research."),
|
|
167
|
+
audience: optionalShortText("Optional target audience or ICP."),
|
|
168
|
+
brand: optionalShortText("Optional brand/domain to account for."),
|
|
169
|
+
competitors: competitorList.optional().describe("Competitor brands/domains."),
|
|
170
|
+
country: z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".'),
|
|
171
|
+
channels: z.array(channelEnum).optional().describe("Optional data sources to include.")
|
|
172
|
+
}),
|
|
173
|
+
execute: async (input) => aivPost("/workflows/content-opportunities", input)
|
|
174
|
+
});
|
|
175
|
+
var aivAnalyzeTopicDemand = createTool({
|
|
176
|
+
id: "cite42_analyze_topic_demand",
|
|
177
|
+
description: `Run the topic-demand workflow: SEO keyword data, Google Trends, AI answers, and audience conversations, aggregated in one response. ${MCP_USAGE_GUIDANCE}`,
|
|
178
|
+
inputSchema: z.object({
|
|
179
|
+
topic: queryText("Topic, keyword, category, or audience demand to analyze."),
|
|
180
|
+
country: z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".'),
|
|
181
|
+
timeframe: z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Trend window. Defaults to "past_12_months".')
|
|
182
|
+
}),
|
|
183
|
+
execute: async (input) => aivPost("/workflows/topic-demand", input)
|
|
184
|
+
});
|
|
185
|
+
var aivMapAiPrompts = createTool({
|
|
186
|
+
id: "cite42_map_ai_prompts",
|
|
187
|
+
description: `Run the AI-prompt-map workflow: discover and cluster buyer prompts worth tracking from AI search, SEO demand, trends, citations, Reddit, and YouTube data. ${MCP_USAGE_GUIDANCE}`,
|
|
188
|
+
inputSchema: z.object({
|
|
189
|
+
topic: queryText("Market, product category, buyer problem, or audience to map prompts for."),
|
|
190
|
+
audience: optionalShortText("Optional target audience or ICP."),
|
|
191
|
+
brand: optionalShortText("Optional brand/domain to include in prompt tracking recommendations."),
|
|
192
|
+
competitors: competitorList.optional().describe("Competitor brands/domains."),
|
|
193
|
+
country: z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".'),
|
|
194
|
+
timeframe: z.string().trim().max(TIMEFRAME_MAX_CHARS).optional().describe('Trend window. Defaults to "past_12_months".')
|
|
195
|
+
}),
|
|
196
|
+
execute: async (input) => aivPost("/workflows/ai-prompt-map", input)
|
|
197
|
+
});
|
|
198
|
+
var aivAnalyzeCompetitorContent = createTool({
|
|
199
|
+
id: "cite42_analyze_competitor_content",
|
|
200
|
+
description: `Run the competitor-content workflow: AI rankings, head-to-head comparison, citations, keyword demand, and topic coverage, aggregated in one response. ${MCP_USAGE_GUIDANCE}`,
|
|
201
|
+
inputSchema: z.object({
|
|
202
|
+
competitors: competitorList.describe("Competitor brands, domains, or channels to analyze."),
|
|
203
|
+
topic: z.string().trim().min(1).max(QUERY_MAX_CHARS).optional().describe("Optional topic/category to constrain the analysis."),
|
|
204
|
+
brand: optionalShortText("Optional primary brand/domain to compare against."),
|
|
205
|
+
country: z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".')
|
|
206
|
+
}),
|
|
207
|
+
execute: async (input) => aivPost("/workflows/competitor-content", input)
|
|
208
|
+
});
|
|
209
|
+
var aivFindAiCitationGaps = createTool({
|
|
210
|
+
id: "cite42_find_ai_citation_gaps",
|
|
211
|
+
description: `Run the AI-citation-gaps workflow: find queries where AI answers cite others but not your brand, domain, or URL, with the supporting data. ${MCP_USAGE_GUIDANCE}`,
|
|
212
|
+
inputSchema: z.object({
|
|
213
|
+
query: queryText("AI-search query to inspect for citation gaps."),
|
|
214
|
+
brand: shortText("Brand or domain that should earn citations."),
|
|
215
|
+
url: z.string().trim().max(500).optional().describe("Optional exact URL to check for citations."),
|
|
216
|
+
competitors: competitorList.optional().describe("Competitor brands/domains."),
|
|
217
|
+
models: modelsInput
|
|
218
|
+
}),
|
|
219
|
+
execute: async (input) => aivPost("/workflows/ai-citation-gaps", input)
|
|
220
|
+
});
|
|
221
|
+
var aivGenerateContentBrief = createTool({
|
|
222
|
+
id: "cite42_generate_content_brief",
|
|
223
|
+
description: `Run the content-brief workflow: AI answers, citations, SEO keyword demand, trends, Reddit, and YouTube signals aggregated into brief-ready data. ${MCP_USAGE_GUIDANCE}`,
|
|
224
|
+
inputSchema: z.object({
|
|
225
|
+
topic: queryText("Topic, keyword, or content idea to brief."),
|
|
226
|
+
audience: optionalShortText("Optional target audience or ICP."),
|
|
227
|
+
brand: optionalShortText("Optional brand/domain the brief is for."),
|
|
228
|
+
goal: optionalShortText("Optional content goal, e.g. rank, earn citations, convert."),
|
|
229
|
+
country: z.string().trim().max(8).optional().describe('ISO-2 country code. Defaults to "us".')
|
|
230
|
+
}),
|
|
231
|
+
execute: async (input) => aivPost("/workflows/content-brief", input)
|
|
232
|
+
});
|
|
123
233
|
|
|
124
234
|
// src/stdio.ts
|
|
125
235
|
var server = new MCPServer({
|
|
126
236
|
id: "cite42",
|
|
127
237
|
name: "Cite42",
|
|
128
238
|
version: "0.1.0",
|
|
129
|
-
description: "AI
|
|
239
|
+
description: "AI market data API: AI search, citations, SEO keywords, trends, and workflows.",
|
|
130
240
|
tools: {
|
|
131
241
|
cite42_search: aivSearch,
|
|
132
242
|
cite42_rankings: aivRankings,
|
|
@@ -134,7 +244,15 @@ var server = new MCPServer({
|
|
|
134
244
|
cite42_citations: aivCitations,
|
|
135
245
|
cite42_sentiment: aivSentiment,
|
|
136
246
|
cite42_keywords: aivKeywords,
|
|
137
|
-
cite42_trends: aivTrends
|
|
247
|
+
cite42_trends: aivTrends,
|
|
248
|
+
cite42_reddit_trends: aivRedditTrends,
|
|
249
|
+
cite42_youtube_trends: aivYoutubeTrends,
|
|
250
|
+
cite42_find_content_opportunities: aivFindContentOpportunities,
|
|
251
|
+
cite42_analyze_topic_demand: aivAnalyzeTopicDemand,
|
|
252
|
+
cite42_map_ai_prompts: aivMapAiPrompts,
|
|
253
|
+
cite42_analyze_competitor_content: aivAnalyzeCompetitorContent,
|
|
254
|
+
cite42_find_ai_citation_gaps: aivFindAiCitationGaps,
|
|
255
|
+
cite42_generate_content_brief: aivGenerateContentBrief
|
|
138
256
|
}
|
|
139
257
|
});
|
|
140
258
|
server.startStdio().catch((error) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cite42/mcp",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "MCP server for the Cite42
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "MCP server for the Cite42 API. Requires a Cite42 API key for AI search, citations, SEO keywords, trends, and workflows.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
|
-
"keywords": ["mcp", "model-context-protocol", "
|
|
32
|
+
"keywords": ["mcp", "model-context-protocol", "cite42", "ai-search", "seo", "keywords", "trends", "claude"],
|
|
33
33
|
"engines": {
|
|
34
34
|
"node": ">=18"
|
|
35
35
|
}
|