peeptrend-mcp 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.
- package/LICENSE +21 -0
- package/README.md +100 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +67 -0
- package/dist/cli.js.map +1 -0
- package/dist/client.d.ts +50 -0
- package/dist/client.js +125 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.js +17 -0
- package/dist/config.js.map +1 -0
- package/dist/format.d.ts +12 -0
- package/dist/format.js +150 -0
- package/dist/format.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +32 -0
- package/dist/server.js.map +1 -0
- package/dist/tools.d.ts +3 -0
- package/dist/tools.js +198 -0
- package/dist/tools.js.map +1 -0
- package/dist/types.d.ts +252 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/integrations/claude/README.md +23 -0
- package/integrations/codex/README.md +27 -0
- package/integrations/mcp/README.md +25 -0
- package/integrations/openclaw/README.md +23 -0
- package/mcp-registry/server.json +30 -0
- package/package.json +59 -0
- package/plugins/peeptrend-youtube-gaming-trend-finder/.codex-plugin/plugin.json +33 -0
- package/plugins/peeptrend-youtube-gaming-trend-finder/.mcp.json +11 -0
- package/plugins/peeptrend-youtube-gaming-trend-finder/skills/youtube-gaming-trend-finder/SKILL.md +27 -0
- package/skills/claude/peeptrend-youtube-gaming-trend-finder/SKILL.md +13 -0
- package/skills/openclaw/youtube-gaming-trend-finder/SKILL.md +11 -0
package/dist/tools.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { authStatus } from "./config.js";
|
|
3
|
+
import { PeepTrendClient, youtubeResearchPaths } from "./client.js";
|
|
4
|
+
import { PeepTrendApiError } from "./types.js";
|
|
5
|
+
import { formatChannelNameResult, formatConnectionStatus, formatGameCheckerResult, formatOpportunities, formatOpportunityDetail, formatTitleResult, formatYoutubeResearchResult } from "./format.js";
|
|
6
|
+
const periodSchema = z.enum(["7d", "30d", "90d", "180d", "365d"]).default("30d");
|
|
7
|
+
const marketRegionSchema = z.string().min(2).max(12).default("US");
|
|
8
|
+
const marketLanguageSchema = z.string().min(2).max(12).default("en");
|
|
9
|
+
function ok(text, data) {
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: "text", text }],
|
|
12
|
+
structuredContent: data === undefined ? undefined : { data }
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function fail(error) {
|
|
16
|
+
if (error instanceof PeepTrendApiError) {
|
|
17
|
+
const hint = error.upgradeUrl ? `\n\nContinue in PeepTrend: ${error.upgradeUrl}` : "";
|
|
18
|
+
return {
|
|
19
|
+
isError: true,
|
|
20
|
+
content: [{ type: "text", text: `${error.message}${hint}` }],
|
|
21
|
+
structuredContent: {
|
|
22
|
+
error: {
|
|
23
|
+
status: error.status,
|
|
24
|
+
code: error.code ?? error.name,
|
|
25
|
+
upgradeUrl: error.upgradeUrl ?? null
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
isError: true,
|
|
32
|
+
content: [{ type: "text", text: error instanceof Error ? error.message : "PeepTrend MCP tool failed." }]
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
async function safeRun(fn) {
|
|
36
|
+
try {
|
|
37
|
+
return await fn();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
return fail(error);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function registerPeepTrendTools(server, config) {
|
|
44
|
+
const client = new PeepTrendClient(config);
|
|
45
|
+
server.registerTool("get_peeptrend_connection_status", {
|
|
46
|
+
title: "PeepTrend connection status",
|
|
47
|
+
description: "Show whether this MCP server is connected anonymously or with a PeepTrend API key."
|
|
48
|
+
}, async () => ok(formatConnectionStatus({
|
|
49
|
+
authenticated: authStatus(config) === "authenticated",
|
|
50
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
51
|
+
websiteBaseUrl: config.websiteBaseUrl
|
|
52
|
+
}), {
|
|
53
|
+
authenticated: authStatus(config) === "authenticated",
|
|
54
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
55
|
+
websiteBaseUrl: config.websiteBaseUrl
|
|
56
|
+
}));
|
|
57
|
+
server.registerTool("check_youtube_channel_name", {
|
|
58
|
+
title: "Check YouTube channel name",
|
|
59
|
+
description: "Check whether a channel name or handle collides with returned YouTube channel results.",
|
|
60
|
+
inputSchema: {
|
|
61
|
+
query: z.string().trim().min(1).max(60).describe("Channel name or handle idea, for example 'CozyPixel'.")
|
|
62
|
+
}
|
|
63
|
+
}, async ({ query }) => safeRun(async () => {
|
|
64
|
+
const result = await client.checkYoutubeChannelName(query);
|
|
65
|
+
return ok(formatChannelNameResult(result), result);
|
|
66
|
+
}));
|
|
67
|
+
server.registerTool("check_youtube_title", {
|
|
68
|
+
title: "Check YouTube video title",
|
|
69
|
+
description: "Compare a gaming video title or keyword against recent YouTube videos, demand, competition, and title overlap.",
|
|
70
|
+
inputSchema: {
|
|
71
|
+
query: z.string().trim().min(1).max(100).describe("Video title or keyword idea."),
|
|
72
|
+
period: periodSchema.describe("Recent search window.")
|
|
73
|
+
}
|
|
74
|
+
}, async ({ query, period }) => safeRun(async () => {
|
|
75
|
+
const result = await client.checkYoutubeTitle(query, period);
|
|
76
|
+
return ok(formatTitleResult(result), result);
|
|
77
|
+
}));
|
|
78
|
+
server.registerTool("check_youtube_shelf_saturation", {
|
|
79
|
+
title: "Check YouTube shelf saturation",
|
|
80
|
+
description: "Check whether a gaming topic shelf is already crowded or still has room for a sharper angle.",
|
|
81
|
+
inputSchema: {
|
|
82
|
+
query: z.string().trim().min(1).max(180),
|
|
83
|
+
period: periodSchema
|
|
84
|
+
}
|
|
85
|
+
}, async ({ query, period }) => safeRun(async () => {
|
|
86
|
+
const result = await client.checkYoutubeResearchTool(youtubeResearchPaths.shelf, query, period);
|
|
87
|
+
return ok(formatYoutubeResearchResult(result), result);
|
|
88
|
+
}));
|
|
89
|
+
server.registerTool("check_gaming_niche", {
|
|
90
|
+
title: "Check gaming niche",
|
|
91
|
+
description: "Evaluate a gaming niche for demand, creator pressure, opportunity, and small-channel fit.",
|
|
92
|
+
inputSchema: {
|
|
93
|
+
query: z.string().trim().min(1).max(180),
|
|
94
|
+
period: periodSchema
|
|
95
|
+
}
|
|
96
|
+
}, async ({ query, period }) => safeRun(async () => {
|
|
97
|
+
const result = await client.checkYoutubeResearchTool(youtubeResearchPaths.niche, query, period);
|
|
98
|
+
return ok(formatYoutubeResearchResult(result), result);
|
|
99
|
+
}));
|
|
100
|
+
server.registerTool("check_steam_update_opportunity", {
|
|
101
|
+
title: "Check Steam update opportunity",
|
|
102
|
+
description: "Check whether a Steam update, patch, DLC, comeback, or event may be worth covering on YouTube.",
|
|
103
|
+
inputSchema: {
|
|
104
|
+
query: z.string().trim().min(1).max(180),
|
|
105
|
+
period: periodSchema
|
|
106
|
+
}
|
|
107
|
+
}, async ({ query, period }) => safeRun(async () => {
|
|
108
|
+
const result = await client.checkYoutubeResearchTool(youtubeResearchPaths.steamUpdate, query, period);
|
|
109
|
+
return ok(formatYoutubeResearchResult(result), result);
|
|
110
|
+
}));
|
|
111
|
+
server.registerTool("check_small_youtuber_game_fit", {
|
|
112
|
+
title: "Check small YouTuber game fit",
|
|
113
|
+
description: "Check whether a game or gaming topic looks realistic for a smaller YouTube channel.",
|
|
114
|
+
inputSchema: {
|
|
115
|
+
query: z.string().trim().min(1).max(180),
|
|
116
|
+
period: periodSchema,
|
|
117
|
+
channelSize: z.enum(["under_1k", "one_to_10k", "ten_to_50k", "over_50k"]).default("one_to_10k")
|
|
118
|
+
}
|
|
119
|
+
}, async ({ query, period, channelSize }) => safeRun(async () => {
|
|
120
|
+
const result = await client.checkYoutubeResearchTool(youtubeResearchPaths.smallYoutuberFit, query, period, { channelSize });
|
|
121
|
+
return ok(formatYoutubeResearchResult(result), result);
|
|
122
|
+
}));
|
|
123
|
+
server.registerTool("check_game_for_youtube", {
|
|
124
|
+
title: "Check Steam game for YouTube channel",
|
|
125
|
+
description: "Check whether one Steam game is a good YouTube opportunity for one creator channel.",
|
|
126
|
+
inputSchema: {
|
|
127
|
+
steamUrl: z.string().trim().min(10).max(500).describe("Steam store app URL."),
|
|
128
|
+
youtubeChannelUrl: z.string().trim().min(8).max(500).describe("YouTube channel URL."),
|
|
129
|
+
region: marketRegionSchema,
|
|
130
|
+
language: marketLanguageSchema
|
|
131
|
+
}
|
|
132
|
+
}, async (input) => safeRun(async () => {
|
|
133
|
+
const result = await client.checkGameForYoutube(input);
|
|
134
|
+
return ok(formatGameCheckerResult(result), result);
|
|
135
|
+
}));
|
|
136
|
+
server.registerTool("find_youtube_gaming_opportunities", {
|
|
137
|
+
title: "Find YouTube gaming opportunities",
|
|
138
|
+
description: "Return PeepTrend's ranked Steam and YouTube opportunity feed for a market. Requires a PeepTrend API key.",
|
|
139
|
+
inputSchema: {
|
|
140
|
+
region: marketRegionSchema,
|
|
141
|
+
language: marketLanguageSchema,
|
|
142
|
+
mode: z.enum(["qualified", "steam-only", "watchlist"]).default("qualified")
|
|
143
|
+
}
|
|
144
|
+
}, async (input) => safeRun(async () => {
|
|
145
|
+
const result = await client.findOpportunities(input);
|
|
146
|
+
return ok(formatOpportunities(result), result);
|
|
147
|
+
}));
|
|
148
|
+
server.registerTool("get_opportunity_detail", {
|
|
149
|
+
title: "Get opportunity detail",
|
|
150
|
+
description: "Open a full opportunity report with score breakdown, Steam/YouTube evidence, crowding estimate, and creator brief. Requires a PeepTrend API key.",
|
|
151
|
+
inputSchema: {
|
|
152
|
+
slug: z.string().trim().min(1).max(120),
|
|
153
|
+
region: marketRegionSchema,
|
|
154
|
+
language: marketLanguageSchema
|
|
155
|
+
}
|
|
156
|
+
}, async (input) => safeRun(async () => {
|
|
157
|
+
const result = await client.getOpportunityDetail(input);
|
|
158
|
+
return ok(formatOpportunityDetail(result), result);
|
|
159
|
+
}));
|
|
160
|
+
server.registerTool("generate_creator_ideas", {
|
|
161
|
+
title: "Generate creator ideas",
|
|
162
|
+
description: "Generate PeepTrend content ideas for an opportunity. Requires an active PeepTrend subscription.",
|
|
163
|
+
inputSchema: {
|
|
164
|
+
slug: z.string().trim().min(1).max(120),
|
|
165
|
+
region: marketRegionSchema,
|
|
166
|
+
language: marketLanguageSchema,
|
|
167
|
+
regenerate: z.boolean().default(false)
|
|
168
|
+
}
|
|
169
|
+
}, async (input) => safeRun(async () => {
|
|
170
|
+
const result = await client.generateCreatorIdeas(input);
|
|
171
|
+
return ok("Generated PeepTrend creator ideas. Use the structured data for titles, hooks, risks, and descriptions.", result);
|
|
172
|
+
}));
|
|
173
|
+
server.registerTool("save_opportunity_workflow", {
|
|
174
|
+
title: "Save opportunity workflow",
|
|
175
|
+
description: "Save, plan, dismiss, publish, or clear a PeepTrend opportunity workflow status. Requires an active PeepTrend subscription.",
|
|
176
|
+
inputSchema: {
|
|
177
|
+
gameId: z.string().trim().min(1).max(80),
|
|
178
|
+
status: z.enum(["none", "saved", "dismissed", "planned", "published"]),
|
|
179
|
+
note: z.string().trim().max(1000).optional()
|
|
180
|
+
}
|
|
181
|
+
}, async (input) => safeRun(async () => {
|
|
182
|
+
const result = await client.setWorkflow(input);
|
|
183
|
+
return ok(`Workflow updated to "${input.status}".`, result);
|
|
184
|
+
}));
|
|
185
|
+
server.registerTool("send_opportunity_feedback", {
|
|
186
|
+
title: "Send opportunity feedback",
|
|
187
|
+
description: "Tell PeepTrend whether an opportunity was useful, wrong, saturated, off-niche, or used for a video. Requires an active PeepTrend subscription.",
|
|
188
|
+
inputSchema: {
|
|
189
|
+
gameId: z.string().trim().min(1).max(80),
|
|
190
|
+
type: z.enum(["useful", "not_useful", "wrong_match", "too_saturated", "not_my_niche", "made_video"]),
|
|
191
|
+
message: z.string().trim().max(1000).optional()
|
|
192
|
+
}
|
|
193
|
+
}, async (input) => safeRun(async () => {
|
|
194
|
+
const result = await client.sendFeedback(input);
|
|
195
|
+
return ok(`Feedback recorded as "${input.type}".`, result);
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
export type PeriodId = "7d" | "30d" | "90d" | "180d" | "365d";
|
|
2
|
+
export type ChannelSize = "under_1k" | "one_to_10k" | "ten_to_50k" | "over_50k";
|
|
3
|
+
export type OpportunityMode = "qualified" | "steam-only" | "watchlist";
|
|
4
|
+
export type ApiEnvelope<T> = {
|
|
5
|
+
data: T;
|
|
6
|
+
};
|
|
7
|
+
export type ApiErrorPayload = {
|
|
8
|
+
error?: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
};
|
|
11
|
+
export type ToolLimit = {
|
|
12
|
+
limit: number | null;
|
|
13
|
+
used: number | null;
|
|
14
|
+
remaining: number | null;
|
|
15
|
+
resetAt: string | null;
|
|
16
|
+
scope: string;
|
|
17
|
+
unlimited?: boolean;
|
|
18
|
+
};
|
|
19
|
+
export type YoutubeChannelResult = {
|
|
20
|
+
query: string;
|
|
21
|
+
handleCandidate: string;
|
|
22
|
+
verdict: "taken" | "close" | "available";
|
|
23
|
+
channels: Array<{
|
|
24
|
+
title: string;
|
|
25
|
+
handle: string;
|
|
26
|
+
youtubeUrl: string;
|
|
27
|
+
subscribers: number | null;
|
|
28
|
+
exactHandleMatch: boolean;
|
|
29
|
+
exactTitleMatch: boolean;
|
|
30
|
+
containsMatch: boolean;
|
|
31
|
+
}>;
|
|
32
|
+
};
|
|
33
|
+
export type YoutubeTitleResult = {
|
|
34
|
+
query: string;
|
|
35
|
+
period: {
|
|
36
|
+
id: PeriodId;
|
|
37
|
+
label: string;
|
|
38
|
+
};
|
|
39
|
+
videos: Array<{
|
|
40
|
+
title: string;
|
|
41
|
+
author: string;
|
|
42
|
+
youtubeUrl: string;
|
|
43
|
+
viewCount: number;
|
|
44
|
+
viewsPerDay: number;
|
|
45
|
+
publishedText: string;
|
|
46
|
+
exactTitleMatch: boolean;
|
|
47
|
+
}>;
|
|
48
|
+
summary: {
|
|
49
|
+
videosAnalyzed: number;
|
|
50
|
+
averageViews: number;
|
|
51
|
+
topViews: number;
|
|
52
|
+
averageViewsPerDay: number;
|
|
53
|
+
uniqueChannels: number;
|
|
54
|
+
demandScore: number;
|
|
55
|
+
competitionScore: number;
|
|
56
|
+
opportunityScore: number;
|
|
57
|
+
recommendation: string;
|
|
58
|
+
warnings: string[];
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
export type YoutubeResearchResult = {
|
|
62
|
+
tool: string;
|
|
63
|
+
query: string;
|
|
64
|
+
searchQuery: string;
|
|
65
|
+
period: {
|
|
66
|
+
id: PeriodId;
|
|
67
|
+
label: string;
|
|
68
|
+
};
|
|
69
|
+
videos: YoutubeTitleResult["videos"];
|
|
70
|
+
summary: {
|
|
71
|
+
verdictLabel: string;
|
|
72
|
+
headline: string;
|
|
73
|
+
recommendation: string;
|
|
74
|
+
nextStep: string;
|
|
75
|
+
scoreCards: Array<{
|
|
76
|
+
label: string;
|
|
77
|
+
score: number | null;
|
|
78
|
+
tone: string;
|
|
79
|
+
}>;
|
|
80
|
+
metrics: Array<{
|
|
81
|
+
label: string;
|
|
82
|
+
value: string;
|
|
83
|
+
detail: string;
|
|
84
|
+
}>;
|
|
85
|
+
insights: string[];
|
|
86
|
+
angles: Array<{
|
|
87
|
+
title: string;
|
|
88
|
+
text: string;
|
|
89
|
+
}>;
|
|
90
|
+
warnings: string[];
|
|
91
|
+
videosAnalyzed: number;
|
|
92
|
+
demandScore: number;
|
|
93
|
+
competitionScore: number;
|
|
94
|
+
opportunityScore: number;
|
|
95
|
+
saturationScore: number;
|
|
96
|
+
smallCreatorFitScore: number;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
export type GameCheckerResult = {
|
|
100
|
+
checkId: string;
|
|
101
|
+
limit: ToolLimit;
|
|
102
|
+
game: {
|
|
103
|
+
tracked: boolean;
|
|
104
|
+
name: string;
|
|
105
|
+
steamUrl: string | null;
|
|
106
|
+
imageUrl: string | null;
|
|
107
|
+
currentPlayers: number | null;
|
|
108
|
+
peakPlayers24h: number | null;
|
|
109
|
+
genres: string[];
|
|
110
|
+
tags: string[];
|
|
111
|
+
};
|
|
112
|
+
channel: {
|
|
113
|
+
channelTitle: string;
|
|
114
|
+
youtubeUrl: string;
|
|
115
|
+
subscriberCount: number;
|
|
116
|
+
averageViews: number;
|
|
117
|
+
sizeSegment: string;
|
|
118
|
+
};
|
|
119
|
+
score: {
|
|
120
|
+
opportunityScore: number | null;
|
|
121
|
+
fitScore: number | null;
|
|
122
|
+
verdict: string;
|
|
123
|
+
verdictLabel: string;
|
|
124
|
+
explanation: string;
|
|
125
|
+
fitReason: string;
|
|
126
|
+
riskFlags: string[];
|
|
127
|
+
};
|
|
128
|
+
youtube: {
|
|
129
|
+
videosCount7d: number | null;
|
|
130
|
+
views7d: number | null;
|
|
131
|
+
uniqueChannelsCount: number | null;
|
|
132
|
+
evidenceVideos: Array<{
|
|
133
|
+
title: string;
|
|
134
|
+
url: string;
|
|
135
|
+
channelTitle: string | null;
|
|
136
|
+
viewCount: number;
|
|
137
|
+
}>;
|
|
138
|
+
};
|
|
139
|
+
ideas: Array<{
|
|
140
|
+
title: string;
|
|
141
|
+
angle: string;
|
|
142
|
+
reason: string;
|
|
143
|
+
difficulty: string;
|
|
144
|
+
urgency: string;
|
|
145
|
+
}>;
|
|
146
|
+
};
|
|
147
|
+
export type OpportunityListResult = {
|
|
148
|
+
data: OpportunityPreview[];
|
|
149
|
+
lockedOpportunities: Array<{
|
|
150
|
+
id: string;
|
|
151
|
+
gameName: string;
|
|
152
|
+
gameImageUrl: string | null;
|
|
153
|
+
}>;
|
|
154
|
+
locked: boolean;
|
|
155
|
+
preview: boolean;
|
|
156
|
+
lockedCount?: number;
|
|
157
|
+
subscription?: SubscriptionStatus;
|
|
158
|
+
};
|
|
159
|
+
export type SubscriptionStatus = {
|
|
160
|
+
status: string;
|
|
161
|
+
canAccess: boolean;
|
|
162
|
+
requiresSubscription: boolean;
|
|
163
|
+
previewAccess: boolean;
|
|
164
|
+
previewAccessExpired: boolean;
|
|
165
|
+
freeOpportunityUnlockLimit: number;
|
|
166
|
+
freeOpportunityUnlocksUsed: number;
|
|
167
|
+
freeOpportunityUnlocksRemaining: number;
|
|
168
|
+
};
|
|
169
|
+
export type OpportunityPreview = {
|
|
170
|
+
gameId: string;
|
|
171
|
+
slug: string;
|
|
172
|
+
gameName: string;
|
|
173
|
+
gameImageUrl: string | null;
|
|
174
|
+
region: string;
|
|
175
|
+
language: string;
|
|
176
|
+
finalScore: number;
|
|
177
|
+
momentumScore: number;
|
|
178
|
+
saturationScore: number;
|
|
179
|
+
opportunityGapScore: number;
|
|
180
|
+
queryPrecisionScore: number;
|
|
181
|
+
crowdingVelocityScore: number;
|
|
182
|
+
crowdingWindowHours: number | null;
|
|
183
|
+
confidenceScore: number;
|
|
184
|
+
riskFlags: string[];
|
|
185
|
+
explanation: string;
|
|
186
|
+
suggestedVideoAngle: string;
|
|
187
|
+
suggestedVideoReason: string;
|
|
188
|
+
suggestedVideoUrgency: string;
|
|
189
|
+
currentPlayers: number | null;
|
|
190
|
+
videosCount7d: number | null;
|
|
191
|
+
evidenceVideos: Array<{
|
|
192
|
+
title: string;
|
|
193
|
+
url: string;
|
|
194
|
+
channelTitle: string | null;
|
|
195
|
+
viewCount: number;
|
|
196
|
+
}>;
|
|
197
|
+
};
|
|
198
|
+
export type OpportunityDetail = {
|
|
199
|
+
game: {
|
|
200
|
+
id: string;
|
|
201
|
+
name: string;
|
|
202
|
+
slug: string;
|
|
203
|
+
steamUrl: string | null;
|
|
204
|
+
imageUrl: string | null;
|
|
205
|
+
genres: string[];
|
|
206
|
+
tags: string[];
|
|
207
|
+
};
|
|
208
|
+
score: {
|
|
209
|
+
finalScore: number;
|
|
210
|
+
gameMomentumScore: number;
|
|
211
|
+
youtubeSaturationScore: number;
|
|
212
|
+
opportunityGapScore: number;
|
|
213
|
+
timingScore: number;
|
|
214
|
+
confidenceScore: number;
|
|
215
|
+
queryPrecisionScore: number;
|
|
216
|
+
crowdingVelocityScore: number;
|
|
217
|
+
crowdingWindowHours: number | null;
|
|
218
|
+
riskFlags: string[];
|
|
219
|
+
explanation: string;
|
|
220
|
+
};
|
|
221
|
+
videoIdeas: Array<{
|
|
222
|
+
title: string;
|
|
223
|
+
angle: string;
|
|
224
|
+
reason: string;
|
|
225
|
+
difficulty: string;
|
|
226
|
+
urgency: string;
|
|
227
|
+
}>;
|
|
228
|
+
evidenceVideos: Array<{
|
|
229
|
+
title: string;
|
|
230
|
+
url: string;
|
|
231
|
+
channelTitle: string | null;
|
|
232
|
+
viewCount: number;
|
|
233
|
+
}>;
|
|
234
|
+
creatorBrief: {
|
|
235
|
+
action: string;
|
|
236
|
+
recommendedFormat: string;
|
|
237
|
+
suggestedTitle: string;
|
|
238
|
+
hook: string;
|
|
239
|
+
whatToCheck: string;
|
|
240
|
+
deadline: string;
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
export declare class PeepTrendApiError extends Error {
|
|
244
|
+
readonly status: number;
|
|
245
|
+
readonly code?: string;
|
|
246
|
+
readonly upgradeUrl?: string;
|
|
247
|
+
constructor(message: string, options: {
|
|
248
|
+
status: number;
|
|
249
|
+
code?: string;
|
|
250
|
+
upgradeUrl?: string;
|
|
251
|
+
});
|
|
252
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class PeepTrendApiError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
code;
|
|
4
|
+
upgradeUrl;
|
|
5
|
+
constructor(message, options) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "PeepTrendApiError";
|
|
8
|
+
this.status = options.status;
|
|
9
|
+
this.code = options.code;
|
|
10
|
+
this.upgradeUrl = options.upgradeUrl;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAyOA,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,MAAM,CAAS;IACf,IAAI,CAAU;IACd,UAAU,CAAU;IAE7B,YAAY,OAAe,EAAE,OAA+D;QAC1F,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACvC,CAAC;CACF"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# PeepTrend for Claude
|
|
2
|
+
|
|
3
|
+
Add PeepTrend to Claude Desktop as an MCP server:
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"mcpServers": {
|
|
8
|
+
"peeptrend": {
|
|
9
|
+
"command": "npx",
|
|
10
|
+
"args": ["-y", "peeptrend-mcp"],
|
|
11
|
+
"env": {
|
|
12
|
+
"PEEPTREND_API_KEY": "pt_key_from_profile"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Suggested first prompt:
|
|
20
|
+
|
|
21
|
+
"Use PeepTrend to find a gaming topic I can record this week. Prefer lower saturation and explain the evidence."
|
|
22
|
+
|
|
23
|
+
The portable Claude skill prompt is in `skills/claude/peeptrend-youtube-gaming-trend-finder/SKILL.md`.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# PeepTrend for Codex
|
|
2
|
+
|
|
3
|
+
PeepTrend can be used in Codex through the MCP server or the bundled Codex plugin scaffold in this repository.
|
|
4
|
+
|
|
5
|
+
## MCP Config
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"mcpServers": {
|
|
10
|
+
"peeptrend": {
|
|
11
|
+
"command": "npx",
|
|
12
|
+
"args": ["-y", "peeptrend-mcp"],
|
|
13
|
+
"env": {
|
|
14
|
+
"PEEPTREND_API_KEY": "pt_key_from_profile"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Plugin Scaffold
|
|
22
|
+
|
|
23
|
+
The Codex plugin manifest lives at:
|
|
24
|
+
|
|
25
|
+
`plugins/peeptrend-youtube-gaming-trend-finder/.codex-plugin/plugin.json`
|
|
26
|
+
|
|
27
|
+
It declares the same MCP server and a focused PeepTrend skill for YouTube gaming trend research.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# PeepTrend MCP
|
|
2
|
+
|
|
3
|
+
Use this for any MCP-compatible client.
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"mcpServers": {
|
|
8
|
+
"peeptrend": {
|
|
9
|
+
"command": "npx",
|
|
10
|
+
"args": ["-y", "peeptrend-mcp"],
|
|
11
|
+
"env": {
|
|
12
|
+
"PEEPTREND_API_KEY": "pt_key_from_profile"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Good starter prompts:
|
|
20
|
+
|
|
21
|
+
- "Find gaming opportunities for US English creators and explain the top 3."
|
|
22
|
+
- "Check whether this YouTube title is crowded: Minecraft update explained."
|
|
23
|
+
- "Check if this Steam game is worth covering for my channel."
|
|
24
|
+
|
|
25
|
+
Create and revoke API keys at https://peeptrend.com/profile.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# PeepTrend for OpenClaw
|
|
2
|
+
|
|
3
|
+
Add the PeepTrend MCP server to OpenClaw's MCP configuration:
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"mcpServers": {
|
|
8
|
+
"peeptrend": {
|
|
9
|
+
"command": "npx",
|
|
10
|
+
"args": ["-y", "peeptrend-mcp"],
|
|
11
|
+
"env": {
|
|
12
|
+
"PEEPTREND_API_KEY": "pt_key_from_profile"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Suggested first prompt:
|
|
20
|
+
|
|
21
|
+
"Use PeepTrend to check whether this Steam update is worth covering on YouTube and suggest a safe angle."
|
|
22
|
+
|
|
23
|
+
The portable OpenClaw skill prompt is in `skills/openclaw/youtube-gaming-trend-finder/SKILL.md`.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.peeptrend/youtube-gaming-trend-finder",
|
|
4
|
+
"title": "PeepTrend: YouTube Gaming Trend Finder",
|
|
5
|
+
"description": "Find rising Steam games and YouTube content opportunities before the niche gets crowded.",
|
|
6
|
+
"repository": {
|
|
7
|
+
"url": "https://github.com/PeepTrend/PeepTrend.MCP",
|
|
8
|
+
"source": "github"
|
|
9
|
+
},
|
|
10
|
+
"version": "0.1.0",
|
|
11
|
+
"packages": [
|
|
12
|
+
{
|
|
13
|
+
"registryType": "npm",
|
|
14
|
+
"identifier": "peeptrend-mcp",
|
|
15
|
+
"version": "0.1.0",
|
|
16
|
+
"transport": {
|
|
17
|
+
"type": "stdio"
|
|
18
|
+
},
|
|
19
|
+
"environmentVariables": [
|
|
20
|
+
{
|
|
21
|
+
"name": "PEEPTREND_API_KEY",
|
|
22
|
+
"description": "Optional PeepTrend API key from Profile > AI integrations. Required for account-aware limits, full reports, ideas, workflow actions, and subscription features.",
|
|
23
|
+
"format": "string",
|
|
24
|
+
"isRequired": false,
|
|
25
|
+
"isSecret": true
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "peeptrend-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "PeepTrend MCP server for finding rising Steam games and YouTube gaming content opportunities before niches get crowded.",
|
|
5
|
+
"mcpName": "io.github.peeptrend/youtube-gaming-trend-finder",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"author": "PeepTrend <support@peeptrend.com>",
|
|
9
|
+
"homepage": "https://peeptrend.com/integrations/mcp",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+ssh://git@github.com/PeepTrend/PeepTrend.MCP.git"
|
|
13
|
+
},
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/PeepTrend/PeepTrend.MCP/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"youtube",
|
|
20
|
+
"gaming",
|
|
21
|
+
"steam",
|
|
22
|
+
"creator-tools",
|
|
23
|
+
"peeptrend"
|
|
24
|
+
],
|
|
25
|
+
"bin": {
|
|
26
|
+
"peeptrend-mcp": "dist/server.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"integrations",
|
|
33
|
+
"plugins",
|
|
34
|
+
"skills",
|
|
35
|
+
"mcp-registry"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
39
|
+
"build": "npm run clean && tsc -p tsconfig.build.json",
|
|
40
|
+
"prepare": "npm run build",
|
|
41
|
+
"dev": "tsx src/server.ts",
|
|
42
|
+
"start": "node dist/server.js",
|
|
43
|
+
"test": "node --import tsx --test \"src/**/*.test.ts\"",
|
|
44
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
45
|
+
"validate": "npm run typecheck && npm test && npm run build"
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
49
|
+
"zod": "^4.4.3"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@types/node": "^24.10.1",
|
|
53
|
+
"tsx": "^4.22.4",
|
|
54
|
+
"typescript": "^6.0.3"
|
|
55
|
+
},
|
|
56
|
+
"engines": {
|
|
57
|
+
"node": ">=22"
|
|
58
|
+
}
|
|
59
|
+
}
|