@frase/mcp-server 0.3.0 → 0.3.2
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/dist/formatter.d.ts +1 -1
- package/dist/formatter.d.ts.map +1 -1
- package/dist/formatter.js +1 -1
- package/dist/formatter.js.map +1 -1
- package/dist/lib/mcp-audit.d.ts +3 -0
- package/dist/lib/mcp-audit.d.ts.map +1 -0
- package/dist/lib/mcp-audit.js +95 -0
- package/dist/lib/mcp-audit.js.map +1 -0
- package/dist/mcpb-bundle.js +30072 -0
- package/dist/prompts/content-pipeline.d.ts.map +1 -1
- package/dist/prompts/content-pipeline.js +10 -18
- package/dist/prompts/content-pipeline.js.map +1 -1
- package/dist/prompts/create-seo-article.d.ts.map +1 -1
- package/dist/prompts/create-seo-article.js +17 -42
- package/dist/prompts/create-seo-article.js.map +1 -1
- package/dist/prompts/keyword-research.d.ts.map +1 -1
- package/dist/prompts/keyword-research.js +20 -31
- package/dist/prompts/keyword-research.js.map +1 -1
- package/dist/resources/briefs.d.ts.map +1 -1
- package/dist/resources/briefs.js +12 -6
- package/dist/resources/briefs.js.map +1 -1
- package/dist/tools/ai-visibility.d.ts.map +1 -1
- package/dist/tools/ai-visibility.js +67 -12
- package/dist/tools/ai-visibility.js.map +1 -1
- package/dist/tools/analytics.d.ts.map +1 -1
- package/dist/tools/analytics.js +9 -4
- package/dist/tools/analytics.js.map +1 -1
- package/dist/tools/audits.d.ts +8 -5
- package/dist/tools/audits.d.ts.map +1 -1
- package/dist/tools/audits.js +112 -20
- package/dist/tools/audits.js.map +1 -1
- package/dist/tools/briefs.d.ts +40 -145
- package/dist/tools/briefs.d.ts.map +1 -1
- package/dist/tools/briefs.js +153 -163
- package/dist/tools/briefs.js.map +1 -1
- package/dist/tools/content.d.ts +34 -6
- package/dist/tools/content.d.ts.map +1 -1
- package/dist/tools/content.js +351 -30
- package/dist/tools/content.js.map +1 -1
- package/dist/tools/discover.js +3 -3
- package/dist/tools/discover.js.map +1 -1
- package/dist/tools/optimizations.d.ts +4 -0
- package/dist/tools/optimizations.d.ts.map +1 -1
- package/dist/tools/optimizations.js +359 -26
- package/dist/tools/optimizations.js.map +1 -1
- package/dist/tools/publish.d.ts +3 -3
- package/dist/tools/publish.js +6 -6
- package/dist/tools/publish.js.map +1 -1
- package/dist/tools/research.d.ts +18 -6
- package/dist/tools/research.d.ts.map +1 -1
- package/dist/tools/research.js +210 -19
- package/dist/tools/research.js.map +1 -1
- package/dist/tools/rules.d.ts +76 -0
- package/dist/tools/rules.d.ts.map +1 -1
- package/dist/tools/rules.js +355 -12
- package/dist/tools/rules.js.map +1 -1
- package/dist/tools/serp.d.ts.map +1 -1
- package/dist/tools/serp.js +30 -18
- package/dist/tools/serp.js.map +1 -1
- package/dist/tools/site-health.js +10 -10
- package/dist/tools/site-health.js.map +1 -1
- package/dist/tools/templates.js +5 -5
- package/dist/tools/templates.js.map +1 -1
- package/dist/tools/webhooks.d.ts.map +1 -1
- package/dist/tools/webhooks.js +24 -3
- package/dist/tools/webhooks.js.map +1 -1
- package/package.json +8 -11
- package/server.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-pipeline.d.ts","sourceRoot":"","sources":["../../src/prompts/content-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,qBAAqB,EAAE,mBAoCnC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IAC9E,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC,
|
|
1
|
+
{"version":3,"file":"content-pipeline.d.ts","sourceRoot":"","sources":["../../src/prompts/content-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,qBAAqB,EAAE,mBAoCnC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IAC9E,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC,CAoDD"}
|
|
@@ -34,7 +34,7 @@ export const contentPipelinePrompt = {
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
name: "content_type",
|
|
37
|
-
description: "Type of content: blog, guide,
|
|
37
|
+
description: "Type of content: blog, guide, comparison, landing, product (default: blog)",
|
|
38
38
|
required: false,
|
|
39
39
|
},
|
|
40
40
|
{
|
|
@@ -72,32 +72,24 @@ export function getContentPipelineMessages(args) {
|
|
|
72
72
|
|
|
73
73
|
**Execute these steps in order:**
|
|
74
74
|
|
|
75
|
-
**Step 1 — Research:** Use start_research with
|
|
75
|
+
**Step 1 — Research:** Use start_research with query "${topic}" and site_id "${siteId}". This runs keywords, SERP analysis, content gaps, evidence, and AI visibility in parallel. Wait for completion using get_job_status (poll every 5 seconds). Then retrieve results with get_research to confirm keywords, competitors, and gaps were found. If research fails after 3 polls with "failed" status, report the error and stop.
|
|
76
76
|
|
|
77
|
-
**Step 2 —
|
|
78
|
-
|
|
79
|
-
**Step 3 — Competitor Analysis:** Use analyze_competitors for "${topic}" to identify content gaps and opportunities in the top-ranking pages. If this fails, continue — competitor data enriches but isn't required.
|
|
80
|
-
|
|
81
|
-
**Step 4 — Create Brief:** Use create_brief with:
|
|
82
|
-
- topic: "${topic}"
|
|
83
|
-
- generate_outline: true
|
|
77
|
+
**Step 2 — Create Brief:** Use create_brief with:
|
|
78
|
+
- research_session_id: the ID from Step 1
|
|
84
79
|
- content_type: "${contentType}"
|
|
85
|
-
-
|
|
86
|
-
- target_language: "${targetLanguage}"
|
|
87
|
-
- target_country: "${targetCountry}"
|
|
88
|
-
Wait for the brief to complete using get_job_status (poll every 5 seconds, up to 60 polls / 5 minutes). Then use get_brief to retrieve the full outline. If brief generation fails or times out, report the error and stop — content cannot be generated without a brief.
|
|
80
|
+
This creates a research-backed brief using the full research context (keywords, SERP headings, content gaps, evidence, AI visibility, search intent). Wait for the brief to be ready using get_job_status with type "brief" (poll every 5 seconds, up to 60 polls / 5 minutes). Then use get_brief to retrieve the full outline. If brief generation fails or times out, report the error and stop.
|
|
89
81
|
|
|
90
|
-
**Step
|
|
82
|
+
**Step 3 — Generate Content:** Use generate_content with the brief ID. Wait for completion using get_job_status (poll every 10 seconds, up to 30 polls / 5 minutes). Retrieve the generated content with get_content. If content generation fails or times out, report the error and stop.
|
|
91
83
|
|
|
92
|
-
**Step
|
|
84
|
+
**Step 4 — Optimize:** Use start_optimization with the content ID. Wait for analysis to complete (poll every 5 seconds), then use get_optimization to review the score and suggestions.
|
|
93
85
|
- If the score is below ${targetScore}: apply the highest-priority suggestions using apply_optimization (one call per suggestion_id), then re-run start_optimization and check the new score.
|
|
94
86
|
- Repeat this cycle up to 3 times or until the score meets the target.
|
|
95
87
|
- Report the final score.
|
|
96
|
-
- If optimization fails, skip to Step
|
|
88
|
+
- If optimization fails, skip to Step 5 — content can still be published as a draft for manual optimization.
|
|
97
89
|
|
|
98
|
-
**Step
|
|
90
|
+
**Step 5 — Publish:** Use list_cms_connections with site_id "${siteId}" to check available platforms. If a CMS is connected, use publish_content with the content ID, destination "frase_cms" (or the connected platform), site_id "${siteId}", and status "draft". Report the published URL. If no CMS connection exists, skip publishing and note this in the report.
|
|
99
91
|
|
|
100
|
-
**Step
|
|
92
|
+
**Step 6 — Monitor:** Use create_prompt with prompt_text set to a natural question about "${topic}" (min 10 chars, e.g., "What is the best approach to ${topic}?") and target_brand set to the site's brand name. This tracks whether AI search engines (ChatGPT, Perplexity, Claude, etc.) cite this content. If monitoring setup fails, note it in the report — it can be configured manually later.
|
|
101
93
|
|
|
102
94
|
**After all steps, provide a summary report:**
|
|
103
95
|
- Topic and URL
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content-pipeline.js","sourceRoot":"","sources":["../../src/prompts/content-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAwB;IACxD,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,mNAAmN;IACrN,SAAS,EAAE;QACT;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6DAA6D;YAC1E,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,0EAA0E;YACvF,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"content-pipeline.js","sourceRoot":"","sources":["../../src/prompts/content-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAwB;IACxD,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,mNAAmN;IACrN,SAAS,EAAE;QACT;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6DAA6D;YAC1E,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,0EAA0E;YACvF,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,4EAA4E;YACzF,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,iBAAiB;YACvB,WAAW,EAAE,iFAAiF;YAC9F,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,gBAAgB;YACtB,WAAW,EAAE,6EAA6E;YAC1F,QAAQ,EAAE,KAAK;SAChB;KACF;CACF,CAAC;AAEF,MAAM,UAAU,0BAA0B,CAAC,IAA4B;IAIrE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,qBAAqB,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC;IAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC;IAChD,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC;IACpD,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC;IAElD,OAAO;QACL;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,sCAAsC,KAAK;;;aAG5C,MAAM;kBACD,WAAW;+BACE,WAAW;cAC5B,cAAc;aACf,aAAa;;;;wDAI8B,KAAK,kBAAkB,MAAM;;;;mBAIlE,WAAW;;;;;;0BAMJ,WAAW;;;;;+DAK0B,MAAM,iKAAiK,MAAM;;4FAEhJ,KAAK,wDAAwD,KAAK;;;;;;;gCAO9H;aACzB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-seo-article.d.ts","sourceRoot":"","sources":["../../src/prompts/create-seo-article.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"create-seo-article.d.ts","sourceRoot":"","sources":["../../src/prompts/create-seo-article.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,sBAAsB,EAAE,mBA2BpC,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IAC/E,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC,CA4DD"}
|
|
@@ -12,36 +12,21 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export const createSeoArticlePrompt = {
|
|
14
14
|
name: "create_seo_article",
|
|
15
|
-
description: "Create a complete SEO article from scratch.
|
|
15
|
+
description: "Create a complete SEO article from scratch. Researches the topic, creates a research-backed brief with outline, generates optimized content, scores and revises until quality threshold is met, publishes to CMS, and sets up AI visibility monitoring.",
|
|
16
16
|
arguments: [
|
|
17
17
|
{
|
|
18
18
|
name: "topic",
|
|
19
19
|
description: "The topic or title for the article (required)",
|
|
20
20
|
required: true,
|
|
21
21
|
},
|
|
22
|
-
{
|
|
23
|
-
name: "keywords",
|
|
24
|
-
description: "Target keywords to optimize for (comma-separated)",
|
|
25
|
-
required: false,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: "content_type",
|
|
29
|
-
description: "Type of content: blog, guide, listicle, comparison, landing (default: blog)",
|
|
30
|
-
required: false,
|
|
31
|
-
},
|
|
32
22
|
{
|
|
33
23
|
name: "site_id",
|
|
34
|
-
description: "Site ID to associate and
|
|
35
|
-
required:
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
name: "target_language",
|
|
39
|
-
description: "ISO 639-1 language code (e.g., 'en', 'de', 'es'). Defaults to 'en'.",
|
|
40
|
-
required: false,
|
|
24
|
+
description: "Site ID to associate research and content with (required). Use list_sites to find your site ID.",
|
|
25
|
+
required: true,
|
|
41
26
|
},
|
|
42
27
|
{
|
|
43
|
-
name: "
|
|
44
|
-
description: "
|
|
28
|
+
name: "content_type",
|
|
29
|
+
description: "Type of content: blog, guide, comparison, landing, product (default: blog)",
|
|
45
30
|
required: false,
|
|
46
31
|
},
|
|
47
32
|
{
|
|
@@ -53,18 +38,9 @@ export const createSeoArticlePrompt = {
|
|
|
53
38
|
};
|
|
54
39
|
export function getCreateSeoArticleMessages(args) {
|
|
55
40
|
const topic = args.topic || "the requested topic";
|
|
56
|
-
const keywords = args.keywords ? args.keywords.split(",").map((k) => k.trim()) : [];
|
|
57
41
|
const contentType = args.content_type || "blog";
|
|
58
|
-
const siteId = args.site_id ||
|
|
59
|
-
const targetLanguage = args.target_language || null;
|
|
60
|
-
const targetCountry = args.target_country || null;
|
|
42
|
+
const siteId = args.site_id || "";
|
|
61
43
|
const targetScore = args.target_score || "70";
|
|
62
|
-
const keywordText = keywords.length > 0
|
|
63
|
-
? `\n- Target keywords: ${keywords.join(", ")}`
|
|
64
|
-
: "";
|
|
65
|
-
const siteText = siteId ? `\n- Site ID: ${siteId}` : "";
|
|
66
|
-
const languageText = targetLanguage ? `\n- Language: ${targetLanguage}` : "";
|
|
67
|
-
const countryText = targetCountry ? `\n- Country: ${targetCountry}` : "";
|
|
68
44
|
return [
|
|
69
45
|
{
|
|
70
46
|
role: "user",
|
|
@@ -73,24 +49,25 @@ export function getCreateSeoArticleMessages(args) {
|
|
|
73
49
|
text: `Please help me create a complete SEO article about "${topic}".
|
|
74
50
|
|
|
75
51
|
Article specifications:
|
|
76
|
-
- Content type: ${contentType}
|
|
52
|
+
- Content type: ${contentType}
|
|
53
|
+
- Site ID: ${siteId}
|
|
77
54
|
- Target optimization score: ${targetScore}+
|
|
78
55
|
|
|
79
56
|
Please follow these steps:
|
|
80
57
|
|
|
81
|
-
1. **Research the topic** using start_research
|
|
58
|
+
1. **Research the topic** using start_research with query "${topic}" and site_id "${siteId}". Wait for completion using get_job_status (poll every 5 seconds). Then retrieve results with get_research to see keywords, competitors, content gaps, and search intent.
|
|
82
59
|
|
|
83
|
-
2. **Create a
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
|
|
60
|
+
2. **Create a research-backed brief** using create_brief with:
|
|
61
|
+
- research_session_id: the ID from step 1
|
|
62
|
+
- content_type: "${contentType}"
|
|
63
|
+
This generates a detailed outline from the full research context (keywords, SERP headings, gaps, evidence, AI visibility).
|
|
87
64
|
|
|
88
|
-
3. **Wait for the brief** to be ready using get_job_status, then get the full brief with get_brief
|
|
65
|
+
3. **Wait for the brief** to be ready using get_job_status with type "brief", then get the full brief with get_brief.
|
|
89
66
|
|
|
90
67
|
4. **Review the outline** and let me know what was generated, including:
|
|
91
68
|
- The suggested outline structure
|
|
92
69
|
- Key topics to cover
|
|
93
|
-
-
|
|
70
|
+
- Research insights used
|
|
94
71
|
|
|
95
72
|
5. **Ask for my approval** before generating the final content
|
|
96
73
|
|
|
@@ -105,16 +82,14 @@ Please follow these steps:
|
|
|
105
82
|
- Re-score until the target is met or no more high-priority suggestions remain
|
|
106
83
|
- Report the final optimization score
|
|
107
84
|
|
|
108
|
-
|
|
85
|
+
9. **Publish to CMS**:
|
|
109
86
|
- Use list_cms_connections with site_id "${siteId}" to check available platforms
|
|
110
87
|
- Use publish_content with content_id, destination "frase_cms" (or the connected platform), site_id "${siteId}", and status "draft"
|
|
111
88
|
- Confirm the published URL
|
|
112
89
|
|
|
113
90
|
10. **Set up AI visibility monitoring**:
|
|
114
91
|
- Use create_prompt with prompt_text set to a natural question about "${topic}" (min 10 chars) and target_brand set to the site's brand name
|
|
115
|
-
- Confirm the monitoring is active
|
|
116
|
-
- Use create_prompt with prompt_text set to a natural question about "${topic}" (min 10 chars) and target_brand set to your brand name
|
|
117
|
-
- Confirm the monitoring is active`}
|
|
92
|
+
- Confirm the monitoring is active
|
|
118
93
|
|
|
119
94
|
Please start with the research step and guide me through this process.`,
|
|
120
95
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-seo-article.js","sourceRoot":"","sources":["../../src/prompts/create-seo-article.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,CAAC,MAAM,sBAAsB,GAAwB;IACzD,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"create-seo-article.js","sourceRoot":"","sources":["../../src/prompts/create-seo-article.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,MAAM,CAAC,MAAM,sBAAsB,GAAwB;IACzD,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,yPAAyP;IAC3P,SAAS,EAAE;QACT;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,+CAA+C;YAC5D,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,iGAAiG;YAC9G,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EACT,4EAA4E;YAC9E,QAAQ,EAAE,KAAK;SAChB;QACD;YACE,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,4DAA4D;YACzE,QAAQ,EAAE,KAAK;SAChB;KACF;CACF,CAAC;AAEF,MAAM,UAAU,2BAA2B,CAAC,IAA4B;IAItE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,qBAAqB,CAAC;IAClD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IAClC,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC;IAE9C,OAAO;QACL;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,uDAAuD,KAAK;;;kBAGxD,WAAW;aAChB,MAAM;+BACY,WAAW;;;;6DAImB,KAAK,kBAAkB,MAAM;;;;sBAIpE,WAAW;;;;;;;;;;;;;;;;;;;6BAmBJ,WAAW;;;;;8CAKM,MAAM;0GACsD,MAAM;;;;4EAIpC,KAAK;;;uEAGV;aAChE;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyword-research.d.ts","sourceRoot":"","sources":["../../src/prompts/keyword-research.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"keyword-research.d.ts","sourceRoot":"","sources":["../../src/prompts/keyword-research.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,qBAAqB,EAAE,mBAgBnC,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IAC9E,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAC3B,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC,CAoCD"}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export const keywordResearchPrompt = {
|
|
10
10
|
name: "keyword_research",
|
|
11
|
-
description: "Research keywords for a topic.
|
|
11
|
+
description: "Research keywords for a topic. Runs full research including keyword extraction, SERP analysis, content gaps, and search intent classification.",
|
|
12
12
|
arguments: [
|
|
13
13
|
{
|
|
14
14
|
name: "topic",
|
|
@@ -16,21 +16,15 @@ export const keywordResearchPrompt = {
|
|
|
16
16
|
required: true,
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
name: "
|
|
20
|
-
description: "
|
|
21
|
-
required:
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
name: "language",
|
|
25
|
-
description: "Two-letter language code (default: en)",
|
|
26
|
-
required: false,
|
|
19
|
+
name: "site_id",
|
|
20
|
+
description: "Site ID for brand context and localization (required). Use list_sites to find your site ID.",
|
|
21
|
+
required: true,
|
|
27
22
|
},
|
|
28
23
|
],
|
|
29
24
|
};
|
|
30
25
|
export function getKeywordResearchMessages(args) {
|
|
31
26
|
const topic = args.topic || "[topic]";
|
|
32
|
-
const
|
|
33
|
-
const language = args.language || "en";
|
|
27
|
+
const siteId = args.site_id || "";
|
|
34
28
|
return [
|
|
35
29
|
{
|
|
36
30
|
role: "user",
|
|
@@ -38,33 +32,28 @@ export function getKeywordResearchMessages(args) {
|
|
|
38
32
|
type: "text",
|
|
39
33
|
text: `Please help me research keywords for: "${topic}"
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
- Country: ${country}
|
|
43
|
-
- Language: ${language}
|
|
35
|
+
Site ID: ${siteId}
|
|
44
36
|
|
|
45
37
|
Please follow these steps:
|
|
46
38
|
|
|
47
|
-
1. **
|
|
48
|
-
- Current top-ranking content
|
|
49
|
-
- Featured snippets
|
|
50
|
-
- People Also Ask questions
|
|
51
|
-
- Related searches
|
|
52
|
-
|
|
53
|
-
2. **Get search intent** using get_search_intent to determine:
|
|
54
|
-
- Primary intent (informational, transactional, navigational)
|
|
55
|
-
- Recommended content type and format
|
|
39
|
+
1. **Research the topic** using start_research with query "${topic}" and site_id "${siteId}". Wait for completion using get_job_status. This runs keyword extraction, SERP analysis, content gaps, evidence gathering, and AI visibility analysis in parallel.
|
|
56
40
|
|
|
57
|
-
|
|
41
|
+
2. **Retrieve results** using get_research to see:
|
|
42
|
+
- Keywords with search volume, difficulty, and categories
|
|
43
|
+
- SERP competitors and their content structure
|
|
44
|
+
- Content gaps and opportunities
|
|
45
|
+
- Questions people ask about this topic
|
|
46
|
+
- Search intent analysis
|
|
58
47
|
|
|
59
|
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
- Recommended content angle
|
|
48
|
+
3. **Present your findings** including:
|
|
49
|
+
- Top keyword opportunities (sorted by volume and difficulty)
|
|
50
|
+
- Content gaps worth exploiting
|
|
51
|
+
- Search intent breakdown
|
|
52
|
+
- Recommended content angle based on the competitive landscape
|
|
64
53
|
|
|
65
|
-
|
|
54
|
+
4. **Suggest next steps** — offer to create a research-backed brief using create_brief with the research_session_id
|
|
66
55
|
|
|
67
|
-
Please start with the
|
|
56
|
+
Please start with the research.`,
|
|
68
57
|
},
|
|
69
58
|
},
|
|
70
59
|
];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyword-research.js","sourceRoot":"","sources":["../../src/prompts/keyword-research.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAwB;IACxD,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,
|
|
1
|
+
{"version":3,"file":"keyword-research.js","sourceRoot":"","sources":["../../src/prompts/keyword-research.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,CAAC,MAAM,qBAAqB,GAAwB;IACxD,IAAI,EAAE,kBAAkB;IACxB,WAAW,EACT,gJAAgJ;IAClJ,SAAS,EAAE;QACT;YACE,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,kDAAkD;YAC/D,QAAQ,EAAE,IAAI;SACf;QACD;YACE,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,6FAA6F;YAC1G,QAAQ,EAAE,IAAI;SACf;KACF;CACF,CAAC;AAEF,MAAM,UAAU,0BAA0B,CAAC,IAA4B;IAIrE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;IACtC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;IAElC,OAAO;QACL;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,0CAA0C,KAAK;;WAElD,MAAM;;;;6DAI4C,KAAK,kBAAkB,MAAM;;;;;;;;;;;;;;;;;gCAiB1D;aACzB;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"briefs.d.ts","sourceRoot":"","sources":["../../src/resources/briefs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"briefs.d.ts","sourceRoot":"","sources":["../../src/resources/briefs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,aAAa,CAAC;AAgCrB,eAAO,MAAM,UAAU,mBAAmB,CAAC;AAC3C,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAMlD,eAAO,MAAM,sBAAsB;;;;;GAOlC,CAAC;AAMF,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,aAAa,EAAE,CAAC,CAsC1B;AAMD,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAWjB;AA6GD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEpD"}
|
package/dist/resources/briefs.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - frase://briefs/{id} - Individual brief with outline
|
|
7
7
|
*/
|
|
8
8
|
import { CACHE_TTL } from "../cache.js";
|
|
9
|
-
import { formatKeyValue, formatDate, formatStatus, truncate } from "../formatter.js";
|
|
9
|
+
import { formatKeyValue, formatDate, formatStatus, formatContentType, truncate } from "../formatter.js";
|
|
10
10
|
// ============================================
|
|
11
11
|
// Resource URIs
|
|
12
12
|
// ============================================
|
|
@@ -39,7 +39,7 @@ export async function listBriefResources(context) {
|
|
|
39
39
|
resources.push({
|
|
40
40
|
uri: `${BRIEF_URI_PREFIX}${brief.id}`,
|
|
41
41
|
name: truncate(brief.topic, 50),
|
|
42
|
-
description: `${formatStatus(brief.status)} - ${brief.content_type
|
|
42
|
+
description: `${formatStatus(brief.status)} - ${formatContentType(brief.content_type)}`,
|
|
43
43
|
mimeType: "text/markdown",
|
|
44
44
|
});
|
|
45
45
|
}
|
|
@@ -79,7 +79,7 @@ async function readBriefsList(context) {
|
|
|
79
79
|
markdown += `| Topic | Status | Type | Created |\n`;
|
|
80
80
|
markdown += `|-------|--------|------|--------|\n`;
|
|
81
81
|
for (const brief of response.data) {
|
|
82
|
-
markdown += `| ${truncate(brief.topic, 40)} | ${formatStatus(brief.status)} | ${brief.content_type
|
|
82
|
+
markdown += `| ${truncate(brief.topic, 40)} | ${formatStatus(brief.status)} | ${formatContentType(brief.content_type)} | ${formatDate(brief.created_at)} |\n`;
|
|
83
83
|
}
|
|
84
84
|
const { pagination } = response;
|
|
85
85
|
markdown += `\n**Showing ${response.data.length} of ${pagination.total} items**\n`;
|
|
@@ -95,15 +95,21 @@ async function readBriefDetails(briefId, context) {
|
|
|
95
95
|
markdown += formatKeyValue({
|
|
96
96
|
ID: brief.id,
|
|
97
97
|
Status: formatStatus(brief.status),
|
|
98
|
-
"Content Type": brief.content_type
|
|
98
|
+
"Content Type": formatContentType(brief.content_type),
|
|
99
99
|
"Search Intent": brief.search_intent || "-",
|
|
100
100
|
"Target Words": brief.target_word_count || "-",
|
|
101
101
|
Created: formatDate(brief.created_at),
|
|
102
102
|
Updated: brief.updated_at ? formatDate(brief.updated_at) : "-",
|
|
103
103
|
});
|
|
104
|
-
|
|
104
|
+
// Use original user-specified keywords if available (targetKeywords gets
|
|
105
|
+
// overwritten with expanded keywords during outline generation)
|
|
106
|
+
const originalKeywords = brief.progress_details?.originalKeywords;
|
|
107
|
+
const displayKeywords = (originalKeywords && originalKeywords.length > 0)
|
|
108
|
+
? originalKeywords
|
|
109
|
+
: brief.target_keywords;
|
|
110
|
+
if (displayKeywords && displayKeywords.length > 0) {
|
|
105
111
|
markdown += "\n## Target Keywords\n\n";
|
|
106
|
-
for (const keyword of
|
|
112
|
+
for (const keyword of displayKeywords) {
|
|
107
113
|
markdown += `- ${keyword}\n`;
|
|
108
114
|
}
|
|
109
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"briefs.js","sourceRoot":"","sources":["../../src/resources/briefs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"briefs.js","sourceRoot":"","sources":["../../src/resources/briefs.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-visibility.d.ts","sourceRoot":"","sources":["../../src/tools/ai-visibility.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,UAAU,EAGX,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ai-visibility.d.ts","sourceRoot":"","sources":["../../src/tools/ai-visibility.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,UAAU,EAGX,MAAM,aAAa,CAAC;AAwIrB,eAAO,MAAM,mBAAmB,EAAE,iBAiBjC,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CA8GrB;AAYD,eAAO,MAAM,eAAe,EAAE,iBAoB7B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CA8CrB;AAiBD,eAAO,MAAM,gBAAgB,EAAE,iBA8C9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CA8CrB;AAUD,eAAO,MAAM,aAAa,EAAE,iBAa3B,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAiErB;AAcD,eAAO,MAAM,gBAAgB,EAAE,iBAiC9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoCrB;AAaD,eAAO,MAAM,kBAAkB,EAAE,iBAwBhC,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAwDrB;AAWD,eAAO,MAAM,aAAa,EAAE,iBAgB3B,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAsDrB;AAYD,eAAO,MAAM,eAAe,EAAE,iBAoB7B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoErB;AAoBD,eAAO,MAAM,kBAAkB,EAAE,iBAqBhC,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAqDrB;AAMD,eAAO,MAAM,iBAAiB,EAAE,iBAAiB,EAUhD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,MAAM,CACxC,MAAM,EACN,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAW9D,CAAC"}
|
|
@@ -11,10 +11,11 @@ import { formatTable, formatStatus, formatDate, formatPagination, formatKeyValue
|
|
|
11
11
|
// ============================================
|
|
12
12
|
const getAiVisibilityInputSchema = z.object({
|
|
13
13
|
days: z.number().min(1).max(90).optional().default(30),
|
|
14
|
+
site_id: z.string().optional(),
|
|
14
15
|
});
|
|
15
16
|
export const getAiVisibilityTool = {
|
|
16
17
|
name: "get_ai_visibility",
|
|
17
|
-
description: "Get an overview of your AI visibility metrics - how your content appears in AI search results like ChatGPT, Perplexity, etc.",
|
|
18
|
+
description: "Get an overview of your AI visibility metrics - how your content appears in AI search results like ChatGPT, Perplexity, etc. Use site_id to filter to a specific site (recommended), or omit for aggregated data across all sites.",
|
|
18
19
|
inputSchema: {
|
|
19
20
|
type: "object",
|
|
20
21
|
properties: {
|
|
@@ -22,6 +23,10 @@ export const getAiVisibilityTool = {
|
|
|
22
23
|
type: "number",
|
|
23
24
|
description: "Number of days to look back (1-90, default: 30)",
|
|
24
25
|
},
|
|
26
|
+
site_id: {
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "Site ID for per-site metrics. Use list_sites to get available IDs. If omitted, returns aggregated data across all sites.",
|
|
29
|
+
},
|
|
25
30
|
},
|
|
26
31
|
},
|
|
27
32
|
};
|
|
@@ -33,9 +38,11 @@ export async function executeGetAiVisibility(input, context) {
|
|
|
33
38
|
markdown: `**Error:** Invalid input - ${parsed.error.message}`,
|
|
34
39
|
};
|
|
35
40
|
}
|
|
36
|
-
const { days } = parsed.data;
|
|
41
|
+
const { days, site_id } = parsed.data;
|
|
37
42
|
try {
|
|
38
43
|
const params = { days };
|
|
44
|
+
if (site_id)
|
|
45
|
+
params.site_id = site_id;
|
|
39
46
|
const response = await context.client.get("/ai-visibility", params, CACHE_TTL.resources);
|
|
40
47
|
const data = response.data;
|
|
41
48
|
if (!data) {
|
|
@@ -46,14 +53,39 @@ export async function executeGetAiVisibility(input, context) {
|
|
|
46
53
|
};
|
|
47
54
|
}
|
|
48
55
|
const overview = data.overview;
|
|
56
|
+
const overviewPrompts = data.prompts ?? [];
|
|
57
|
+
// Appearance rate: % of prompts where brand is visible (matches app definition)
|
|
58
|
+
const appearanceRate = overviewPrompts.length > 0
|
|
59
|
+
? Math.round((overviewPrompts.filter((p) => p.is_visible).length / overviewPrompts.length) * 100)
|
|
60
|
+
: null;
|
|
61
|
+
// Citation rate: % of prompts where brand is cited
|
|
62
|
+
const citationRate = overviewPrompts.length > 0
|
|
63
|
+
? Math.round((overviewPrompts.filter((p) => p.is_cited).length / overviewPrompts.length) * 100)
|
|
64
|
+
: null;
|
|
49
65
|
let markdown = `## AI Visibility Overview (Last ${overview.period_days} days)\n\n`;
|
|
50
66
|
markdown += formatKeyValue({
|
|
51
67
|
total_prompts: overview.total_prompts ?? 0,
|
|
52
|
-
avg_visibility_score: overview.avg_visibility_score != null ? overview.avg_visibility_score
|
|
68
|
+
avg_visibility_score: overview.avg_visibility_score != null ? `${overview.avg_visibility_score}/100` : "N/A",
|
|
69
|
+
share_of_voice: overview.share_of_voice != null ? `${overview.share_of_voice}%` : "N/A (provide site_id for SOV)",
|
|
70
|
+
appearance_rate: appearanceRate != null ? `${appearanceRate}%` : "N/A",
|
|
71
|
+
citation_rate: citationRate != null ? `${citationRate}%` : "N/A",
|
|
53
72
|
total_checks: overview.total_checks ?? 0,
|
|
54
73
|
total_mentions: overview.total_mentions ?? 0,
|
|
55
74
|
total_citations: overview.total_citations ?? 0,
|
|
56
75
|
});
|
|
76
|
+
// Show competitor SOV breakdown if available
|
|
77
|
+
const competitorBreakdown = overview.competitor_breakdown ?? [];
|
|
78
|
+
if (competitorBreakdown.length > 0) {
|
|
79
|
+
markdown += "\n\n### Share of Voice Breakdown\n\n";
|
|
80
|
+
const sovHeaders = ["Competitor", "Mentions", "SOV"];
|
|
81
|
+
const sovRows = competitorBreakdown.map((c) => [
|
|
82
|
+
c.name,
|
|
83
|
+
c.mentions.toString(),
|
|
84
|
+
`${c.sov}%`,
|
|
85
|
+
]);
|
|
86
|
+
markdown += formatTable(sovHeaders, sovRows);
|
|
87
|
+
}
|
|
88
|
+
markdown += `\n\n> **Tip:** Use \`list_prompts\` and \`get_prompt\` for detailed per-prompt metrics.`;
|
|
57
89
|
const platforms = data.platform_breakdown ?? [];
|
|
58
90
|
if (platforms.length > 0) {
|
|
59
91
|
markdown += "\n\n### Platform Breakdown\n\n";
|
|
@@ -170,8 +202,10 @@ const createPromptInputSchema = z.object({
|
|
|
170
202
|
prompt_text: z.string().min(10).max(1000),
|
|
171
203
|
target_brand: z.string().min(1).max(255),
|
|
172
204
|
brand_variants: z.array(z.string()).optional(),
|
|
173
|
-
frequency: z.enum(["daily", "weekly"
|
|
205
|
+
frequency: z.enum(["daily", "weekly"]).optional().default("daily"),
|
|
174
206
|
platforms: z.array(z.string()).optional(),
|
|
207
|
+
category: z.enum(["brand", "competitors", "product", "problem", "commercial", "custom"]).optional().default("product"),
|
|
208
|
+
location: z.enum(["global", "us", "uk", "eu", "apac", "latam"]).optional().default("global"),
|
|
175
209
|
site_id: z.string().optional(),
|
|
176
210
|
});
|
|
177
211
|
export const createPromptTool = {
|
|
@@ -195,7 +229,7 @@ export const createPromptTool = {
|
|
|
195
229
|
},
|
|
196
230
|
frequency: {
|
|
197
231
|
type: "string",
|
|
198
|
-
enum: ["daily", "weekly"
|
|
232
|
+
enum: ["daily", "weekly"],
|
|
199
233
|
description: "How often to crawl this prompt (default: daily)",
|
|
200
234
|
},
|
|
201
235
|
platforms: {
|
|
@@ -203,9 +237,19 @@ export const createPromptTool = {
|
|
|
203
237
|
items: { type: "string" },
|
|
204
238
|
description: "AI platforms to track (e.g., chatgpt, perplexity, claude, gemini, google_ai, grok, copilot, deepseek)",
|
|
205
239
|
},
|
|
240
|
+
category: {
|
|
241
|
+
type: "string",
|
|
242
|
+
enum: ["brand", "competitors", "product", "problem", "commercial", "custom"],
|
|
243
|
+
description: "Prompt category (default: product)",
|
|
244
|
+
},
|
|
245
|
+
location: {
|
|
246
|
+
type: "string",
|
|
247
|
+
enum: ["global", "us", "uk", "eu", "apac", "latam"],
|
|
248
|
+
description: "Geographic location for tracking (default: global)",
|
|
249
|
+
},
|
|
206
250
|
site_id: {
|
|
207
251
|
type: "string",
|
|
208
|
-
description: "Associate with a specific site",
|
|
252
|
+
description: "Associate with a specific site (strongly recommended — prompts without a site_id will NOT appear in the Frase app). Use list_sites to get available IDs.",
|
|
209
253
|
},
|
|
210
254
|
},
|
|
211
255
|
required: ["prompt_text", "target_brand"],
|
|
@@ -219,9 +263,9 @@ export async function executeCreatePrompt(input, context) {
|
|
|
219
263
|
markdown: `**Error:** Invalid input - ${parsed.error.message}`,
|
|
220
264
|
};
|
|
221
265
|
}
|
|
222
|
-
const { prompt_text, target_brand, brand_variants, frequency, platforms, site_id } = parsed.data;
|
|
266
|
+
const { prompt_text, target_brand, brand_variants, frequency, platforms, category, location, site_id } = parsed.data;
|
|
223
267
|
try {
|
|
224
|
-
const body = { prompt_text, target_brand, frequency };
|
|
268
|
+
const body = { prompt_text, target_brand, frequency, category, location };
|
|
225
269
|
if (brand_variants)
|
|
226
270
|
body.brand_variants = brand_variants;
|
|
227
271
|
if (platforms)
|
|
@@ -235,9 +279,13 @@ export async function executeCreatePrompt(input, context) {
|
|
|
235
279
|
prompt_text: prompt.prompt_text,
|
|
236
280
|
status: prompt.status,
|
|
237
281
|
});
|
|
282
|
+
let markdown = `## Prompt Created\n\n${details}\n\n**Note:** The prompt will be crawled automatically. Use \`get_prompt\` to see results.`;
|
|
283
|
+
if (!site_id) {
|
|
284
|
+
markdown += `\n\n> **Warning:** No site_id was provided. This prompt may not appear in site-scoped views in the Frase app. Recreate the prompt with a site_id to ensure visibility.`;
|
|
285
|
+
}
|
|
238
286
|
return {
|
|
239
287
|
success: true,
|
|
240
|
-
markdown
|
|
288
|
+
markdown,
|
|
241
289
|
data: response,
|
|
242
290
|
};
|
|
243
291
|
}
|
|
@@ -331,7 +379,7 @@ export async function executeGetPrompt(input, context) {
|
|
|
331
379
|
const updatePromptInputSchema = z.object({
|
|
332
380
|
id: z.string().min(1),
|
|
333
381
|
status: z.enum(["active", "paused", "archived"]).optional(),
|
|
334
|
-
frequency: z.enum(["daily", "weekly"
|
|
382
|
+
frequency: z.enum(["daily", "weekly"]).optional(),
|
|
335
383
|
platforms: z.array(z.string()).optional(),
|
|
336
384
|
brand_variants: z.array(z.string()).optional(),
|
|
337
385
|
});
|
|
@@ -352,7 +400,7 @@ export const updatePromptTool = {
|
|
|
352
400
|
},
|
|
353
401
|
frequency: {
|
|
354
402
|
type: "string",
|
|
355
|
-
enum: ["daily", "weekly"
|
|
403
|
+
enum: ["daily", "weekly"],
|
|
356
404
|
description: "How often to crawl this prompt",
|
|
357
405
|
},
|
|
358
406
|
platforms: {
|
|
@@ -407,6 +455,7 @@ const getCompetitorsInputSchema = z.object({
|
|
|
407
455
|
page: z.number().min(1).optional().default(1),
|
|
408
456
|
page_size: z.number().min(1).max(100).optional().default(20),
|
|
409
457
|
days: z.number().min(1).max(90).optional().default(30),
|
|
458
|
+
site_id: z.string().optional(),
|
|
410
459
|
});
|
|
411
460
|
export const getCompetitorsTool = {
|
|
412
461
|
name: "get_competitors",
|
|
@@ -426,6 +475,10 @@ export const getCompetitorsTool = {
|
|
|
426
475
|
type: "number",
|
|
427
476
|
description: "Number of days to look back (1-90, default: 30)",
|
|
428
477
|
},
|
|
478
|
+
site_id: {
|
|
479
|
+
type: "string",
|
|
480
|
+
description: "Filter competitors by site ID. Use list_sites to get available IDs.",
|
|
481
|
+
},
|
|
429
482
|
},
|
|
430
483
|
},
|
|
431
484
|
};
|
|
@@ -437,9 +490,11 @@ export async function executeGetCompetitors(input, context) {
|
|
|
437
490
|
markdown: `**Error:** Invalid input - ${parsed.error.message}`,
|
|
438
491
|
};
|
|
439
492
|
}
|
|
440
|
-
const { page, page_size, days } = parsed.data;
|
|
493
|
+
const { page, page_size, days, site_id } = parsed.data;
|
|
441
494
|
try {
|
|
442
495
|
const params = { page, page_size, days };
|
|
496
|
+
if (site_id)
|
|
497
|
+
params.site_id = site_id;
|
|
443
498
|
const response = await context.client.get("/ai-visibility/competitors", params, CACHE_TTL.resources);
|
|
444
499
|
const competitors = Array.isArray(response.data) ? response.data : [];
|
|
445
500
|
if (competitors.length === 0) {
|