hermoso 0.1.231 → 0.1.233

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 (2) hide show
  1. package/mcp/tools.mjs +7 -7
  2. package/package.json +1 -1
package/mcp/tools.mjs CHANGED
@@ -5256,13 +5256,13 @@ function buildTools(rawServer, opts = {}, sink = null) {
5256
5256
  server.group('channel_admin');
5257
5257
  server.registerTool('youtube_channel', {
5258
5258
  title: 'Get the connected YouTube channel',
5259
- description: 'Read the brand’s connected YouTube channel — title + subscriber / view / video counts (for reporting). Needs a connected YouTube channel.',
5259
+ description: 'Read the brand’s connected YouTube channel — title + subscriber / view / video counts (for reporting), and whether CUSTOM THUMBNAILS are on (customThumbnails: enabled | needs_verification | unavailable | unknown). When they are not on, the reply carries YouTube’s own step-by-step to turn them on (a phone verification in YouTube Studio), so check this before promising a custom thumbnail. Needs a connected YouTube channel.',
5260
5260
  inputSchema: {},
5261
- outputSchema: { id: z.string().optional(), title: z.string().optional(), subscribers: z.string().optional(), views: z.string().optional(), videos: z.string().optional() },
5261
+ outputSchema: { id: z.string().optional(), title: z.string().optional(), subscribers: z.string().optional(), views: z.string().optional(), videos: z.string().optional(), customThumbnails: z.string().optional(), customThumbnailsNote: z.string().optional() },
5262
5262
  annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
5263
5263
  }, wrap(async () => {
5264
5264
  const d = await apiGet('/api/youtube/channel', {});
5265
- return ok(`${d.title} — ${d.subscribers} subscribers, ${d.videos} videos, ${d.views} total views.`, d);
5265
+ return ok(`${d.title} — ${d.subscribers} subscribers, ${d.videos} videos, ${d.views} total views.${d.customThumbnails && d.customThumbnails !== 'enabled' && d.customThumbnailsNote ? `\n${d.customThumbnailsNote}` : ''}`, d);
5266
5266
  }));
5267
5267
  // ── YOUTUBE: MEASURE + MANAGE (2026-07-30). We requested yt-analytics.readonly and youtube.force-ssl from day one
5268
5268
  // and shipped nothing that used them, so an agent could publish to YouTube and then neither measure nor manage it.
@@ -11350,11 +11350,11 @@ function buildTools(rawServer, opts = {}, sink = null) {
11350
11350
  inputSchema: { businessAgentId: z.string(), confirm: z.boolean().optional() }, annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
11351
11351
  }, wrap(async (a) => oaiNote(await apiPost('/api/openai-ads/business-agent/publish', a))));
11352
11352
  server.registerTool('list_openai_ads_spend_windows', {
11353
- title: 'List ChatGPT Ads account spending limits', description: 'Account-level SPENDING LIMITS on ChatGPT Ads, both kinds: the date-range SPEND-LIMIT WINDOWS (a ceiling on what the whole account may spend between an inclusive start date and an exclusive end date, with amount and spent so far) and the DAILY LIMIT (a per-day ceiling that renews at midnight in the account timezone, with what is spent and left today). Also returns the configuration `revision` that set_openai_ads_daily_spend_limit and remove_openai_ads_daily_spend_limit need as expectedRevision, and the earliest date a new daily limit may start. A limit caps spend; it never makes anything spend. OpenAI requires an admin of the ad account to read these. Read-only, 0 credits.',
11353
+ title: 'List ChatGPT Ads account spending limits', description: 'Account-level SPENDING LIMITS on ChatGPT Ads, both kinds: the date-range SPEND-LIMIT WINDOWS (a ceiling on what the whole account may spend between an inclusive start date and an exclusive end date, with amount and spent so far) and the DAILY LIMIT (a per-day ceiling that renews at midnight in the account timezone, with what is spent and left today). Also returns the configuration `revision` that set_openai_ads_daily_spend_limit and remove_openai_ads_daily_spend_limit need as expectedRevision, and the earliest date a new daily limit may start. A limit caps spend; it never makes anything spend. OpenAI serves account spending limits only to ad accounts on postpaid INVOICE billing, and every spending-limit request, reads included, needs billing-management permission: a card-billed account is refused (a 403 that says only admins can do it) from any key, including one its own admin created. Read-only, 0 credits.',
11354
11354
  inputSchema: {}, annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: true },
11355
11355
  }, wrap(async () => oaiNote(await apiGet('/api/openai-ads/spend-windows'))));
