@yoonion/mimi-seed-mcp 0.6.4 → 0.6.6

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.
@@ -114,6 +114,18 @@ export declare function listAppInfoLocalizations(appId: string, locale?: string)
114
114
  }[];
115
115
  }>;
116
116
  export declare function updateAppInfoLocalization(localizationId: string, fields: AppInfoLocalizationFields): Promise<any>;
117
+ export declare function createAppInfoLocalization(appId: string, locale: string, fields: AppInfoLocalizationFields): Promise<{
118
+ appInfoId: string;
119
+ appInfoState: string;
120
+ localization: {
121
+ id: any;
122
+ locale: any;
123
+ name: any;
124
+ subtitle: any;
125
+ privacyPolicyUrl: any;
126
+ privacyPolicyText: any;
127
+ };
128
+ }>;
117
129
  export interface ListCustomerReviewsOptions {
118
130
  limit?: number;
119
131
  territory?: string;
@@ -440,6 +440,32 @@ export async function updateAppInfoLocalization(localizationId, fields) {
440
440
  },
441
441
  });
442
442
  }
443
+ export async function createAppInfoLocalization(appId, locale, fields) {
444
+ const attributes = Object.fromEntries(Object.entries(fields).filter(([, v]) => v !== undefined));
445
+ const { appInfoId, state } = await findEditableAppInfoId(appId);
446
+ const data = await apiPost('/appInfoLocalizations', {
447
+ data: {
448
+ type: 'appInfoLocalizations',
449
+ attributes: { locale, ...attributes },
450
+ relationships: {
451
+ appInfo: { data: { type: 'appInfos', id: appInfoId } },
452
+ },
453
+ },
454
+ });
455
+ const created = data?.data;
456
+ return {
457
+ appInfoId,
458
+ appInfoState: state,
459
+ localization: {
460
+ id: created?.id,
461
+ locale: created?.attributes?.locale,
462
+ name: created?.attributes?.name,
463
+ subtitle: created?.attributes?.subtitle,
464
+ privacyPolicyUrl: created?.attributes?.privacyPolicyUrl,
465
+ privacyPolicyText: created?.attributes?.privacyPolicyText,
466
+ },
467
+ };
468
+ }
443
469
  export async function listCustomerReviews(appId, opts = {}) {
444
470
  const params = {
445
471
  'sort': '-createdDate',
@@ -25,6 +25,12 @@ export interface PlayStatisticsQuery {
25
25
  export declare function withEdit<T>(auth: OAuth2Client | JWT, packageName: string, fn: (editId: string) => Promise<T>, commit?: boolean): Promise<T>;
26
26
  export declare function getStatistics(auth: OAuth2Client | JWT, packageName: string, query: PlayStatisticsQuery): Promise<unknown>;
27
27
  export declare function getAppDetails(auth: OAuth2Client | JWT, packageName: string): Promise<import("googleapis").androidpublisher_v3.Schema$AppDetails>;
28
+ export declare function updateAppDetails(auth: OAuth2Client | JWT, packageName: string, data: {
29
+ contactEmail?: string;
30
+ contactPhone?: string;
31
+ contactWebsite?: string;
32
+ defaultLanguage?: string;
33
+ }): Promise<import("googleapis").androidpublisher_v3.Schema$AppDetails>;
28
34
  export declare function getListing(auth: OAuth2Client | JWT, packageName: string, language?: string): Promise<import("googleapis").androidpublisher_v3.Schema$Listing>;
29
35
  export declare function updateListing(auth: OAuth2Client | JWT, packageName: string, language: string, data: {
30
36
  title?: string;
@@ -111,6 +111,22 @@ export async function getAppDetails(auth, packageName) {
111
111
  return details.data;
112
112
  });
113
113
  }
114
+ // ─── 앱 세부정보(개발자 연락처·기본 언어) 수정 ───
115
+ //
116
+ // edits.details = 스토어 리스팅(제목·설명)과 별개인 개발자 연락처(이메일/전화/웹사이트)
117
+ // 와 기본 언어. patch 로 부분 갱신 — 넘긴 필드만 교체하고 나머지 연락처는 보존한다
118
+ // (update=PUT 은 전체 치환이라 미지정 필드가 지워질 수 있어 patch 사용). edit → commit.
119
+ export async function updateAppDetails(auth, packageName, data) {
120
+ return withEdit(auth, packageName, async (editId) => {
121
+ const updated = await publisher().edits.details.patch({
122
+ auth,
123
+ packageName,
124
+ editId,
125
+ requestBody: data,
126
+ });
127
+ return updated.data;
128
+ }, true);
129
+ }
114
130
  // ─── 스토어 리스팅 조회 ───
115
131
  export async function getListing(auth, packageName, language = 'ko-KR') {
116
132
  return withEdit(auth, packageName, async (editId) => {
@@ -285,6 +285,23 @@ export function registerAppstoreTools(server) {
285
285
  const result = await appstore.updateAppInfoLocalization(localizationId, fields);
286
286
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
287
287
  });
288
+ server.tool('appstore_create_app_info_localization', [
289
+ 'appInfo 로컬라이제이션(스토어 언어) 추가 — POST /appInfoLocalizations.',
290
+ '편집 가능 appInfo를 자동으로 찾아 새 locale의 앱 이름/부제/개인정보 URL을 생성.',
291
+ '이미 존재하는 locale이면 409 DUPLICATE — 그땐 appstore_update_app_info_localization 사용.',
292
+ '생성하면 같은 locale의 버전 로컬라이제이션(설명/키워드/whatsNew)도 함께 생길 수 있음(2026-07 실측) — 내용 채우기는 appstore_update_localization.',
293
+ '제한: name 30자, subtitle 30자. locale 예: "en-US", "ja", "zh-Hans", "zh-Hant".',
294
+ ].join(' '), {
295
+ appId: z.string().describe('앱 ID (appstore_list_apps 결과)'),
296
+ locale: z.string().describe('추가할 언어 (예: "en-US", "ja", "zh-Hans", "zh-Hant")'),
297
+ name: z.string().optional().describe('앱 이름 (30자 이내)'),
298
+ subtitle: z.string().optional().describe('부제 (30자 이내)'),
299
+ privacyPolicyUrl: z.string().url().optional().describe('개인정보 처리방침 URL'),
300
+ privacyPolicyText: z.string().optional().describe('개인정보 처리방침 텍스트'),
301
+ }, async ({ appId, locale, ...fields }) => {
302
+ const result = await appstore.createAppInfoLocalization(appId, locale, fields);
303
+ return { content: [{ type: 'text', text: `✅ ${locale} 로컬라이제이션이 생성됐어.\n\n${JSON.stringify(result, null, 2)}` }] };
304
+ });
288
305
  server.tool('appstore_list_reviews', [
289
306
  'App Store 받은 고객 리뷰 조회 (최신순).',
290
307
  'response 필드에 개발자 답변 존재 여부와 내용이 함께 포함됨 (없으면 null).',
@@ -33,11 +33,24 @@ const playstore = new Proxy(playstoreRaw, {
33
33
  },
34
34
  });
35
35
  export function registerPlaystoreTools(server) {
36
- server.tool('playstore_get_app', 'Google Play 앱 상세 정보 조회', { packageName: z.string().describe('패키지명 (예: com.findthem.app)') }, async ({ packageName }) => {
36
+ server.tool('playstore_get_app', 'Google Play 앱 세부정보 조회 — 개발자 연락처(이메일·전화·웹사이트)·기본 언어 등 (edits.details). 수정은 playstore_update_details.', { packageName: z.string().describe('패키지명 (예: com.findthem.app)') }, async ({ packageName }) => {
37
37
  const auth = requirePlayStoreAuth(packageName);
38
38
  const details = await playstore.getAppDetails(auth, packageName);
39
39
  return { content: [{ type: 'text', text: JSON.stringify(details, null, 2) }] };
40
40
  });
41
+ server.tool('playstore_update_details', 'Google Play 앱 세부정보(개발자 연락처·기본 언어) 수정 — 연락처 이메일/전화/웹사이트, 기본 언어. 스토어 리스팅(제목·설명)과는 별개이며, 넘긴 필드만 부분 갱신(edits.details.patch). ⚠️ Console 에서 같은 앱을 편집·미게시 중이면 충돌할 수 있음.', {
42
+ packageName: z.string().describe('패키지명 (예: gg.pryzm.penguinrun)'),
43
+ contactEmail: z.string().optional().describe('개발자 연락처 이메일 (스토어 등록정보에 공개)'),
44
+ contactPhone: z.string().optional().describe('개발자 연락처 전화번호 (선택)'),
45
+ contactWebsite: z.string().optional().describe('개발자 웹사이트 URL (예: https://penguin.pryzm.gg)'),
46
+ defaultLanguage: z.string().optional().describe('기본 언어 코드 (예: ko-KR, en-US)'),
47
+ }, async ({ packageName, contactEmail, contactPhone, contactWebsite, defaultLanguage }) => {
48
+ const auth = requirePlayStoreAuth(packageName);
49
+ const result = await playstore.updateAppDetails(auth, packageName, {
50
+ contactEmail, contactPhone, contactWebsite, defaultLanguage,
51
+ });
52
+ return { content: [{ type: 'text', text: `수정 완료:\n${JSON.stringify(result, null, 2)}` }] };
53
+ });
41
54
  server.tool('playstore_get_listing', 'Google Play 스토어 리스팅 조회 (제목, 설명문 등)', {
42
55
  packageName: z.string().describe('패키지명'),
43
56
  language: z.string().default('ko-KR').describe('언어 코드 (기본: ko-KR)'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yoonion/mimi-seed-mcp",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "description": "Mimi Seed MCP server — Firebase + AdMob + Google Play + App Store management for Claude Code / Codex / Cursor / any MCP client.",
5
5
  "type": "module",
6
6
  "bin": {