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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 PeepTrend
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # PeepTrend: YouTube Gaming Trend Finder
2
+
3
+ Find rising Steam games and YouTube content opportunities before the niche gets crowded.
4
+
5
+ This repository contains the PeepTrend MCP server plus setup files for Codex, Claude, OpenClaw, and generic MCP clients.
6
+
7
+ ## What It Does
8
+
9
+ PeepTrend gives AI agents focused tools for gaming creator research:
10
+
11
+ - Check YouTube channel name and handle conflicts.
12
+ - Check YouTube video titles against recent videos, demand, competition, and velocity.
13
+ - Check YouTube shelf saturation for gaming topics.
14
+ - Check gaming niches and small-channel fit.
15
+ - Check Steam update opportunities before the shelf fills.
16
+ - Check whether a Steam game fits a YouTube channel.
17
+ - Pull PeepTrend opportunity feeds and full reports when connected to a PeepTrend account.
18
+ - Generate creator ideas, save workflow status, and send feedback when the account has subscription access.
19
+
20
+ PeepTrend accounts can create API keys for MCP clients. Some tools are available to try with a free account; full reports, generated ideas, workflow actions, alerts, and higher usage are available from PeepTrend plans.
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ npm install -g peeptrend-mcp
26
+ ```
27
+
28
+ Or run it directly:
29
+
30
+ ```bash
31
+ npx -y peeptrend-mcp
32
+ ```
33
+
34
+ Running the command manually prints setup instructions. In normal use, your AI client starts this package as an MCP server and communicates with it over stdio.
35
+
36
+ ## Configure
37
+
38
+ Create an API key in PeepTrend:
39
+
40
+ 1. Create or log in to your PeepTrend account.
41
+ 2. Open Profile.
42
+ 3. Create an API key under AI integrations.
43
+ 4. Add it to your MCP client as `PEEPTREND_API_KEY`.
44
+
45
+ Example MCP config:
46
+
47
+ ```json
48
+ {
49
+ "mcpServers": {
50
+ "peeptrend": {
51
+ "command": "npx",
52
+ "args": ["-y", "peeptrend-mcp"],
53
+ "env": {
54
+ "PEEPTREND_API_KEY": "pt_key_from_profile"
55
+ }
56
+ }
57
+ }
58
+ }
59
+ ```
60
+
61
+ An API key is recommended. It connects MCP requests to your PeepTrend account and enables account features when available.
62
+
63
+ ## Check Status
64
+
65
+ ```bash
66
+ npx -y peeptrend-mcp --doctor
67
+ ```
68
+
69
+ Use `--stdio` only when a tool or MCP client explicitly asks for the raw MCP server process.
70
+
71
+ ## Available Tools
72
+
73
+ - `get_peeptrend_connection_status`
74
+ - `check_youtube_channel_name`
75
+ - `check_youtube_title`
76
+ - `check_youtube_shelf_saturation`
77
+ - `check_gaming_niche`
78
+ - `check_steam_update_opportunity`
79
+ - `check_small_youtuber_game_fit`
80
+ - `check_game_for_youtube`
81
+ - `find_youtube_gaming_opportunities`
82
+ - `get_opportunity_detail`
83
+ - `generate_creator_ideas`
84
+ - `save_opportunity_workflow`
85
+ - `send_opportunity_feedback`
86
+
87
+ ## Client Guides
88
+
89
+ - [Generic MCP](./integrations/mcp/README.md)
90
+ - [Codex](./integrations/codex/README.md)
91
+ - [Claude](./integrations/claude/README.md)
92
+ - [OpenClaw](./integrations/openclaw/README.md)
93
+
94
+ ## Safety And Limits
95
+
96
+ PeepTrend API keys are account scoped and can be revoked from Profile. Store keys only in your MCP client's environment configuration and do not commit API keys to source control.
97
+
98
+ ## License
99
+
100
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import { type PeepTrendMcpConfig } from "./config.js";
2
+ export declare const serverVersion = "0.1.0";
3
+ export type CliAction = "help" | "version" | "doctor" | "manual" | "stdio" | "unknown";
4
+ export declare function resolveCliAction(args: string[], stdinIsTty: boolean): CliAction;
5
+ export declare function renderHelp(config: PeepTrendMcpConfig): string;
6
+ export declare function renderDoctor(config: PeepTrendMcpConfig, nodeVersion?: string): string;
package/dist/cli.js ADDED
@@ -0,0 +1,67 @@
1
+ import { authStatus } from "./config.js";
2
+ export const serverVersion = "0.1.0";
3
+ export function resolveCliAction(args, stdinIsTty) {
4
+ const firstArg = args[0];
5
+ if (firstArg === "--stdio") {
6
+ return "stdio";
7
+ }
8
+ if (firstArg === "--help" || firstArg === "-h" || firstArg === "help") {
9
+ return "help";
10
+ }
11
+ if (firstArg === "--version" || firstArg === "-v" || firstArg === "version") {
12
+ return "version";
13
+ }
14
+ if (firstArg === "--doctor" || firstArg === "doctor") {
15
+ return "doctor";
16
+ }
17
+ if (args.length === 0 && stdinIsTty) {
18
+ return "manual";
19
+ }
20
+ return args.length === 0 ? "stdio" : "unknown";
21
+ }
22
+ export function renderHelp(config) {
23
+ return [
24
+ "PeepTrend MCP is installed and ready.",
25
+ "",
26
+ "This package is an MCP server for AI clients. Add it to Codex, Claude Desktop, OpenClaw, or any MCP-compatible client instead of using it as an interactive shell command.",
27
+ "",
28
+ "Quick config:",
29
+ "{",
30
+ ' "mcpServers": {',
31
+ ' "peeptrend": {',
32
+ ' "command": "npx",',
33
+ ' "args": ["-y", "peeptrend-mcp"],',
34
+ ' "env": {',
35
+ ' "PEEPTREND_API_KEY": "pt_key_from_profile"',
36
+ " }",
37
+ " }",
38
+ " }",
39
+ "}",
40
+ "",
41
+ "Useful commands:",
42
+ " npx -y peeptrend-mcp --doctor",
43
+ " npx -y peeptrend-mcp --help",
44
+ " npx -y peeptrend-mcp --stdio",
45
+ "",
46
+ `Profile/API keys: ${config.websiteBaseUrl}/profile`,
47
+ `Setup guide: ${config.websiteBaseUrl}/integrations/mcp`
48
+ ].join("\n");
49
+ }
50
+ export function renderDoctor(config, nodeVersion = process.version) {
51
+ const connected = authStatus(config) === "authenticated";
52
+ return [
53
+ "PeepTrend MCP status",
54
+ "",
55
+ `Node: ${nodeVersion}`,
56
+ `API endpoint: ${config.apiBaseUrl}`,
57
+ `Website: ${config.websiteBaseUrl}`,
58
+ `API key: ${connected ? "found" : "not configured"}`,
59
+ "",
60
+ connected
61
+ ? "Ready: add the MCP config to your AI client and ask it to use PeepTrend."
62
+ : "Ready for setup: create an API key in PeepTrend Profile, then add it as PEEPTREND_API_KEY in your MCP client config.",
63
+ "",
64
+ `Setup guide: ${config.websiteBaseUrl}/integrations/mcp`
65
+ ].join("\n");
66
+ }
67
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAA2B,MAAM,aAAa,CAAC;AAElE,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AAIrC,MAAM,UAAU,gBAAgB,CAAC,IAAc,EAAE,UAAmB;IAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAEzB,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACtE,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,QAAQ,KAAK,WAAW,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC5E,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,QAAQ,KAAK,UAAU,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACrD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,UAAU,EAAE,CAAC;QACpC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAA0B;IACnD,OAAO;QACL,uCAAuC;QACvC,EAAE;QACF,4KAA4K;QAC5K,EAAE;QACF,eAAe;QACf,GAAG;QACH,mBAAmB;QACnB,oBAAoB;QACpB,yBAAyB;QACzB,wCAAwC;QACxC,gBAAgB;QAChB,oDAAoD;QACpD,SAAS;QACT,OAAO;QACP,KAAK;QACL,GAAG;QACH,EAAE;QACF,kBAAkB;QAClB,iCAAiC;QACjC,+BAA+B;QAC/B,gCAAgC;QAChC,EAAE;QACF,qBAAqB,MAAM,CAAC,cAAc,UAAU;QACpD,gBAAgB,MAAM,CAAC,cAAc,mBAAmB;KACzD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAA0B,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO;IACpF,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,eAAe,CAAC;IAEzD,OAAO;QACL,sBAAsB;QACtB,EAAE;QACF,SAAS,WAAW,EAAE;QACtB,iBAAiB,MAAM,CAAC,UAAU,EAAE;QACpC,YAAY,MAAM,CAAC,cAAc,EAAE;QACnC,YAAY,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,EAAE;QACpD,EAAE;QACF,SAAS;YACP,CAAC,CAAC,0EAA0E;YAC5E,CAAC,CAAC,sHAAsH;QAC1H,EAAE;QACF,gBAAgB,MAAM,CAAC,cAAc,mBAAmB;KACzD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { type ChannelSize, type GameCheckerResult, type OpportunityDetail, type OpportunityListResult, type OpportunityMode, type PeriodId, type YoutubeChannelResult, type YoutubeResearchResult, type YoutubeTitleResult } from "./types.js";
2
+ import type { PeepTrendMcpConfig } from "./config.js";
3
+ export declare class PeepTrendClient {
4
+ private readonly config;
5
+ constructor(config: PeepTrendMcpConfig);
6
+ private resolvePath;
7
+ private request;
8
+ checkYoutubeChannelName(query: string): Promise<YoutubeChannelResult>;
9
+ checkYoutubeTitle(query: string, period: PeriodId): Promise<YoutubeTitleResult>;
10
+ checkYoutubeResearchTool(path: string, query: string, period: PeriodId, extra?: Record<string, unknown>): Promise<YoutubeResearchResult>;
11
+ checkGameForYoutube(input: {
12
+ steamUrl: string;
13
+ youtubeChannelUrl: string;
14
+ region: string;
15
+ language: string;
16
+ }): Promise<GameCheckerResult>;
17
+ findOpportunities(input: {
18
+ region: string;
19
+ language: string;
20
+ mode: OpportunityMode;
21
+ }): Promise<OpportunityListResult>;
22
+ getOpportunityDetail(input: {
23
+ slug: string;
24
+ region: string;
25
+ language: string;
26
+ }): Promise<OpportunityDetail>;
27
+ generateCreatorIdeas(input: {
28
+ slug: string;
29
+ region: string;
30
+ language: string;
31
+ regenerate?: boolean;
32
+ }): Promise<unknown>;
33
+ setWorkflow(input: {
34
+ gameId: string;
35
+ status: "none" | "saved" | "dismissed" | "planned" | "published";
36
+ note?: string;
37
+ }): Promise<unknown>;
38
+ sendFeedback(input: {
39
+ gameId: string;
40
+ type: "useful" | "not_useful" | "wrong_match" | "too_saturated" | "not_my_niche" | "made_video";
41
+ message?: string;
42
+ }): Promise<unknown>;
43
+ }
44
+ export declare const youtubeResearchPaths: {
45
+ readonly shelf: "/api/free-tools/youtube-shelf-saturation-checker";
46
+ readonly niche: "/api/free-tools/gaming-niche-checker";
47
+ readonly steamUpdate: "/api/free-tools/steam-update-opportunity-checker";
48
+ readonly smallYoutuberFit: "/api/free-tools/small-youtuber-game-fit-checker";
49
+ };
50
+ export type { ChannelSize, PeriodId };
package/dist/client.js ADDED
@@ -0,0 +1,125 @@
1
+ import { PeepTrendApiError } from "./types.js";
2
+ function upgradeUrl(path = "/pricing") {
3
+ return `https://peeptrend.com${path}`;
4
+ }
5
+ export class PeepTrendClient {
6
+ config;
7
+ constructor(config) {
8
+ this.config = config;
9
+ }
10
+ resolvePath(path, authRequired) {
11
+ if (!this.config.apiKey) {
12
+ return path;
13
+ }
14
+ if (authRequired || path.startsWith("/api/free-tools/")) {
15
+ return path.replace(/^\/api\//, "/api/mcp/");
16
+ }
17
+ return path;
18
+ }
19
+ async request(options) {
20
+ if (options.authRequired && !this.config.apiKey) {
21
+ throw new PeepTrendApiError("Connect a free PeepTrend API key to use this tool. Create one in Profile > API keys.", {
22
+ status: 401,
23
+ code: "ApiKeyRequired",
24
+ upgradeUrl: upgradeUrl("/profile")
25
+ });
26
+ }
27
+ const headers = new Headers({
28
+ "Content-Type": "application/json",
29
+ "User-Agent": this.config.userAgent,
30
+ "X-PeepTrend-MCP": "true"
31
+ });
32
+ if (this.config.apiKey) {
33
+ headers.set("Authorization", `Bearer ${this.config.apiKey}`);
34
+ }
35
+ const response = await fetch(`${this.config.apiBaseUrl}${this.resolvePath(options.path, Boolean(options.authRequired))}`, {
36
+ method: options.method ?? (options.body === undefined ? "GET" : "POST"),
37
+ headers,
38
+ body: options.body === undefined ? undefined : JSON.stringify(options.body)
39
+ });
40
+ const payload = (await response.json().catch(() => null));
41
+ if (!response.ok) {
42
+ const errorPayload = payload;
43
+ const code = errorPayload?.error;
44
+ const rawMessage = errorPayload?.message ?? `PeepTrend API request failed with ${response.status}`;
45
+ const message = response.status === 402
46
+ ? "This PeepTrend action is locked after the free preview. Start the trial to unlock full opportunities, idea generation, workflow actions, and higher MCP limits."
47
+ : response.status === 429
48
+ ? "This PeepTrend tool is temporarily rate limited. Try a cached result, wait for the reset, or upgrade for more room."
49
+ : rawMessage;
50
+ throw new PeepTrendApiError(message, {
51
+ status: response.status,
52
+ code,
53
+ upgradeUrl: response.status === 402 || response.status === 429 ? upgradeUrl("/pricing") : undefined
54
+ });
55
+ }
56
+ return payload.data;
57
+ }
58
+ checkYoutubeChannelName(query) {
59
+ return this.request({
60
+ path: "/api/free-tools/youtube-channel-name-checker",
61
+ body: { query }
62
+ });
63
+ }
64
+ checkYoutubeTitle(query, period) {
65
+ return this.request({
66
+ path: "/api/free-tools/youtube-title-checker",
67
+ body: { query, period }
68
+ });
69
+ }
70
+ checkYoutubeResearchTool(path, query, period, extra) {
71
+ return this.request({
72
+ path,
73
+ body: { query, period, ...extra }
74
+ });
75
+ }
76
+ checkGameForYoutube(input) {
77
+ return this.request({
78
+ path: "/api/free-tools/game-checker",
79
+ body: input
80
+ });
81
+ }
82
+ findOpportunities(input) {
83
+ const params = new URLSearchParams({ region: input.region, language: input.language, mode: input.mode });
84
+ return this.request({
85
+ path: `/api/opportunities?${params.toString()}`,
86
+ authRequired: true
87
+ });
88
+ }
89
+ getOpportunityDetail(input) {
90
+ const params = new URLSearchParams({ region: input.region, language: input.language });
91
+ return this.request({
92
+ path: `/api/opportunities/${encodeURIComponent(input.slug)}?${params.toString()}`,
93
+ authRequired: true
94
+ });
95
+ }
96
+ generateCreatorIdeas(input) {
97
+ const params = new URLSearchParams({ region: input.region, language: input.language });
98
+ return this.request({
99
+ path: `/api/creator-ideas/${encodeURIComponent(input.slug)}/generate?${params.toString()}`,
100
+ body: { regenerate: Boolean(input.regenerate), region: input.region, language: input.language },
101
+ authRequired: true
102
+ });
103
+ }
104
+ setWorkflow(input) {
105
+ return this.request({
106
+ path: "/api/opportunities/workflow",
107
+ body: input,
108
+ authRequired: true
109
+ });
110
+ }
111
+ sendFeedback(input) {
112
+ return this.request({
113
+ path: "/api/opportunities/feedback",
114
+ body: input,
115
+ authRequired: true
116
+ });
117
+ }
118
+ }
119
+ export const youtubeResearchPaths = {
120
+ shelf: "/api/free-tools/youtube-shelf-saturation-checker",
121
+ niche: "/api/free-tools/gaming-niche-checker",
122
+ steamUpdate: "/api/free-tools/steam-update-opportunity-checker",
123
+ smallYoutuberFit: "/api/free-tools/small-youtuber-game-fit-checker"
124
+ };
125
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type PeepTrendMcpConfig = {
2
+ apiBaseUrl: string;
3
+ apiKey?: string;
4
+ userAgent: string;
5
+ websiteBaseUrl: string;
6
+ };
7
+ export declare function loadConfig(env?: NodeJS.ProcessEnv): PeepTrendMcpConfig;
8
+ export declare function authStatus(config: PeepTrendMcpConfig): "authenticated" | "anonymous";
package/dist/config.js ADDED
@@ -0,0 +1,17 @@
1
+ function normalizeBaseUrl(value) {
2
+ return value.replace(/\/+$/, "");
3
+ }
4
+ export function loadConfig(env = process.env) {
5
+ const apiBaseUrl = normalizeBaseUrl(env.PEEPTREND_API_BASE_URL ?? "https://api.peeptrend.com");
6
+ const websiteBaseUrl = normalizeBaseUrl(env.PEEPTREND_WEBSITE_BASE_URL ?? "https://peeptrend.com");
7
+ return {
8
+ apiBaseUrl,
9
+ apiKey: env.PEEPTREND_API_KEY,
10
+ userAgent: env.PEEPTREND_USER_AGENT ?? "peeptrend-mcp",
11
+ websiteBaseUrl
12
+ };
13
+ }
14
+ export function authStatus(config) {
15
+ return config.apiKey ? "authenticated" : "anonymous";
16
+ }
17
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAOA,SAAS,gBAAgB,CAAC,KAAa;IACrC,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,UAAU,GAAG,gBAAgB,CAAC,GAAG,CAAC,sBAAsB,IAAI,2BAA2B,CAAC,CAAC;IAC/F,MAAM,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,0BAA0B,IAAI,uBAAuB,CAAC,CAAC;IAEnG,OAAO;QACL,UAAU;QACV,MAAM,EAAE,GAAG,CAAC,iBAAiB;QAC7B,SAAS,EAAE,GAAG,CAAC,oBAAoB,IAAI,eAAe;QACtD,cAAc;KACf,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAA0B;IACnD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC;AACvD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { GameCheckerResult, OpportunityDetail, OpportunityListResult, YoutubeChannelResult, YoutubeResearchResult, YoutubeTitleResult } from "./types.js";
2
+ export declare function formatConnectionStatus(input: {
3
+ authenticated: boolean;
4
+ apiBaseUrl: string;
5
+ websiteBaseUrl: string;
6
+ }): string;
7
+ export declare function formatChannelNameResult(result: YoutubeChannelResult): string;
8
+ export declare function formatTitleResult(result: YoutubeTitleResult): string;
9
+ export declare function formatYoutubeResearchResult(result: YoutubeResearchResult): string;
10
+ export declare function formatGameCheckerResult(result: GameCheckerResult): string;
11
+ export declare function formatOpportunities(result: OpportunityListResult): string;
12
+ export declare function formatOpportunityDetail(result: OpportunityDetail): string;
package/dist/format.js ADDED
@@ -0,0 +1,150 @@
1
+ function number(value) {
2
+ if (value === null || value === undefined || Number.isNaN(value)) {
3
+ return "-";
4
+ }
5
+ return new Intl.NumberFormat("en", { notation: "compact", maximumFractionDigits: 1 }).format(value);
6
+ }
7
+ function percent(value) {
8
+ if (value === null || value === undefined || Number.isNaN(value)) {
9
+ return "-";
10
+ }
11
+ return `${Math.round(value)}%`;
12
+ }
13
+ function list(values, limit = 5) {
14
+ return values.slice(0, limit).map((value) => `- ${value}`).join("\n");
15
+ }
16
+ function upgradeCopy() {
17
+ return [
18
+ "",
19
+ "Next step: use PeepTrend to turn this signal into a recording plan, alerts, and full opportunity details:",
20
+ "https://peeptrend.com/pricing"
21
+ ].join("\n");
22
+ }
23
+ export function formatConnectionStatus(input) {
24
+ return [
25
+ `PeepTrend MCP is connected to ${input.apiBaseUrl}.`,
26
+ input.authenticated
27
+ ? "API key is configured. Paid dashboard actions, workflow, and higher limits can be used when the PeepTrend account allows it."
28
+ : "No API key is configured. Free tools still work with public limits; create a key in PeepTrend Profile to unlock account-aware tools.",
29
+ `Create or revoke keys: ${input.websiteBaseUrl}/profile`,
30
+ `Integration docs: ${input.websiteBaseUrl}/integrations/mcp`
31
+ ].join("\n");
32
+ }
33
+ export function formatChannelNameResult(result) {
34
+ const topMatches = result.channels
35
+ .slice(0, 10)
36
+ .map((channel, index) => {
37
+ const flags = [
38
+ channel.exactHandleMatch ? "exact handle" : null,
39
+ channel.exactTitleMatch ? "exact title" : null,
40
+ channel.containsMatch ? "close" : null
41
+ ].filter(Boolean);
42
+ return `${index + 1}. ${channel.title} (${channel.handle || "no handle"}) - ${number(channel.subscribers)} subscribers${flags.length ? `, ${flags.join(", ")}` : ""}`;
43
+ })
44
+ .join("\n");
45
+ return [
46
+ `Channel name check for "${result.query}"`,
47
+ `Candidate handle: ${result.handleCandidate}`,
48
+ `Verdict: ${result.verdict}`,
49
+ "",
50
+ topMatches || "No similar channels were returned.",
51
+ upgradeCopy()
52
+ ].join("\n");
53
+ }
54
+ export function formatTitleResult(result) {
55
+ return [
56
+ `YouTube title check for "${result.query}" (${result.period.label})`,
57
+ `Opportunity: ${percent(result.summary.opportunityScore)} | Demand: ${percent(result.summary.demandScore)} | Competition: ${percent(result.summary.competitionScore)}`,
58
+ `Videos analyzed: ${result.summary.videosAnalyzed}; avg views: ${number(result.summary.averageViews)}; top views: ${number(result.summary.topViews)}; avg views/day: ${number(result.summary.averageViewsPerDay)}; channels: ${result.summary.uniqueChannels}`,
59
+ `Recommendation: ${result.summary.recommendation}`,
60
+ result.summary.warnings.length ? `Warnings:\n${list(result.summary.warnings, 4)}` : "Warnings: none",
61
+ "",
62
+ "Top returned videos:",
63
+ result.videos.slice(0, 10).map((video, index) => `${index + 1}. ${video.title} - ${number(video.viewCount)} views, ${number(video.viewsPerDay)}/day (${video.author})`).join("\n") || "No videos returned.",
64
+ upgradeCopy()
65
+ ].join("\n");
66
+ }
67
+ export function formatYoutubeResearchResult(result) {
68
+ return [
69
+ `${result.summary.headline}`,
70
+ `Query: "${result.query}" (${result.period.label})`,
71
+ `Opportunity: ${percent(result.summary.opportunityScore)} | Demand: ${percent(result.summary.demandScore)} | Competition: ${percent(result.summary.competitionScore)} | Saturation: ${percent(result.summary.saturationScore)} | Small-channel fit: ${percent(result.summary.smallCreatorFitScore)}`,
72
+ `Verdict: ${result.summary.verdictLabel}`,
73
+ `Recommendation: ${result.summary.recommendation}`,
74
+ `Next step: ${result.summary.nextStep}`,
75
+ "",
76
+ result.summary.insights.length ? `Insights:\n${list(result.summary.insights, 5)}` : "Insights: none",
77
+ result.summary.angles.length
78
+ ? `Angles:\n${result.summary.angles.slice(0, 4).map((angle) => `- ${angle.title}: ${angle.text}`).join("\n")}`
79
+ : "Angles: none",
80
+ "",
81
+ "Returned videos:",
82
+ result.videos.slice(0, 10).map((video, index) => `${index + 1}. ${video.title} - ${number(video.viewCount)} views (${video.author})`).join("\n") || "No videos returned.",
83
+ upgradeCopy()
84
+ ].join("\n");
85
+ }
86
+ export function formatGameCheckerResult(result) {
87
+ return [
88
+ `Game fit check: ${result.game.name}`,
89
+ `Verdict: ${result.score.verdictLabel}`,
90
+ `Opportunity: ${percent(result.score.opportunityScore)} | Channel fit: ${percent(result.score.fitScore)}`,
91
+ result.game.tracked
92
+ ? `Steam: ${number(result.game.currentPlayers)} current players, ${number(result.game.peakPlayers24h)} 24h peak`
93
+ : "This game is not fully tracked yet.",
94
+ `YouTube: ${number(result.youtube.videosCount7d)} videos in 7d, ${number(result.youtube.views7d)} views, ${number(result.youtube.uniqueChannelsCount)} channels`,
95
+ `Why: ${result.score.explanation}`,
96
+ `Fit: ${result.score.fitReason}`,
97
+ result.score.riskFlags.length ? `Risk flags:\n${list(result.score.riskFlags, 5)}` : "Risk flags: none",
98
+ "",
99
+ "Video angles:",
100
+ result.ideas.slice(0, 5).map((idea) => `- ${idea.title}: ${idea.angle}`).join("\n") || "No angles returned.",
101
+ upgradeCopy()
102
+ ].join("\n");
103
+ }
104
+ export function formatOpportunities(result) {
105
+ const visible = result.data
106
+ .slice(0, 12)
107
+ .map((item, index) => {
108
+ const window = item.crowdingWindowHours === null
109
+ ? "unknown crowding window"
110
+ : `${Math.max(1, Math.round(item.crowdingWindowHours / 24))}d estimated crowding window`;
111
+ return `${index + 1}. ${item.gameName} - score ${item.finalScore}, gap ${item.opportunityGapScore}, saturation ${item.saturationScore}, ${window}. Angle: ${item.suggestedVideoAngle}`;
112
+ })
113
+ .join("\n");
114
+ const locked = result.lockedOpportunities.length > 0
115
+ ? `\nLocked preview games: ${result.lockedOpportunities.slice(0, 8).map((item) => item.gameName).join(", ")}`
116
+ : "";
117
+ return [
118
+ "PeepTrend opportunity feed",
119
+ result.preview
120
+ ? "Free preview is active. Open a few full reports, then start the trial to unlock all details, generated ideas, alerts, and workflow."
121
+ : "Full feed is available for this account.",
122
+ "",
123
+ visible || "No opportunities returned for this market yet.",
124
+ locked,
125
+ upgradeCopy()
126
+ ].join("\n");
127
+ }
128
+ export function formatOpportunityDetail(result) {
129
+ const crowding = result.score.crowdingWindowHours === null
130
+ ? "not enough movement for a reliable crowding window yet"
131
+ : `about ${Math.max(1, Math.round(result.score.crowdingWindowHours / 24))} days`;
132
+ return [
133
+ `${result.game.name} - PeepTrend opportunity detail`,
134
+ `Score: ${result.score.finalScore}; momentum ${result.score.gameMomentumScore}; saturation ${result.score.youtubeSaturationScore}; gap ${result.score.opportunityGapScore}; query precision ${result.score.queryPrecisionScore}; crowding velocity ${result.score.crowdingVelocityScore}`,
135
+ `Estimated time before crowded: ${crowding}`,
136
+ `Why: ${result.score.explanation}`,
137
+ result.score.riskFlags.length ? `Risk flags:\n${list(result.score.riskFlags, 6)}` : "Risk flags: none",
138
+ "",
139
+ "Creator brief:",
140
+ `- Format: ${result.creatorBrief.recommendedFormat}`,
141
+ `- Suggested title: ${result.creatorBrief.suggestedTitle}`,
142
+ `- Hook: ${result.creatorBrief.hook}`,
143
+ `- Deadline: ${result.creatorBrief.deadline}`,
144
+ "",
145
+ "Saved ideas:",
146
+ result.videoIdeas.slice(0, 6).map((idea) => `- ${idea.title}: ${idea.reason}`).join("\n") || "No saved ideas returned.",
147
+ upgradeCopy()
148
+ ].join("\n");
149
+ }
150
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AASA,SAAS,MAAM,CAAC,KAAgC;IAC9C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,qBAAqB,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACtG,CAAC;AAED,SAAS,OAAO,CAAC,KAAgC;IAC/C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;AACjC,CAAC;AAED,SAAS,IAAI,CAAC,MAAgB,EAAE,KAAK,GAAG,CAAC;IACvC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;QACL,EAAE;QACF,2GAA2G;QAC3G,+BAA+B;KAChC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAItC;IACC,OAAO;QACL,iCAAiC,KAAK,CAAC,UAAU,GAAG;QACpD,KAAK,CAAC,aAAa;YACjB,CAAC,CAAC,8HAA8H;YAChI,CAAC,CAAC,sIAAsI;QAC1I,0BAA0B,KAAK,CAAC,cAAc,UAAU;QACxD,qBAAqB,KAAK,CAAC,cAAc,mBAAmB;KAC7D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAA4B;IAClE,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ;SAC/B,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACtB,MAAM,KAAK,GAAG;YACZ,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI;YAChD,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI;YAC9C,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;SACvC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAClB,OAAO,GAAG,KAAK,GAAG,CAAC,KAAK,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,MAAM,IAAI,WAAW,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,eAAe,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACxK,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;QACL,2BAA2B,MAAM,CAAC,KAAK,GAAG;QAC1C,qBAAqB,MAAM,CAAC,eAAe,EAAE;QAC7C,YAAY,MAAM,CAAC,OAAO,EAAE;QAC5B,EAAE;QACF,UAAU,IAAI,oCAAoC;QAClD,WAAW,EAAE;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAA0B;IAC1D,OAAO;QACL,4BAA4B,MAAM,CAAC,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG;QACpE,gBAAgB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,cAAc,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,mBAAmB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE;QACtK,oBAAoB,MAAM,CAAC,OAAO,CAAC,cAAc,gBAAgB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,gBAAgB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,eAAe,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE;QAC9P,mBAAmB,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE;QAClD,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB;QACpG,EAAE;QACF,sBAAsB;QACtB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,qBAAqB;QAC3M,WAAW,EAAE;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,MAA6B;IACvE,OAAO;QACL,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE;QAC5B,WAAW,MAAM,CAAC,KAAK,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG;QACnD,gBAAgB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,cAAc,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,mBAAmB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,kBAAkB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,yBAAyB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE;QACpS,YAAY,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE;QACzC,mBAAmB,MAAM,CAAC,OAAO,CAAC,cAAc,EAAE;QAClD,cAAc,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE;QACvC,EAAE;QACF,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,gBAAgB;QACpG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM;YAC1B,CAAC,CAAC,YAAY,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC9G,CAAC,CAAC,cAAc;QAClB,EAAE;QACF,kBAAkB;QAClB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,WAAW,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,qBAAqB;QACzK,WAAW,EAAE;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAyB;IAC/D,OAAO;QACL,mBAAmB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;QACrC,YAAY,MAAM,CAAC,KAAK,CAAC,YAAY,EAAE;QACvC,gBAAgB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,mBAAmB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;QACzG,MAAM,CAAC,IAAI,CAAC,OAAO;YACjB,CAAC,CAAC,UAAU,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,qBAAqB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW;YAChH,CAAC,CAAC,qCAAqC;QACzC,YAAY,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,kBAAkB,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,WAAW;QAChK,QAAQ,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE;QAClC,QAAQ,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE;QAChC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB;QACtG,EAAE;QACF,eAAe;QACf,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,qBAAqB;QAC5G,WAAW,EAAE;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAA6B;IAC/D,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI;SACxB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACnB,MAAM,MAAM,GACV,IAAI,CAAC,mBAAmB,KAAK,IAAI;YAC/B,CAAC,CAAC,yBAAyB;YAC3B,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC,6BAA6B,CAAC;QAC7F,OAAO,GAAG,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,QAAQ,YAAY,IAAI,CAAC,UAAU,SAAS,IAAI,CAAC,mBAAmB,gBAAgB,IAAI,CAAC,eAAe,KAAK,MAAM,YAAY,IAAI,CAAC,mBAAmB,EAAE,CAAC;IACzL,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,MAAM,GACV,MAAM,CAAC,mBAAmB,CAAC,MAAM,GAAG,CAAC;QACnC,CAAC,CAAC,2BAA2B,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAC7G,CAAC,CAAC,EAAE,CAAC;IAET,OAAO;QACL,4BAA4B;QAC5B,MAAM,CAAC,OAAO;YACZ,CAAC,CAAC,qIAAqI;YACvI,CAAC,CAAC,0CAA0C;QAC9C,EAAE;QACF,OAAO,IAAI,gDAAgD;QAC3D,MAAM;QACN,WAAW,EAAE;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAyB;IAC/D,MAAM,QAAQ,GACZ,MAAM,CAAC,KAAK,CAAC,mBAAmB,KAAK,IAAI;QACvC,CAAC,CAAC,wDAAwD;QAC1D,CAAC,CAAC,SAAS,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC;IAErF,OAAO;QACL,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,iCAAiC;QACpD,UAAU,MAAM,CAAC,KAAK,CAAC,UAAU,cAAc,MAAM,CAAC,KAAK,CAAC,iBAAiB,gBAAgB,MAAM,CAAC,KAAK,CAAC,sBAAsB,SAAS,MAAM,CAAC,KAAK,CAAC,mBAAmB,qBAAqB,MAAM,CAAC,KAAK,CAAC,mBAAmB,uBAAuB,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE;QACzR,kCAAkC,QAAQ,EAAE;QAC5C,QAAQ,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE;QAClC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB;QACtG,EAAE;QACF,gBAAgB;QAChB,aAAa,MAAM,CAAC,YAAY,CAAC,iBAAiB,EAAE;QACpD,sBAAsB,MAAM,CAAC,YAAY,CAAC,cAAc,EAAE;QAC1D,WAAW,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE;QACrC,eAAe,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE;QAC7C,EAAE;QACF,cAAc;QACd,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,0BAA0B;QACvH,WAAW,EAAE;KACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/server.js ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { renderDoctor, renderHelp, resolveCliAction, serverVersion } from "./cli.js";
5
+ import { loadConfig } from "./config.js";
6
+ import { registerPeepTrendTools } from "./tools.js";
7
+ const config = loadConfig();
8
+ const action = resolveCliAction(process.argv.slice(2), process.stdin.isTTY === true);
9
+ if (action === "help" || action === "manual") {
10
+ console.log(renderHelp(config));
11
+ process.exit(0);
12
+ }
13
+ if (action === "version") {
14
+ console.log(serverVersion);
15
+ process.exit(0);
16
+ }
17
+ if (action === "doctor") {
18
+ console.log(renderDoctor(config));
19
+ process.exit(0);
20
+ }
21
+ if (action === "unknown") {
22
+ console.error(renderHelp(config));
23
+ process.exit(1);
24
+ }
25
+ const server = new McpServer({
26
+ name: "PeepTrend: YouTube Gaming Trend Finder",
27
+ version: serverVersion
28
+ });
29
+ registerPeepTrendTools(server, config);
30
+ const transport = new StdioServerTransport();
31
+ await server.connect(transport);
32
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACrF,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;AAC5B,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;AAErF,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAChC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;IACzB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;IACxB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;IACzB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,wCAAwC;IAC9C,OAAO,EAAE,aAAa;CACvB,CAAC,CAAC;AAEH,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEvC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type PeepTrendMcpConfig } from "./config.js";
3
+ export declare function registerPeepTrendTools(server: McpServer, config: PeepTrendMcpConfig): void;