@heyseo/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 (46) hide show
  1. package/README.md +284 -0
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +258 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/prompts/index.d.ts +22 -0
  7. package/dist/prompts/index.d.ts.map +1 -0
  8. package/dist/prompts/index.js +267 -0
  9. package/dist/prompts/index.js.map +1 -0
  10. package/dist/resources/index.d.ts +38 -0
  11. package/dist/resources/index.d.ts.map +1 -0
  12. package/dist/resources/index.js +247 -0
  13. package/dist/resources/index.js.map +1 -0
  14. package/dist/tools/comparison.d.ts +159 -0
  15. package/dist/tools/comparison.d.ts.map +1 -0
  16. package/dist/tools/comparison.js +482 -0
  17. package/dist/tools/comparison.js.map +1 -0
  18. package/dist/tools/ga4.d.ts +182 -0
  19. package/dist/tools/ga4.d.ts.map +1 -0
  20. package/dist/tools/ga4.js +429 -0
  21. package/dist/tools/ga4.js.map +1 -0
  22. package/dist/tools/gsc.d.ts +194 -0
  23. package/dist/tools/gsc.d.ts.map +1 -0
  24. package/dist/tools/gsc.js +348 -0
  25. package/dist/tools/gsc.js.map +1 -0
  26. package/dist/tools/index.d.ts +392 -0
  27. package/dist/tools/index.d.ts.map +1 -0
  28. package/dist/tools/index.js +59 -0
  29. package/dist/tools/index.js.map +1 -0
  30. package/dist/tools/pagespeed.d.ts +88 -0
  31. package/dist/tools/pagespeed.d.ts.map +1 -0
  32. package/dist/tools/pagespeed.js +285 -0
  33. package/dist/tools/pagespeed.js.map +1 -0
  34. package/dist/tools/tasks.d.ts +71 -0
  35. package/dist/tools/tasks.d.ts.map +1 -0
  36. package/dist/tools/tasks.js +116 -0
  37. package/dist/tools/tasks.js.map +1 -0
  38. package/dist/types.d.ts +151 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +5 -0
  41. package/dist/types.js.map +1 -0
  42. package/dist/utils/api-client.d.ts +69 -0
  43. package/dist/utils/api-client.d.ts.map +1 -0
  44. package/dist/utils/api-client.js +202 -0
  45. package/dist/utils/api-client.js.map +1 -0
  46. package/package.json +42 -0
