@frase/mcp-server 0.1.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +262 -0
  3. package/dist/api-client.d.ts +93 -0
  4. package/dist/api-client.d.ts.map +1 -0
  5. package/dist/api-client.js +213 -0
  6. package/dist/api-client.js.map +1 -0
  7. package/dist/cache.d.ts +52 -0
  8. package/dist/cache.d.ts.map +1 -0
  9. package/dist/cache.js +97 -0
  10. package/dist/cache.js.map +1 -0
  11. package/dist/config.d.ts +17 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +31 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/formatter.d.ts +47 -0
  16. package/dist/formatter.d.ts.map +1 -0
  17. package/dist/formatter.js +136 -0
  18. package/dist/formatter.js.map +1 -0
  19. package/dist/index.d.ts +32 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +292 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/prompts/competitor-analysis.d.ts +18 -0
  24. package/dist/prompts/competitor-analysis.d.ts.map +1 -0
  25. package/dist/prompts/competitor-analysis.js +71 -0
  26. package/dist/prompts/competitor-analysis.js.map +1 -0
  27. package/dist/prompts/content-audit.d.ts +18 -0
  28. package/dist/prompts/content-audit.d.ts.map +1 -0
  29. package/dist/prompts/content-audit.js +67 -0
  30. package/dist/prompts/content-audit.js.map +1 -0
  31. package/dist/prompts/create-seo-article.d.ts +19 -0
  32. package/dist/prompts/create-seo-article.d.ts.map +1 -0
  33. package/dist/prompts/create-seo-article.js +78 -0
  34. package/dist/prompts/create-seo-article.js.map +1 -0
  35. package/dist/prompts/index.d.ts +18 -0
  36. package/dist/prompts/index.d.ts.map +1 -0
  37. package/dist/prompts/index.js +52 -0
  38. package/dist/prompts/index.js.map +1 -0
  39. package/dist/prompts/keyword-research.d.ts +18 -0
  40. package/dist/prompts/keyword-research.d.ts.map +1 -0
  41. package/dist/prompts/keyword-research.js +72 -0
  42. package/dist/prompts/keyword-research.js.map +1 -0
  43. package/dist/prompts/optimize-content.d.ts +18 -0
  44. package/dist/prompts/optimize-content.d.ts.map +1 -0
  45. package/dist/prompts/optimize-content.js +59 -0
  46. package/dist/prompts/optimize-content.js.map +1 -0
  47. package/dist/resources/briefs.d.ts +26 -0
  48. package/dist/resources/briefs.d.ts.map +1 -0
  49. package/dist/resources/briefs.js +144 -0
  50. package/dist/resources/briefs.js.map +1 -0
  51. package/dist/resources/content.d.ts +26 -0
  52. package/dist/resources/content.d.ts.map +1 -0
  53. package/dist/resources/content.js +128 -0
  54. package/dist/resources/content.js.map +1 -0
  55. package/dist/resources/index.d.ts +32 -0
  56. package/dist/resources/index.d.ts.map +1 -0
  57. package/dist/resources/index.js +85 -0
  58. package/dist/resources/index.js.map +1 -0
  59. package/dist/resources/sites.d.ts +26 -0
  60. package/dist/resources/sites.d.ts.map +1 -0
  61. package/dist/resources/sites.js +108 -0
  62. package/dist/resources/sites.js.map +1 -0
  63. package/dist/tools/ai-visibility.d.ts +25 -0
  64. package/dist/tools/ai-visibility.d.ts.map +1 -0
  65. package/dist/tools/ai-visibility.js +537 -0
  66. package/dist/tools/ai-visibility.js.map +1 -0
  67. package/dist/tools/analytics.d.ts +17 -0
  68. package/dist/tools/analytics.d.ts.map +1 -0
  69. package/dist/tools/analytics.js +311 -0
  70. package/dist/tools/analytics.js.map +1 -0
  71. package/dist/tools/audits.d.ts +73 -0
  72. package/dist/tools/audits.d.ts.map +1 -0
  73. package/dist/tools/audits.js +345 -0
  74. package/dist/tools/audits.js.map +1 -0
  75. package/dist/tools/briefs.d.ts +63 -0
  76. package/dist/tools/briefs.d.ts.map +1 -0
  77. package/dist/tools/briefs.js +276 -0
  78. package/dist/tools/briefs.js.map +1 -0
  79. package/dist/tools/content.d.ts +51 -0
  80. package/dist/tools/content.d.ts.map +1 -0
  81. package/dist/tools/content.js +233 -0
  82. package/dist/tools/content.js.map +1 -0
  83. package/dist/tools/index.d.ts +29 -0
  84. package/dist/tools/index.d.ts.map +1 -0
  85. package/dist/tools/index.js +96 -0
  86. package/dist/tools/index.js.map +1 -0
  87. package/dist/tools/jobs.d.ts +22 -0
  88. package/dist/tools/jobs.d.ts.map +1 -0
  89. package/dist/tools/jobs.js +124 -0
  90. package/dist/tools/jobs.js.map +1 -0
  91. package/dist/tools/optimizations.d.ts +19 -0
  92. package/dist/tools/optimizations.d.ts.map +1 -0
  93. package/dist/tools/optimizations.js +339 -0
  94. package/dist/tools/optimizations.js.map +1 -0
  95. package/dist/tools/research.d.ts +41 -0
  96. package/dist/tools/research.d.ts.map +1 -0
  97. package/dist/tools/research.js +151 -0
  98. package/dist/tools/research.js.map +1 -0
  99. package/dist/tools/serp.d.ts +15 -0
  100. package/dist/tools/serp.d.ts.map +1 -0
  101. package/dist/tools/serp.js +267 -0
  102. package/dist/tools/serp.js.map +1 -0
  103. package/dist/tools/sites.d.ts +31 -0
  104. package/dist/tools/sites.d.ts.map +1 -0
  105. package/dist/tools/sites.js +83 -0
  106. package/dist/tools/sites.js.map +1 -0
  107. package/dist/tools/webhooks.d.ts +19 -0
  108. package/dist/tools/webhooks.d.ts.map +1 -0
  109. package/dist/tools/webhooks.js +350 -0
  110. package/dist/tools/webhooks.js.map +1 -0
  111. package/dist/types.d.ts +167 -0
  112. package/dist/types.d.ts.map +1 -0
  113. package/dist/types.js +5 -0
  114. package/dist/types.js.map +1 -0
  115. package/package.json +67 -0
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Briefs MCP Resources
3
+ *
4
+ * Expose briefs as browsable MCP resources:
5
+ * - frase://briefs - List of briefs
6
+ * - frase://briefs/{id} - Individual brief with outline
7
+ */
8
+ import { CACHE_TTL } from "../cache.js";
9
+ import { formatKeyValue, formatDate, formatStatus, truncate } from "../formatter.js";
10
+ // ============================================
11
+ // Resource URIs
12
+ // ============================================
13
+ export const BRIEFS_URI = "frase://briefs";
14
+ export const BRIEF_URI_PREFIX = "frase://briefs/";
15
+ // ============================================
16
+ // Resource Templates
17
+ // ============================================
18
+ export const briefResourceTemplates = [
19
+ {
20
+ uriTemplate: "frase://briefs/{brief_id}",
21
+ name: "Brief",
22
+ description: "A content brief with outline and SERP data",
23
+ mimeType: "text/markdown",
24
+ },
25
+ ];
26
+ export async function listBriefResources(context) {
27
+ try {
28
+ const response = await context.client.get("/briefs", { page: 1, page_size: 50 }, CACHE_TTL.lists);
29
+ const resources = [
30
+ {
31
+ uri: BRIEFS_URI,
32
+ name: "All Briefs",
33
+ description: "List of all content briefs in your Frase account",
34
+ mimeType: "text/markdown",
35
+ },
36
+ ];
37
+ // Add individual brief resources
38
+ for (const brief of response.data) {
39
+ resources.push({
40
+ uri: `${BRIEF_URI_PREFIX}${brief.id}`,
41
+ name: truncate(brief.topic, 50),
42
+ description: `${formatStatus(brief.status)} - ${brief.content_type || "article"}`,
43
+ mimeType: "text/markdown",
44
+ });
45
+ }
46
+ return resources;
47
+ }
48
+ catch {
49
+ return [
50
+ {
51
+ uri: BRIEFS_URI,
52
+ name: "All Briefs",
53
+ description: "List of all content briefs in your Frase account",
54
+ mimeType: "text/markdown",
55
+ },
56
+ ];
57
+ }
58
+ }
59
+ // ============================================
60
+ // Read Resource
61
+ // ============================================
62
+ export async function readBriefResource(uri, context) {
63
+ if (uri === BRIEFS_URI) {
64
+ return readBriefsList(context);
65
+ }
66
+ if (uri.startsWith(BRIEF_URI_PREFIX)) {
67
+ const briefId = uri.slice(BRIEF_URI_PREFIX.length);
68
+ return readBriefDetails(briefId, context);
69
+ }
70
+ throw new Error(`Unknown brief resource URI: ${uri}`);
71
+ }
72
+ async function readBriefsList(context) {
73
+ const response = await context.client.get("/briefs", { page: 1, page_size: 50 }, CACHE_TTL.lists);
74
+ let markdown = "# Your Briefs\n\n";
75
+ if (response.data.length === 0) {
76
+ markdown += "_No briefs found. Create a brief to start planning your content._\n";
77
+ return markdown;
78
+ }
79
+ markdown += `| Topic | Status | Type | Created |\n`;
80
+ markdown += `|-------|--------|------|--------|\n`;
81
+ for (const brief of response.data) {
82
+ markdown += `| ${truncate(brief.topic, 40)} | ${formatStatus(brief.status)} | ${brief.content_type || "-"} | ${formatDate(brief.created_at)} |\n`;
83
+ }
84
+ const { pagination } = response;
85
+ markdown += `\n**Showing ${response.data.length} of ${pagination.total} items**\n`;
86
+ if (pagination.has_more) {
87
+ markdown += `\n_More briefs available. Use list_briefs tool with page parameter to see more._\n`;
88
+ }
89
+ return markdown;
90
+ }
91
+ async function readBriefDetails(briefId, context) {
92
+ const response = await context.client.get(`/briefs/${briefId}`, {}, CACHE_TTL.resources);
93
+ const brief = response.data;
94
+ let markdown = `# Brief: ${brief.topic}\n\n`;
95
+ markdown += formatKeyValue({
96
+ ID: brief.id,
97
+ Status: formatStatus(brief.status),
98
+ "Content Type": brief.content_type || "-",
99
+ "Search Intent": brief.search_intent || "-",
100
+ "Target Words": brief.target_word_count || "-",
101
+ Created: formatDate(brief.created_at),
102
+ Updated: brief.updated_at ? formatDate(brief.updated_at) : "-",
103
+ });
104
+ if (brief.target_keywords && brief.target_keywords.length > 0) {
105
+ markdown += "\n## Target Keywords\n\n";
106
+ for (const keyword of brief.target_keywords) {
107
+ markdown += `- ${keyword}\n`;
108
+ }
109
+ }
110
+ if (brief.outline && brief.outline.length > 0) {
111
+ markdown += "\n## Outline\n\n";
112
+ for (const item of brief.outline) {
113
+ const indent = " ".repeat(Math.max(0, item.level - 1));
114
+ const prefix = item.type === "heading" ? "##" + "#".repeat(item.level) : "-";
115
+ markdown += `${indent}${prefix} ${item.text}\n`;
116
+ }
117
+ }
118
+ if (brief.competitor_analysis) {
119
+ markdown += "\n## Competitor Analysis\n\n";
120
+ markdown += `**Average Word Count:** ${brief.competitor_analysis.avg_word_count}\n\n`;
121
+ if (brief.competitor_analysis.common_topics.length > 0) {
122
+ markdown += "**Common Topics:**\n";
123
+ for (const topic of brief.competitor_analysis.common_topics.slice(0, 10)) {
124
+ markdown += `- ${topic}\n`;
125
+ }
126
+ }
127
+ }
128
+ if (brief.serp_results && brief.serp_results.length > 0) {
129
+ markdown += "\n## Top SERP Results\n\n";
130
+ markdown += `| # | Domain | Title |\n`;
131
+ markdown += `|---|--------|-------|\n`;
132
+ for (const result of brief.serp_results.slice(0, 10)) {
133
+ markdown += `| ${result.position} | ${result.domain} | ${truncate(result.title, 40)} |\n`;
134
+ }
135
+ }
136
+ return markdown;
137
+ }
138
+ // ============================================
139
+ // URI Matching
140
+ // ============================================
141
+ export function matchesBriefUri(uri) {
142
+ return uri === BRIEFS_URI || uri.startsWith(BRIEF_URI_PREFIX);
143
+ }
144
+ //# sourceMappingURL=briefs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"briefs.js","sourceRoot":"","sources":["../../src/resources/briefs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Content MCP Resources
3
+ *
4
+ * Expose content as browsable MCP resources:
5
+ * - frase://content - List of content items
6
+ * - frase://content/{id} - Individual content with full body
7
+ */
8
+ import type { ToolContext } from "../types.js";
9
+ export declare const CONTENT_URI = "frase://content";
10
+ export declare const CONTENT_URI_PREFIX = "frase://content/";
11
+ export declare const contentResourceTemplates: {
12
+ uriTemplate: string;
13
+ name: string;
14
+ description: string;
15
+ mimeType: string;
16
+ }[];
17
+ export interface ContentResource {
18
+ uri: string;
19
+ name: string;
20
+ description: string;
21
+ mimeType: string;
22
+ }
23
+ export declare function listContentResources(context: ToolContext): Promise<ContentResource[]>;
24
+ export declare function readContentResource(uri: string, context: ToolContext): Promise<string>;
25
+ export declare function matchesContentUri(uri: string): boolean;
26
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/resources/content.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,aAAa,CAAC;AAqBrB,eAAO,MAAM,WAAW,oBAAoB,CAAC;AAC7C,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AAMrD,eAAO,MAAM,wBAAwB;;;;;GAOpC,CAAC;AAMF,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,eAAe,EAAE,CAAC,CAsC5B;AAMD,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAiFD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEtD"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Content MCP Resources
3
+ *
4
+ * Expose content as browsable MCP resources:
5
+ * - frase://content - List of content items
6
+ * - frase://content/{id} - Individual content with full body
7
+ */
8
+ import { CACHE_TTL } from "../cache.js";
9
+ import { formatKeyValue, formatDate, formatStatus, truncate } from "../formatter.js";
10
+ // ============================================
11
+ // Resource URIs
12
+ // ============================================
13
+ export const CONTENT_URI = "frase://content";
14
+ export const CONTENT_URI_PREFIX = "frase://content/";
15
+ // ============================================
16
+ // Resource Templates
17
+ // ============================================
18
+ export const contentResourceTemplates = [
19
+ {
20
+ uriTemplate: "frase://content/{content_id}",
21
+ name: "Content",
22
+ description: "A specific piece of content with full body text",
23
+ mimeType: "text/markdown",
24
+ },
25
+ ];
26
+ export async function listContentResources(context) {
27
+ try {
28
+ const response = await context.client.get("/content", { page: 1, page_size: 50 }, CACHE_TTL.lists);
29
+ const resources = [
30
+ {
31
+ uri: CONTENT_URI,
32
+ name: "All Content",
33
+ description: "List of all content items in your Frase account",
34
+ mimeType: "text/markdown",
35
+ },
36
+ ];
37
+ // Add individual content resources
38
+ for (const content of response.data) {
39
+ resources.push({
40
+ uri: `${CONTENT_URI_PREFIX}${content.id}`,
41
+ name: truncate(content.title, 50),
42
+ description: `${formatStatus(content.status)} - ${content.word_count || 0} words`,
43
+ mimeType: "text/markdown",
44
+ });
45
+ }
46
+ return resources;
47
+ }
48
+ catch {
49
+ return [
50
+ {
51
+ uri: CONTENT_URI,
52
+ name: "All Content",
53
+ description: "List of all content items in your Frase account",
54
+ mimeType: "text/markdown",
55
+ },
56
+ ];
57
+ }
58
+ }
59
+ // ============================================
60
+ // Read Resource
61
+ // ============================================
62
+ export async function readContentResource(uri, context) {
63
+ if (uri === CONTENT_URI) {
64
+ return readContentList(context);
65
+ }
66
+ if (uri.startsWith(CONTENT_URI_PREFIX)) {
67
+ const contentId = uri.slice(CONTENT_URI_PREFIX.length);
68
+ return readContentDetails(contentId, context);
69
+ }
70
+ throw new Error(`Unknown content resource URI: ${uri}`);
71
+ }
72
+ async function readContentList(context) {
73
+ const response = await context.client.get("/content", { page: 1, page_size: 50 }, CACHE_TTL.lists);
74
+ let markdown = "# Your Content\n\n";
75
+ if (response.data.length === 0) {
76
+ markdown += "_No content found. Create content from a brief to get started._\n";
77
+ return markdown;
78
+ }
79
+ markdown += `| Title | Status | Words | Updated |\n`;
80
+ markdown += `|-------|--------|-------|--------|\n`;
81
+ for (const content of response.data) {
82
+ markdown += `| ${truncate(content.title, 40)} | ${formatStatus(content.status)} | ${content.word_count || "-"} | ${formatDate(content.updated_at || content.created_at)} |\n`;
83
+ }
84
+ const { pagination } = response;
85
+ markdown += `\n**Showing ${response.data.length} of ${pagination.total} items**\n`;
86
+ if (pagination.has_more) {
87
+ markdown += `\n_More content available. Use list_content tool with page parameter to see more._\n`;
88
+ }
89
+ return markdown;
90
+ }
91
+ async function readContentDetails(contentId, context) {
92
+ const response = await context.client.get(`/content/${contentId}`, {}, CACHE_TTL.resources);
93
+ const content = response.data;
94
+ let markdown = `# ${content.title}\n\n`;
95
+ markdown += formatKeyValue({
96
+ ID: content.id,
97
+ Status: formatStatus(content.status),
98
+ "Word Count": content.word_count || "-",
99
+ URL: content.url || "-",
100
+ Created: formatDate(content.created_at),
101
+ Updated: content.updated_at ? formatDate(content.updated_at) : "-",
102
+ Published: content.published_at ? formatDate(content.published_at) : "-",
103
+ });
104
+ if (content.meta_title || content.meta_description) {
105
+ markdown += "\n## SEO Meta\n\n";
106
+ if (content.meta_title) {
107
+ markdown += `**Title:** ${content.meta_title}\n`;
108
+ }
109
+ if (content.meta_description) {
110
+ markdown += `**Description:** ${content.meta_description}\n`;
111
+ }
112
+ }
113
+ if (content.body) {
114
+ markdown += "\n## Content Body\n\n";
115
+ markdown += content.body;
116
+ }
117
+ else {
118
+ markdown += "\n_No content body available._\n";
119
+ }
120
+ return markdown;
121
+ }
122
+ // ============================================
123
+ // URI Matching
124
+ // ============================================
125
+ export function matchesContentUri(uri) {
126
+ return uri === CONTENT_URI || uri.startsWith(CONTENT_URI_PREFIX);
127
+ }
128
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/resources/content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Resource registry
3
+ *
4
+ * All MCP resources are registered here. Each resource module exports:
5
+ * - Resource templates (for URI patterns)
6
+ * - List function (for listing available resources)
7
+ * - Read function (for reading resource contents)
8
+ * - URI matching function (for routing)
9
+ */
10
+ import type { ToolContext } from "../types.js";
11
+ export interface McpResource {
12
+ uri: string;
13
+ name: string;
14
+ description: string;
15
+ mimeType: string;
16
+ }
17
+ export declare const ALL_RESOURCE_TEMPLATES: {
18
+ uriTemplate: string;
19
+ name: string;
20
+ description: string;
21
+ mimeType: string;
22
+ }[];
23
+ export declare function listAllResources(context: ToolContext): Promise<McpResource[]>;
24
+ export declare function readResource(uri: string, context: ToolContext): Promise<{
25
+ contents: Array<{
26
+ uri: string;
27
+ mimeType: string;
28
+ text: string;
29
+ }>;
30
+ }>;
31
+ export declare function getRootResources(): McpResource[];
32
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA+B/C,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAMD,eAAO,MAAM,sBAAsB;;;;;GAIlC,CAAC;AAMF,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,WAAW,EAAE,CAAC,CAQxB;AAMD,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CAsB/E;AAMD,wBAAgB,gBAAgB,IAAI,WAAW,EAAE,CAqBhD"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Resource registry
3
+ *
4
+ * All MCP resources are registered here. Each resource module exports:
5
+ * - Resource templates (for URI patterns)
6
+ * - List function (for listing available resources)
7
+ * - Read function (for reading resource contents)
8
+ * - URI matching function (for routing)
9
+ */
10
+ // Import resource modules
11
+ import { siteResourceTemplates, listSiteResources, readSiteResource, matchesSiteUri, SITES_URI, } from "./sites.js";
12
+ import { contentResourceTemplates, listContentResources, readContentResource, matchesContentUri, CONTENT_URI, } from "./content.js";
13
+ import { briefResourceTemplates, listBriefResources, readBriefResource, matchesBriefUri, BRIEFS_URI, } from "./briefs.js";
14
+ // ============================================
15
+ // Resource Templates
16
+ // ============================================
17
+ export const ALL_RESOURCE_TEMPLATES = [
18
+ ...siteResourceTemplates,
19
+ ...contentResourceTemplates,
20
+ ...briefResourceTemplates,
21
+ ];
22
+ // ============================================
23
+ // List All Resources
24
+ // ============================================
25
+ export async function listAllResources(context) {
26
+ const [sites, content, briefs] = await Promise.all([
27
+ listSiteResources(context),
28
+ listContentResources(context),
29
+ listBriefResources(context),
30
+ ]);
31
+ return [...sites, ...content, ...briefs];
32
+ }
33
+ // ============================================
34
+ // Read Resource
35
+ // ============================================
36
+ export async function readResource(uri, context) {
37
+ let text;
38
+ if (matchesSiteUri(uri)) {
39
+ text = await readSiteResource(uri, context);
40
+ }
41
+ else if (matchesContentUri(uri)) {
42
+ text = await readContentResource(uri, context);
43
+ }
44
+ else if (matchesBriefUri(uri)) {
45
+ text = await readBriefResource(uri, context);
46
+ }
47
+ else {
48
+ throw new Error(`Unknown resource URI: ${uri}`);
49
+ }
50
+ return {
51
+ contents: [
52
+ {
53
+ uri,
54
+ mimeType: "text/markdown",
55
+ text,
56
+ },
57
+ ],
58
+ };
59
+ }
60
+ // ============================================
61
+ // Get Root Resources
62
+ // ============================================
63
+ export function getRootResources() {
64
+ return [
65
+ {
66
+ uri: SITES_URI,
67
+ name: "Sites",
68
+ description: "All sites in your Frase account",
69
+ mimeType: "text/markdown",
70
+ },
71
+ {
72
+ uri: CONTENT_URI,
73
+ name: "Content",
74
+ description: "All content items in your Frase account",
75
+ mimeType: "text/markdown",
76
+ },
77
+ {
78
+ uri: BRIEFS_URI,
79
+ name: "Briefs",
80
+ description: "All content briefs in your Frase account",
81
+ mimeType: "text/markdown",
82
+ },
83
+ ];
84
+ }
85
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,0BAA0B;AAC1B,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,SAAS,GACV,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,GACZ,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EACjB,eAAe,EACf,UAAU,GACX,MAAM,aAAa,CAAC;AAarB,+CAA+C;AAC/C,qBAAqB;AACrB,+CAA+C;AAE/C,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,GAAG,qBAAqB;IACxB,GAAG,wBAAwB;IAC3B,GAAG,sBAAsB;CAC1B,CAAC;AAEF,+CAA+C;AAC/C,qBAAqB;AACrB,+CAA+C;AAE/C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAoB;IAEpB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACjD,iBAAiB,CAAC,OAAO,CAAC;QAC1B,oBAAoB,CAAC,OAAO,CAAC;QAC7B,kBAAkB,CAAC,OAAO,CAAC;KAC5B,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,KAAK,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED,+CAA+C;AAC/C,gBAAgB;AAChB,+CAA+C;AAE/C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,OAAoB;IAEpB,IAAI,IAAY,CAAC;IAEjB,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;SAAM,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,IAAI,GAAG,MAAM,mBAAmB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;SAAM,IAAI,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QAChC,IAAI,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,OAAO;QACL,QAAQ,EAAE;YACR;gBACE,GAAG;gBACH,QAAQ,EAAE,eAAe;gBACzB,IAAI;aACL;SACF;KACF,CAAC;AACJ,CAAC;AAED,+CAA+C;AAC/C,qBAAqB;AACrB,+CAA+C;AAE/C,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL;YACE,GAAG,EAAE,SAAS;YACd,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,iCAAiC;YAC9C,QAAQ,EAAE,eAAe;SAC1B;QACD;YACE,GAAG,EAAE,WAAW;YAChB,IAAI,EAAE,SAAS;YACf,WAAW,EAAE,yCAAyC;YACtD,QAAQ,EAAE,eAAe;SAC1B;QACD;YACE,GAAG,EAAE,UAAU;YACf,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,0CAA0C;YACvD,QAAQ,EAAE,eAAe;SAC1B;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Sites MCP Resources
3
+ *
4
+ * Expose sites as browsable MCP resources:
5
+ * - frase://sites - List of all sites
6
+ * - frase://sites/{id} - Individual site details
7
+ */
8
+ import type { ToolContext } from "../types.js";
9
+ export declare const SITES_URI = "frase://sites";
10
+ export declare const SITE_URI_PREFIX = "frase://sites/";
11
+ export declare const siteResourceTemplates: {
12
+ uriTemplate: string;
13
+ name: string;
14
+ description: string;
15
+ mimeType: string;
16
+ }[];
17
+ export interface SiteResource {
18
+ uri: string;
19
+ name: string;
20
+ description: string;
21
+ mimeType: string;
22
+ }
23
+ export declare function listSiteResources(context: ToolContext): Promise<SiteResource[]>;
24
+ export declare function readSiteResource(uri: string, context: ToolContext): Promise<string>;
25
+ export declare function matchesSiteUri(uri: string): boolean;
26
+ //# sourceMappingURL=sites.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sites.d.ts","sourceRoot":"","sources":["../../src/resources/sites.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,WAAW,EAIZ,MAAM,aAAa,CAAC;AAQrB,eAAO,MAAM,SAAS,kBAAkB,CAAC;AACzC,eAAO,MAAM,eAAe,mBAAmB,CAAC;AAMhD,eAAO,MAAM,qBAAqB;;;;;GAOjC,CAAC;AAMF,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,YAAY,EAAE,CAAC,CAuCzB;AAMD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,CAWjB;AAyDD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Sites MCP Resources
3
+ *
4
+ * Expose sites as browsable MCP resources:
5
+ * - frase://sites - List of all sites
6
+ * - frase://sites/{id} - Individual site details
7
+ */
8
+ import { CACHE_TTL } from "../cache.js";
9
+ import { formatKeyValue, formatDate } from "../formatter.js";
10
+ // ============================================
11
+ // Resource URIs
12
+ // ============================================
13
+ export const SITES_URI = "frase://sites";
14
+ export const SITE_URI_PREFIX = "frase://sites/";
15
+ // ============================================
16
+ // Resource Templates
17
+ // ============================================
18
+ export const siteResourceTemplates = [
19
+ {
20
+ uriTemplate: "frase://sites/{site_id}",
21
+ name: "Site",
22
+ description: "A specific Frase site with GSC connection status",
23
+ mimeType: "text/markdown",
24
+ },
25
+ ];
26
+ export async function listSiteResources(context) {
27
+ try {
28
+ const response = await context.client.get("/sites", { page: 1, page_size: 100 }, CACHE_TTL.lists);
29
+ const resources = [
30
+ {
31
+ uri: SITES_URI,
32
+ name: "All Sites",
33
+ description: "List of all sites in your Frase account",
34
+ mimeType: "text/markdown",
35
+ },
36
+ ];
37
+ // Add individual site resources
38
+ for (const site of response.data) {
39
+ resources.push({
40
+ uri: `${SITE_URI_PREFIX}${site.id}`,
41
+ name: site.name || site.domain,
42
+ description: `Site: ${site.domain}${site.gsc_connected ? " (GSC connected)" : ""}`,
43
+ mimeType: "text/markdown",
44
+ });
45
+ }
46
+ return resources;
47
+ }
48
+ catch {
49
+ // Return just the list resource if we can't fetch sites
50
+ return [
51
+ {
52
+ uri: SITES_URI,
53
+ name: "All Sites",
54
+ description: "List of all sites in your Frase account",
55
+ mimeType: "text/markdown",
56
+ },
57
+ ];
58
+ }
59
+ }
60
+ // ============================================
61
+ // Read Resource
62
+ // ============================================
63
+ export async function readSiteResource(uri, context) {
64
+ if (uri === SITES_URI) {
65
+ return readSitesList(context);
66
+ }
67
+ if (uri.startsWith(SITE_URI_PREFIX)) {
68
+ const siteId = uri.slice(SITE_URI_PREFIX.length);
69
+ return readSiteDetails(siteId, context);
70
+ }
71
+ throw new Error(`Unknown site resource URI: ${uri}`);
72
+ }
73
+ async function readSitesList(context) {
74
+ const response = await context.client.get("/sites", { page: 1, page_size: 100 }, CACHE_TTL.lists);
75
+ let markdown = "# Your Sites\n\n";
76
+ if (response.data.length === 0) {
77
+ markdown += "_No sites found. Connect a site in the Frase dashboard._\n";
78
+ return markdown;
79
+ }
80
+ markdown += `| Name | Domain | GSC | Created |\n`;
81
+ markdown += `|------|--------|-----|--------|\n`;
82
+ for (const site of response.data) {
83
+ const gsc = site.gsc_connected ? "Connected" : "-";
84
+ markdown += `| ${site.name || "-"} | ${site.domain} | ${gsc} | ${formatDate(site.created_at)} |\n`;
85
+ }
86
+ markdown += `\n**Total:** ${response.data.length} site(s)\n`;
87
+ return markdown;
88
+ }
89
+ async function readSiteDetails(siteId, context) {
90
+ const response = await context.client.get(`/sites/${siteId}`, {}, CACHE_TTL.resources);
91
+ const site = response.data;
92
+ let markdown = `# Site: ${site.name || site.domain}\n\n`;
93
+ markdown += formatKeyValue({
94
+ ID: site.id,
95
+ Domain: site.domain,
96
+ "GSC Connected": site.gsc_connected ? "Yes" : "No",
97
+ Created: formatDate(site.created_at),
98
+ Updated: site.updated_at ? formatDate(site.updated_at) : "-",
99
+ });
100
+ return markdown;
101
+ }
102
+ // ============================================
103
+ // URI Matching
104
+ // ============================================
105
+ export function matchesSiteUri(uri) {
106
+ return uri === SITES_URI || uri.startsWith(SITE_URI_PREFIX);
107
+ }
108
+ //# sourceMappingURL=sites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sites.js","sourceRoot":"","sources":["../../src/resources/sites.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * AI Visibility tools
3
+ *
4
+ * Track how your content appears in AI-powered search results
5
+ */
6
+ import type { McpToolDefinition, ToolContext, ToolResult } from "../types.js";
7
+ export declare const getAiVisibilityTool: McpToolDefinition;
8
+ export declare function executeGetAiVisibility(input: unknown, context: ToolContext): Promise<ToolResult>;
9
+ export declare const listPromptsTool: McpToolDefinition;
10
+ export declare function executeListPrompts(input: unknown, context: ToolContext): Promise<ToolResult>;
11
+ export declare const createPromptTool: McpToolDefinition;
12
+ export declare function executeCreatePrompt(input: unknown, context: ToolContext): Promise<ToolResult>;
13
+ export declare const getPromptTool: McpToolDefinition;
14
+ export declare function executeGetPrompt(input: unknown, context: ToolContext): Promise<ToolResult>;
15
+ export declare const updatePromptTool: McpToolDefinition;
16
+ export declare function executeUpdatePrompt(input: unknown, context: ToolContext): Promise<ToolResult>;
17
+ export declare const getCompetitorsTool: McpToolDefinition;
18
+ export declare function executeGetCompetitors(input: unknown, context: ToolContext): Promise<ToolResult>;
19
+ export declare const getAlertsTool: McpToolDefinition;
20
+ export declare function executeGetAlerts(input: unknown, context: ToolContext): Promise<ToolResult>;
21
+ export declare const getInsightsTool: McpToolDefinition;
22
+ export declare function executeGetInsights(input: unknown, context: ToolContext): Promise<ToolResult>;
23
+ export declare const aiVisibilityTools: McpToolDefinition[];
24
+ export declare const aiVisibilityExecutors: Record<string, (input: unknown, context: ToolContext) => Promise<ToolResult>>;
25
+ //# sourceMappingURL=ai-visibility.d.ts.map
@@ -0,0 +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;AAqFrB,eAAO,MAAM,mBAAmB,EAAE,iBAajC,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAkDrB;AAYD,eAAO,MAAM,eAAe,EAAE,iBAoB7B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CA6CrB;AAWD,eAAO,MAAM,gBAAgB,EAAE,iBAiB9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoCrB;AAUD,eAAO,MAAM,aAAa,EAAE,iBAa3B,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAqDrB;AAYD,eAAO,MAAM,gBAAgB,EAAE,iBAqB9B,CAAC;AAEF,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAoCrB;AAWD,eAAO,MAAM,kBAAkB,EAAE,iBAgBhC,CAAC;AAEF,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAsDrB;AAWD,eAAO,MAAM,aAAa,EAAE,iBAgB3B,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAqDrB;AAUD,eAAO,MAAM,eAAe,EAAE,iBAY7B,CAAC;AAEF,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAgDrB;AAMD,eAAO,MAAM,iBAAiB,EAAE,iBAAiB,EAShD,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,MAAM,CACxC,MAAM,EACN,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAU9D,CAAC"}