@yoonion/mimi-seed-mcp 0.19.13 → 0.19.14
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/assets/agent-guide.md +9 -1
- package/dist/auth/cli.js +33 -8
- package/dist/auth/google-auth.d.ts +26 -5
- package/dist/auth/google-auth.js +132 -47
- package/dist/auth/youtube-channel.d.ts +8 -0
- package/dist/auth/youtube-channel.js +26 -0
- package/dist/googleads/errors.d.ts +2 -0
- package/dist/googleads/errors.js +31 -0
- package/dist/googleads/tools.d.ts +7 -0
- package/dist/googleads/tools.js +89 -46
- package/dist/helpers.d.ts +1 -1
- package/dist/helpers.js +10 -10
- package/dist/registers/auth.js +25 -4
- package/dist/registers/googleads.js +5 -2
- package/dist/registers/video.js +11 -5
- package/dist/video/schemas.d.ts +12 -12
- package/dist/video/youtube-publish.d.ts +11 -0
- package/dist/video/youtube-publish.js +7 -0
- package/package.json +3 -1
- package/scripts/googleads-report.mjs +32 -0
|
@@ -4,6 +4,7 @@ import { validateVideo } from './render.js';
|
|
|
4
4
|
export declare const YOUTUBE_SCOPE = "https://www.googleapis.com/auth/youtube.force-ssl";
|
|
5
5
|
export type YouTubePrivacyStatus = 'private' | 'unlisted' | 'public';
|
|
6
6
|
export interface UploadYouTubeVideoInput {
|
|
7
|
+
expectedChannelId: string;
|
|
7
8
|
filePath: string;
|
|
8
9
|
title: string;
|
|
9
10
|
description?: string;
|
|
@@ -36,6 +37,8 @@ declare function assertShortsCompatible(facts: ReturnType<typeof videoFacts>): v
|
|
|
36
37
|
export declare function getYouTubeVideoStatus(auth: OAuth2Client, videoId: string): Promise<{
|
|
37
38
|
videoId: string | null;
|
|
38
39
|
title: string | null;
|
|
40
|
+
channelId: string | null;
|
|
41
|
+
channelTitle: string | null;
|
|
39
42
|
privacyStatus: string | null;
|
|
40
43
|
uploadStatus: string | null;
|
|
41
44
|
processingStatus: string | null;
|
|
@@ -46,6 +49,10 @@ export declare function getYouTubeVideoStatus(auth: OAuth2Client, videoId: strin
|
|
|
46
49
|
studioUrl: string | null;
|
|
47
50
|
}>;
|
|
48
51
|
export declare function uploadYouTubeVideo(auth: OAuth2Client, input: UploadYouTubeVideoInput): Promise<{
|
|
52
|
+
authenticatedChannel: {
|
|
53
|
+
id: string;
|
|
54
|
+
title: string;
|
|
55
|
+
};
|
|
49
56
|
requestedPrivacyStatus: YouTubePrivacyStatus;
|
|
50
57
|
file: {
|
|
51
58
|
width?: number;
|
|
@@ -57,6 +64,8 @@ export declare function uploadYouTubeVideo(auth: OAuth2Client, input: UploadYouT
|
|
|
57
64
|
validationWarnings: string[];
|
|
58
65
|
videoId: string | null;
|
|
59
66
|
title: string | null;
|
|
67
|
+
channelId: string | null;
|
|
68
|
+
channelTitle: string | null;
|
|
60
69
|
privacyStatus: string | null;
|
|
61
70
|
uploadStatus: string | null;
|
|
62
71
|
processingStatus: string | null;
|
|
@@ -69,6 +78,8 @@ export declare function uploadYouTubeVideo(auth: OAuth2Client, input: UploadYouT
|
|
|
69
78
|
export declare function updateYouTubeVideoPrivacy(auth: OAuth2Client, input: UpdateYouTubePrivacyInput): Promise<{
|
|
70
79
|
videoId: string | null;
|
|
71
80
|
title: string | null;
|
|
81
|
+
channelId: string | null;
|
|
82
|
+
channelTitle: string | null;
|
|
72
83
|
privacyStatus: string | null;
|
|
73
84
|
uploadStatus: string | null;
|
|
74
85
|
processingStatus: string | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { verifyYouTubeChannel } from '../auth/youtube-channel.js';
|
|
1
2
|
import { createReadStream, existsSync, statSync } from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { google } from '../lib/googleapis-lite.js';
|
|
@@ -57,6 +58,8 @@ function safeStatus(video) {
|
|
|
57
58
|
return {
|
|
58
59
|
videoId: video.id ?? null,
|
|
59
60
|
title: video.snippet?.title ?? null,
|
|
61
|
+
channelId: video.snippet?.channelId ?? null,
|
|
62
|
+
channelTitle: video.snippet?.channelTitle ?? null,
|
|
60
63
|
privacyStatus: video.status?.privacyStatus ?? null,
|
|
61
64
|
uploadStatus: video.status?.uploadStatus ?? null,
|
|
62
65
|
processingStatus: video.processingDetails?.processingStatus ?? null,
|
|
@@ -86,6 +89,9 @@ export async function getYouTubeVideoStatus(auth, videoId) {
|
|
|
86
89
|
}
|
|
87
90
|
}
|
|
88
91
|
export async function uploadYouTubeVideo(auth, input) {
|
|
92
|
+
if (!input.expectedChannelId)
|
|
93
|
+
throw new Error('expectedChannelId is required before uploading.');
|
|
94
|
+
const channel = await verifyYouTubeChannel(auth, input.expectedChannelId);
|
|
89
95
|
const privacyStatus = input.privacyStatus ?? 'private';
|
|
90
96
|
assertVisibilityConfirmed(privacyStatus, input.confirmVisible);
|
|
91
97
|
const file = assertUploadFile(input.filePath);
|
|
@@ -131,6 +137,7 @@ export async function uploadYouTubeVideo(auth, input) {
|
|
|
131
137
|
throw new Error('YouTube 업로드 응답에 videoId가 없습니다.');
|
|
132
138
|
return {
|
|
133
139
|
...safeStatus(response.data),
|
|
140
|
+
authenticatedChannel: channel,
|
|
134
141
|
requestedPrivacyStatus: privacyStatus,
|
|
135
142
|
file: { path: input.filePath, size: file.size, ...facts },
|
|
136
143
|
validationWarnings: validation.issues,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yoonion/mimi-seed-mcp",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.14",
|
|
4
4
|
"description": "Mimi Seed MCP server \u2014 Firebase + AdMob + Google Play + App Store management for Claude Code / Codex / Cursor / any MCP client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,11 +20,13 @@
|
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|
|
23
|
+
"scripts/googleads-report.mjs",
|
|
23
24
|
"assets",
|
|
24
25
|
"tool-manifest.json",
|
|
25
26
|
"LICENSE"
|
|
26
27
|
],
|
|
27
28
|
"scripts": {
|
|
29
|
+
"report:googleads": "node scripts/googleads-report.mjs",
|
|
28
30
|
"build": "tsc",
|
|
29
31
|
"dev": "tsx src/index.ts",
|
|
30
32
|
"auth": "tsx src/auth/cli.ts",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Read-only entry point using the same implementation and auth as the MCP tools.
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import console from 'node:console';
|
|
5
|
+
import { requireAuth } from '../dist/helpers.js';
|
|
6
|
+
import { requireConfig } from '../dist/googleads/config.js';
|
|
7
|
+
import { getCampaignReport, REPORT_METRIC_NOTE } from '../dist/googleads/tools.js';
|
|
8
|
+
|
|
9
|
+
const [startDate, endDate, ...extra] = process.argv.slice(2);
|
|
10
|
+
if (!startDate || !endDate || extra.length) {
|
|
11
|
+
console.error('Usage: node scripts/googleads-report.mjs YYYY-MM-DD YYYY-MM-DD');
|
|
12
|
+
process.exitCode = 1;
|
|
13
|
+
} else {
|
|
14
|
+
try {
|
|
15
|
+
const auth = await requireAuth('https://www.googleapis.com/auth/adwords');
|
|
16
|
+
const config = requireConfig();
|
|
17
|
+
const campaigns = await getCampaignReport(auth, config, { startDate, endDate });
|
|
18
|
+
console.log(JSON.stringify({
|
|
19
|
+
period: { startDate, endDate },
|
|
20
|
+
fetchedAt: new Date().toISOString(),
|
|
21
|
+
customerId: config.customerId,
|
|
22
|
+
currencyCode: campaigns[0]?.currencyCode ?? null,
|
|
23
|
+
timeZone: campaigns[0]?.timeZone ?? null,
|
|
24
|
+
totalCost: campaigns.reduce((sum, row) => sum + row.cost, 0),
|
|
25
|
+
metricNote: REPORT_METRIC_NOTE,
|
|
26
|
+
campaigns,
|
|
27
|
+
}, null, 2));
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.error(error instanceof Error ? error.message : 'Google Ads report failed');
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
}
|
|
32
|
+
}
|