@@ -0,0 +1,267 @@
1
+ /**
2
+ * MCP Prompt Templates
3
+ * Pre-built prompts for common SEO analysis tasks
4
+ */
5
+ export const promptTemplates = [
6
+ {
7
+ name: 'seo_audit',
8
+ description: 'Perform a comprehensive SEO audit for a site, analyzing performance, keywords, pages, and technical factors.',
9
+ arguments: [
10
+ {
11
+ name: 'siteId',
12
+ description: 'The ID of the site to audit',
13
+ required: true,
14
+ },
15
+ {
16
+ name: 'focus',
17
+ description: 'Optional focus area: "technical", "content", "keywords", or "all" (default)',
18
+ required: false,
19
+ },
20
+ ],
21
+ },
22
+ {
23
+ name: 'weekly_report',
24
+ description: 'Generate a weekly SEO performance report with comparisons to the previous week.',
25
+ arguments: [
26
+ {
27
+ name: 'siteId',
28
+ description: 'The ID of the site to report on',
29
+ required: true,
30
+ },
31
+ ],
32
+ },
33
+ {
34
+ name: 'keyword_research',
35
+ description: 'Analyze current keyword performance and identify opportunities for improvement.',
36
+ arguments: [
37
+ {
38
+ name: 'siteId',
39
+ description: 'The ID of the site to analyze',
40
+ required: true,
41
+ },
42
+ {
43
+ name: 'targetKeyword',
44
+ description: 'Optional specific keyword to research',
45
+ required: false,
46
+ },
47
+ ],
48
+ },
49
+ {
50
+ name: 'content_optimization',
51
+ description: 'Get recommendations for optimizing a specific page or content piece for better SEO.',
52
+ arguments: [
53
+ {
54
+ name: 'siteId',
55
+ description: 'The ID of the site',
56
+ required: true,
57
+ },
58
+ {
59
+ name: 'pageUrl',
60
+ description: 'The URL or path of the page to optimize',
61
+ required: true,
62
+ },
63
+ ],
64
+ },
65
+ {
66
+ name: 'technical_health_check',
67
+ description: 'Run a technical SEO health check including Core Web Vitals and performance analysis.',
68
+ arguments: [
69
+ {
70
+ name: 'url',
71
+ description: 'The URL to analyze',
72
+ required: true,
73
+ },
74
+ ],
75
+ },
76
+ {
77
+ name: 'traffic_analysis',
78
+ description: 'Analyze traffic patterns, sources, and user engagement for a site.',
79
+ arguments: [
80
+ {
81
+ name: 'siteId',
82
+ description: 'The ID of the site to analyze',
83
+ required: true,
84
+ },
85
+ {
86
+ name: 'period',
87
+ description: 'Time period: "7d", "28d", "90d" (default: 28d)',
88
+ required: false,
89
+ },
90
+ ],
91
+ },
92
+ {
93
+ name: 'quick_wins',
94
+ description: 'Identify quick-win SEO opportunities that can be implemented with minimal effort.',
95
+ arguments: [
96
+ {
97
+ name: 'siteId',
98
+ description: 'The ID of the site to analyze',
99
+ required: true,
100
+ },
101
+ ],
102
+ },
103
+ {
104
+ name: 'ranking_changes',
105
+ description: 'Analyze recent ranking changes and identify keywords that gained or lost positions.',
106
+ arguments: [
107
+ {
108
+ name: 'siteId',
109
+ description: 'The ID of the site to analyze',
110
+ required: true,
111
+ },
112
+ {
113
+ name: 'threshold',
114
+ description: 'Minimum position change to report (default: 3)',
115
+ required: false,
116
+ },
117
+ ],
118
+ },
119
+ ];
120
+ /**
121
+ * Generate prompt messages for a template
122
+ */
123
+ export function generatePromptMessages(templateName, args) {
124
+ switch (templateName) {
125
+ case 'seo_audit':
126
+ return [
127
+ {
128
+ role: 'user',
129
+ content: `Please perform a comprehensive SEO audit for site ${args.siteId}.
130
+
131
+ ${args.focus && args.focus !== 'all' ? `Focus specifically on ${args.focus} aspects.` : 'Cover all aspects: technical, content, keywords, and performance.'}
132
+
133
+ Include:
134
+ 1. Current performance metrics (clicks, impressions, CTR, position)
135
+ 2. Top performing and underperforming keywords
136
+ 3. Page performance analysis
137
+ 4. Technical health (if applicable)
138
+ 5. Specific recommendations with priority levels
139
+ 6. Create tasks for the top 3-5 action items`,
140
+ },
141
+ ];
142
+ case 'weekly_report':
143
+ return [
144
+ {
145
+ role: 'user',
146
+ content: `Generate a weekly SEO performance report for site ${args.siteId}.
147
+
148
+ Compare this week's performance to last week and include:
149
+ 1. Executive summary with key metrics
150
+ 2. Week-over-week changes (clicks, impressions, CTR, position)
151
+ 3. Top gaining keywords (improved rankings)
152
+ 4. Top losing keywords (declined rankings)
153
+ 5. Notable achievements or concerns
154
+ 6. Recommended actions for next week`,
155
+ },
156
+ ];
157
+ case 'keyword_research':
158
+ return [
159
+ {
160
+ role: 'user',
161
+ content: `Analyze keyword performance for site ${args.siteId}${args.targetKeyword ? ` with focus on "${args.targetKeyword}"` : ''}.
162
+
163
+ Include:
164
+ 1. Current top performing keywords
165
+ 2. Keywords with high impressions but low CTR (opportunities)
166
+ 3. Keywords ranking on page 2 that could reach page 1
167
+ 4. Related keyword opportunities
168
+ 5. Content recommendations for target keywords
169
+ 6. Priority ranking of keywords to focus on`,
170
+ },
171
+ ];
172
+ case 'content_optimization':
173
+ return [
174
+ {
175
+ role: 'user',
176
+ content: `Provide content optimization recommendations for the page at ${args.pageUrl} on site ${args.siteId}.
177
+
178
+ Analyze:
179
+ 1. Current search performance for this page
180
+ 2. Keywords this page ranks for
181
+ 3. CTR performance and opportunities
182
+ 4. Technical factors (if URL provided, run PageSpeed analysis)
183
+ 5. Content improvement suggestions
184
+ 6. Internal linking opportunities
185
+ 7. Create actionable tasks for optimization`,
186
+ },
187
+ ];
188
+ case 'technical_health_check':
189
+ return [
190
+ {
191
+ role: 'user',
192
+ content: `Run a technical SEO health check for ${args.url}.
193
+
194
+ Analyze:
195
+ 1. Core Web Vitals (LCP, INP, CLS)
196
+ 2. Performance score and factors
197
+ 3. Loading performance (FCP, TTFB)
198
+ 4. Top optimization opportunities
199
+ 5. Mobile vs desktop comparison (if helpful)
200
+ 6. Priority fixes with estimated impact
201
+ 7. Create tasks for critical issues`,
202
+ },
203
+ ];
204
+ case 'traffic_analysis':
205
+ return [
206
+ {
207
+ role: 'user',
208
+ content: `Analyze traffic patterns for site ${args.siteId} over the last ${args.period || '28d'}.
209
+
210
+ Include:
211
+ 1. Overall traffic metrics (sessions, users, engagement)
212
+ 2. Traffic source breakdown (organic, direct, referral, social)
213
+ 3. Top landing pages and their performance
214
+ 4. Device category breakdown
215
+ 5. Engagement metrics (bounce rate, session duration)
216
+ 6. Trends and patterns observed
217
+ 7. Recommendations for traffic growth`,
218
+ },
219
+ ];
220
+ case 'quick_wins':
221
+ return [
222
+ {
223
+ role: 'user',
224
+ content: `Find quick-win SEO opportunities for site ${args.siteId}.
225
+
226
+ Look for:
227
+ 1. Low-hanging fruit keywords (good position, low CTR)
228
+ 2. Pages almost ranking on page 1
229
+ 3. High-impression, low-click pages
230
+ 4. Simple technical fixes
231
+ 5. Quick content improvements
232
+
233
+ For each opportunity:
234
+ - Explain why it's a quick win
235
+ - Estimate potential impact
236
+ - Provide specific action steps
237
+ - Create a task if appropriate
238
+
239
+ Focus on changes that can be implemented within a day and show results within weeks.`,
240
+ },
241
+ ];
242
+ case 'ranking_changes':
243
+ return [
244
+ {
245
+ role: 'user',
246
+ content: `Analyze recent ranking changes for site ${args.siteId}.
247
+
248
+ Compare the last 7 days to the previous 7 days and identify:
249
+ 1. Keywords that improved by ${args.threshold || '3'}+ positions
250
+ 2. Keywords that declined by ${args.threshold || '3'}+ positions
251
+ 3. New keywords ranking in top 20
252
+ 4. Keywords that fell out of top 20
253
+ 5. Possible causes for significant changes
254
+ 6. Recommended actions to address declines
255
+ 7. Opportunities to capitalize on improvements`,
256
+ },
257
+ ];
258
+ default:
259
+ return [
260
+ {
261
+ role: 'user',
262
+ content: `Run the ${templateName} analysis with the provided parameters.`,
263
+ },
264
+ ];
265
+ }
266
+ }
267
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/prompts/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * MCP Resources
3
+ * Exposes HeySeo data as readable resources
4
+ */
5
+ import type { HeySeoApiClient } from '../utils/api-client.js';
6
+ /**
7
+ * Resource template definitions
8
+ */
9
+ export declare const resourceTemplates: {
10
+ uriTemplate: string;
11
+ name: string;
12
+ description: string;
13
+ mimeType: string;
14
+ }[];
15
+ /**
16
+ * Parse resource URI to extract type and parameters
17
+ */
18
+ export declare function parseResourceUri(uri: string): {
19
+ type: 'sites' | 'site' | 'overview' | 'keywords' | 'pages';
20
+ siteId?: string;
21
+ } | null;
22
+ /**
23
+ * Fetch resource content
24
+ */
25
+ export declare function fetchResource(client: HeySeoApiClient, uri: string): Promise<{
26
+ content: string;
27
+ mimeType: string;
28
+ }>;
29
+ /**
30
+ * List available resources for a client
31
+ */
32
+ export declare function listResources(client: HeySeoApiClient): Promise<Array<{
33
+ uri: string;
34
+ name: string;
35
+ description: string;
36
+ mimeType: string;
37
+ }>>;
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;GA+B7B,CAAC;AAEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG;IAC7C,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,IAAI,CA+BP;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,eAAe,EACvB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA0JhD;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAsDtF"}
@@ -0,0 +1,247 @@
1
+ /**
2
+ * MCP Resources
3
+ * Exposes HeySeo data as readable resources
4
+ */
5
+ /**
6
+ * Resource template definitions
7
+ */
8
+ export const resourceTemplates = [
9
+ {
10
+ uriTemplate: 'heyseo://sites',
11
+ name: 'Connected Sites',
12
+ description: 'List all sites connected to your HeySeo account',
13
+ mimeType: 'application/json',
14
+ },
15
+ {
16
+ uriTemplate: 'heyseo://sites/{siteId}',
17
+ name: 'Site Details',
18
+ description: 'Get details for a specific connected site',
19
+ mimeType: 'application/json',
20
+ },
21
+ {
22
+ uriTemplate: 'heyseo://sites/{siteId}/overview',
23
+ name: 'Site Overview',
24
+ description: 'Get current SEO metrics overview for a site (last 28 days)',
25
+ mimeType: 'application/json',
26
+ },
27
+ {
28
+ uriTemplate: 'heyseo://sites/{siteId}/keywords',
29
+ name: 'Top Keywords',
30
+ description: 'Get top 50 keywords for a site',
31
+ mimeType: 'application/json',
32
+ },
33
+ {
34
+ uriTemplate: 'heyseo://sites/{siteId}/pages',
35
+ name: 'Top Pages',
36
+ description: 'Get top 50 pages for a site',
37
+ mimeType: 'application/json',
38
+ },
39
+ ];
40
+ /**
41
+ * Parse resource URI to extract type and parameters
42
+ */
43
+ export function parseResourceUri(uri) {
44
+ // heyseo://sites
45
+ if (uri === 'heyseo://sites') {
46
+ return { type: 'sites' };
47
+ }
48
+ // heyseo://sites/{siteId}
49
+ const siteMatch = uri.match(/^heyseo:\/\/sites\/([^/]+)$/);
50
+ if (siteMatch) {
51
+ return { type: 'site', siteId: siteMatch[1] };
52
+ }
53
+ // heyseo://sites/{siteId}/overview
54
+ const overviewMatch = uri.match(/^heyseo:\/\/sites\/([^/]+)\/overview$/);
55
+ if (overviewMatch) {
56
+ return { type: 'overview', siteId: overviewMatch[1] };
57
+ }
58
+ // heyseo://sites/{siteId}/keywords
59
+ const keywordsMatch = uri.match(/^heyseo:\/\/sites\/([^/]+)\/keywords$/);
60
+ if (keywordsMatch) {
61
+ return { type: 'keywords', siteId: keywordsMatch[1] };
62
+ }
63
+ // heyseo://sites/{siteId}/pages
64
+ const pagesMatch = uri.match(/^heyseo:\/\/sites\/([^/]+)\/pages$/);
65
+ if (pagesMatch) {
66
+ return { type: 'pages', siteId: pagesMatch[1] };
67
+ }
68
+ return null;
69
+ }
70
+ /**
71
+ * Fetch resource content
72
+ */
73
+ export async function fetchResource(client, uri) {
74
+ const parsed = parseResourceUri(uri);
75
+ if (!parsed) {
76
+ throw new Error(`Invalid resource URI: ${uri}`);
77
+ }
78
+ const endDate = new Date().toISOString().split('T')[0];
79
+ const startDate = new Date(Date.now() - 28 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
80
+ switch (parsed.type) {
81
+ case 'sites': {
82
+ const sites = await client.getSites();
83
+ return {
84
+ content: JSON.stringify({
85
+ totalSites: sites.length,
86
+ sites: sites.map((s) => ({
87
+ id: s.id,
88
+ url: s.url,
89
+ name: s.name,
90
+ gscConnected: s.gscConnected,
91
+ ga4Connected: s.ga4Connected,
92
+ })),
93
+ }, null, 2),
94
+ mimeType: 'application/json',
95
+ };
96
+ }
97
+ case 'site': {
98
+ if (!parsed.siteId)
99
+ throw new Error('Site ID required');
100
+ const site = await client.getSite(parsed.siteId);
101
+ return {
102
+ content: JSON.stringify({
103
+ id: site.id,
104
+ url: site.url,
105
+ name: site.name,
106
+ gscConnected: site.gscConnected,
107
+ ga4Connected: site.ga4Connected,
108
+ ga4PropertyId: site.ga4PropertyId,
109
+ }, null, 2),
110
+ mimeType: 'application/json',
111
+ };
112
+ }
113
+ case 'overview': {
114
+ if (!parsed.siteId)
115
+ throw new Error('Site ID required');
116
+ const overview = await client.getSiteOverview(parsed.siteId, { startDate, endDate });
117
+ const gscMetrics = overview.gsc.rows[0] || {
118
+ clicks: 0,
119
+ impressions: 0,
120
+ ctr: 0,
121
+ position: 0,
122
+ };
123
+ const ga4Metrics = overview.ga4[0]?.metrics || {};
124
+ return {
125
+ content: JSON.stringify({
126
+ period: { startDate, endDate },
127
+ gsc: {
128
+ clicks: gscMetrics.clicks,
129
+ impressions: gscMetrics.impressions,
130
+ ctr: `${(gscMetrics.ctr * 100).toFixed(2)}%`,
131
+ avgPosition: gscMetrics.position.toFixed(1),
132
+ },
133
+ ga4: {
134
+ sessions: ga4Metrics.sessions || 0,
135
+ activeUsers: ga4Metrics.activeUsers || 0,
136
+ newUsers: ga4Metrics.newUsers || 0,
137
+ bounceRate: ga4Metrics.bounceRate
138
+ ? `${(ga4Metrics.bounceRate * 100).toFixed(1)}%`
139
+ : 'N/A',
140
+ engagementRate: ga4Metrics.engagementRate
141
+ ? `${(ga4Metrics.engagementRate * 100).toFixed(1)}%`
142
+ : 'N/A',
143
+ },
144
+ }, null, 2),
145
+ mimeType: 'application/json',
146
+ };
147
+ }
148
+ case 'keywords': {
149
+ if (!parsed.siteId)
150
+ throw new Error('Site ID required');
151
+ const keywords = await client.getTopKeywords(parsed.siteId, {
152
+ startDate,
153
+ endDate,
154
+ limit: 50,
155
+ });
156
+ return {
157
+ content: JSON.stringify({
158
+ period: { startDate, endDate },
159
+ totalKeywords: keywords.rows.length,
160
+ keywords: keywords.rows.map((row, i) => ({
161
+ rank: i + 1,
162
+ keyword: row.keys[0],
163
+ clicks: row.clicks,
164
+ impressions: row.impressions,
165
+ ctr: `${(row.ctr * 100).toFixed(2)}%`,
166
+ position: row.position.toFixed(1),
167
+ })),
168
+ }, null, 2),
169
+ mimeType: 'application/json',
170
+ };
171
+ }
172
+ case 'pages': {
173
+ if (!parsed.siteId)
174
+ throw new Error('Site ID required');
175
+ const pages = await client.getTopPages(parsed.siteId, {
176
+ startDate,
177
+ endDate,
178
+ limit: 50,
179
+ });
180
+ return {
181
+ content: JSON.stringify({
182
+ period: { startDate, endDate },
183
+ totalPages: pages.rows.length,
184
+ pages: pages.rows.map((row, i) => ({
185
+ rank: i + 1,
186
+ page: row.keys[0],
187
+ clicks: row.clicks,
188
+ impressions: row.impressions,
189
+ ctr: `${(row.ctr * 100).toFixed(2)}%`,
190
+ position: row.position.toFixed(1),
191
+ })),
192
+ }, null, 2),
193
+ mimeType: 'application/json',
194
+ };
195
+ }
196
+ default:
197
+ throw new Error(`Unknown resource type: ${parsed.type}`);
198
+ }
199
+ }
200
+ /**
201
+ * List available resources for a client
202
+ */
203
+ export async function listResources(client) {
204
+ const resources = [];
205
+ // Always include sites list
206
+ resources.push({
207
+ uri: 'heyseo://sites',
208
+ name: 'Connected Sites',
209
+ description: 'List all sites connected to your HeySeo account',
210
+ mimeType: 'application/json',
211
+ });
212
+ // Fetch sites and add resources for each
213
+ try {
214
+ const sites = await client.getSites();
215
+ for (const site of sites) {
216
+ resources.push({
217
+ uri: `heyseo://sites/${site.id}`,
218
+ name: `Site: ${site.name || site.url}`,
219
+ description: `Details for ${site.url}`,
220
+ mimeType: 'application/json',
221
+ });
222
+ resources.push({
223
+ uri: `heyseo://sites/${site.id}/overview`,
224
+ name: `Overview: ${site.name || site.url}`,
225
+ description: `SEO metrics overview for ${site.url}`,
226
+ mimeType: 'application/json',
227
+ });
228
+ resources.push({
229
+ uri: `heyseo://sites/${site.id}/keywords`,
230
+ name: `Keywords: ${site.name || site.url}`,
231
+ description: `Top keywords for ${site.url}`,
232
+ mimeType: 'application/json',
233
+ });
234
+ resources.push({
235
+ uri: `heyseo://sites/${site.id}/pages`,
236
+ name: `Pages: ${site.name || site.url}`,
237
+ description: `Top pages for ${site.url}`,
238
+ mimeType: 'application/json',
239
+ });
240
+ }
241
+ }
242
+ catch {
243
+ // If we can't fetch sites, just return the template
244
+ }
245
+ return resources;
246
+ }
247
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"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"}