11356
11356
  server.registerTool('set_openai_ads_spend_window', {
11357
- title: 'Create or edit a ChatGPT Ads spend-limit window', description: 'Create (no windowId) or edit (windowId) an account-level spend-limit window on ChatGPT Ads: startDate YYYY-MM-DD inclusive, endDate YYYY-MM-DD EXCLUSIVE (the window ends the day before), amount in the account currency (sent as micros), optional name and insertion-order id (ioId). A window is a CEILING on what the whole account may spend in that range; it never makes anything spend, and campaign budgets still apply underneath it. On edit, pass only the fields that change; a window whose canEdit is false (already started, per OpenAI) cannot be edited. Raising the amount lets campaigns spend up to their budgets, so show the user the old and new amounts. Reply carries the stored window (amount, spent so far, status). MEASURED 2026-09-03: OpenAI\'s live API answered "Invalid URL" for this path although it is in their published spec; the tool reports that honestly until they ship it.',
11357
+ title: 'Create or edit a ChatGPT Ads spend-limit window', description: 'Create (no windowId) or edit (windowId) an account-level spend-limit window on ChatGPT Ads: startDate YYYY-MM-DD inclusive, endDate YYYY-MM-DD EXCLUSIVE (the window ends the day before), amount in the account currency (sent as micros), optional name and insertion-order id (ioId). A window is a CEILING on what the whole account may spend in that range; it never makes anything spend, and campaign budgets still apply underneath it. On edit, pass only the fields that change; a window whose canEdit is false (already started, per OpenAI) cannot be edited. Raising the amount lets campaigns spend up to their budgets, so show the user the old and new amounts. Reply carries the stored window (amount, spent so far, status). The live API serves this path since at least 2026-09-12 (it answered "Invalid URL" on 2026-09-03). It needs postpaid INVOICE billing and billing-management permission; a card-billed account is refused whatever key is used.',
11358
11358
  inputSchema: { windowId: z.string().optional(), startDate: z.string().optional(), endDate: z.string().optional(), amount: z.number().optional(), name: z.string().optional(), ioId: z.string().optional() },
11359
11359
  annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
11360
11360
  }, wrap(async (a) => oaiNote(await apiPost('/api/openai-ads/spend-window', a))));
@@ -11363,12 +11363,12 @@ function buildTools(rawServer, opts = {}, sink = null) {
11363
11363
  inputSchema: { windowId: z.string(), confirm: z.boolean().optional() }, annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
11364
11364
  }, wrap(async (a) => oaiNote(await apiPost('/api/openai-ads/spend-window/delete', a))));
11365
11365
  server.registerTool('set_openai_ads_daily_spend_limit', {
11366
- title: 'Set the ChatGPT Ads account daily spending limit', description: 'Create or change the ACCOUNT-WIDE DAILY SPENDING LIMIT on ChatGPT Ads: the most all campaigns together may spend each day, renewing at midnight in the account timezone, until it is removed or reaches its optional end date. OpenAI offers it only on ad accounts with postpaid invoice billing, and only an admin of the ad account can set it. amount is per day in the account currency and is required even when only the end date changes (0 stops account spend). A NEW limit starts tomorrow or later: list_openai_ads_spend_windows names the earliest start date. On an existing limit leave startDate out, because its start cannot change. endDate is exclusive; noEndDate:true clears it. A daily limit and a date-range window cannot overlap. Lowering it can stop delivery and raising it lets campaigns spend up to their own budgets, so show the user the current and new values first: without confirm:true AND expectedRevision (the revision list_openai_ads_spend_windows returns) nothing changes and the reply states what would. The result is read back from ChatGPT Ads.',
11366
+ title: 'Set the ChatGPT Ads account daily spending limit', description: 'Create or change the ACCOUNT-WIDE DAILY SPENDING LIMIT on ChatGPT Ads: the most all campaigns together may spend each day, renewing at midnight in the account timezone, until it is removed or reaches its optional end date. OpenAI offers it only on ad accounts with postpaid INVOICE billing and it needs billing-management permission; a card-billed account is refused whatever key is used. amount is per day in the account currency and is required even when only the end date changes (0 stops account spend). A NEW limit starts tomorrow or later: list_openai_ads_spend_windows names the earliest start date. On an existing limit leave startDate out, because its start cannot change. endDate is exclusive; noEndDate:true clears it. A daily limit and a date-range window cannot overlap. Lowering it can stop delivery and raising it lets campaigns spend up to their own budgets, so show the user the current and new values first: without confirm:true AND expectedRevision (the revision list_openai_ads_spend_windows returns) nothing changes and the reply states what would. The result is read back from ChatGPT Ads.',
11367
11367
  inputSchema: { amount: z.number(), expectedRevision: z.number().optional().describe('the revision from list_openai_ads_spend_windows'), startDate: z.string().optional().describe('YYYY-MM-DD, first day of a NEW daily limit (tomorrow or later)'), endDate: z.string().optional().describe('YYYY-MM-DD, exclusive'), noEndDate: z.boolean().optional().describe('true removes the end date'), confirm: z.boolean().optional() },
11368
11368
  annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
11369
11369
  }, wrap(async (a) => oaiNote(await apiPost('/api/openai-ads/daily-spend-limit', a))));
11370
11370
  server.registerTool('remove_openai_ads_daily_spend_limit', {
11371
- title: 'Remove the ChatGPT Ads account daily spending limit', description: 'Remove the account-wide DAILY spending limit on ChatGPT Ads. This takes a spending CEILING off the whole account, so campaigns may then spend up to their own budgets every day; date-range spend-limit windows are not touched. Only an admin of the ad account can do it. Without confirm:true AND expectedRevision (the revision list_openai_ads_spend_windows returns) nothing changes and the reply names the limit that would be removed. The result is read back from ChatGPT Ads.',
11371
+ title: 'Remove the ChatGPT Ads account daily spending limit', description: 'Remove the account-wide DAILY spending limit on ChatGPT Ads. This takes a spending CEILING off the whole account, so campaigns may then spend up to their own budgets every day; date-range spend-limit windows are not touched. Like every account spending-limit request it needs postpaid INVOICE billing and billing-management permission; a card-billed account is refused whatever key is used. Without confirm:true AND expectedRevision (the revision list_openai_ads_spend_windows returns) nothing changes and the reply names the limit that would be removed. The result is read back from ChatGPT Ads.',
11372
11372
  inputSchema: { expectedRevision: z.number().optional().describe('the revision from list_openai_ads_spend_windows'), confirm: z.boolean().optional() },
11373
11373
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
11374
11374
  }, wrap(async (a) => oaiNote(await apiPost('/api/openai-ads/daily-spend-limit/delete', a))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hermoso",
3
- "version": "0.1.231",
3
+ "version": "0.1.233",
4
4
  "mcpName": "io.github.hermoso-ai/hermoso",
5
5
  "description": "AI ad studio and marketing MCP server with 827 tools. Research the ads already running in any market, generate finished image, video and UGC avatar ads, publish and schedule them to your own channels, build and manage the ad campaigns behind them, and read what they achieved. AD PLATFORMS: Meta, Google Ads, TikTok Ads, LinkedIn Ads, Reddit Ads, X Ads, Pinterest Ads, Snapchat Ads, Microsoft Advertising, Apple Search Ads and ChatGPT Ads, plus product feeds in Google Merchant Center. PUBLISHING AND SCHEDULING: Facebook, Instagram, Threads, TikTok, YouTube, X, LinkedIn, Pinterest, Bluesky and Telegram. AD RESEARCH: the Meta, Google and LinkedIn ad libraries plus organic TikTok, Instagram, YouTube, Threads and Reddit. ANALYTICS: Google Analytics 4, Google Search Console and every connected platform's own post and campaign insights. Also brand onboarding, 50+ image and video generation models, ad scoring, competitor teardowns, Google Drive and OneDrive, a CLI and installable Claude skills.",
6
6
  "type": "module",