hermoso 0.1.181 → 0.1.183
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/mcp/tools.mjs +21 -13
- package/package.json +1 -1
package/mcp/tools.mjs
CHANGED
|
@@ -460,7 +460,9 @@ const geoLine = (r) => {
|
|
|
460
460
|
const dims = d.deliveredWidth && d.deliveredHeight ? `${d.deliveredWidth}x${d.deliveredHeight}` : '';
|
|
461
461
|
const bits = [dims, d.deliveredAspect, d.deliveredResolution].filter(Boolean);
|
|
462
462
|
if (!bits.length && !d.deliveryNote) return '';
|
|
463
|
-
|
|
463
|
+
// A worker's own disclosure rides the read-back (2026-09-01): the Multiplier reports `mechanism` (motion-transfer vs the
|
|
464
|
+
// video-edit fallback) and a `note` saying why — a caller who never sees them reads an edited take as a driven one.
|
|
465
|
+
return (bits.length ? `\nDelivered: ${bits.join(' · ')} (measured off the file)` : '') + (d.deliveryNote ? `\n⚠ ${d.deliveryNote}` : '') + (d.mechanism ? `\nMechanism: ${d.mechanism}` : '') + (d.note && d.note !== d.deliveryNote ? `\nℹ ${d.note}` : '');
|
|
464
466
|
};
|
|
465
467
|
|
|
466
468
|
// Shared outputSchema fields for the job-based render tools (the renderJob result that becomes structuredContent).
|
|
@@ -2901,17 +2903,7 @@ function buildTools(rawServer, opts = {}, sink = null) {
|
|
|
2901
2903
|
return ok(`Brands on this account:\n${lines}\n\nSwitch with use_brand.${sharedTxt}`, { ...d, sharedWorkspaces: shared });
|
|
2902
2904
|
}));
|
|
2903
2905
|
|
|
2904
|
-
|
|
2905
|
-
title: 'Switch brand',
|
|
2906
|
-
description: "Pin which brand this connection acts on (multi-brand accounts). Pass the brand id or exact name from list_brands. Works for a brand on your own account AND for a workspace another account SHARED with you — for a shared one pass its name or the profile id list_brands prints, and access is verified against your real membership before it is pinned. Persists for this API key until changed, on every surface (hosted connector included — no environment variables, no restart).",
|
|
2907
|
-
inputSchema: { brand: z.string().describe('brand id (e.g. default / p_xxx), its exact name from list_brands, or the profile id of a workspace shared with you') },
|
|
2908
|
-
outputSchema: {
|
|
2909
|
-
ok: z.boolean().optional().describe('true when the brand switch persisted'),
|
|
2910
|
-
brand: z.any().optional().describe('the now-active brand ({id, name})'),
|
|
2911
|
-
shared: z.boolean().optional().describe('true when the pinned workspace is owned by another account'),
|
|
2912
|
-
},
|
|
2913
|
-
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
2914
|
-
}, wrap(async ({ brand }) => {
|
|
2906
|
+
const makeUseBrandHandler = (ctx) => wrap(async ({ brand }) => {
|
|
2915
2907
|
const d = await apiGet('/api/brands');
|
|
2916
2908
|
const want = String(brand || '').trim().toLowerCase();
|
|
2917
2909
|
const hit = (d.brands || []).find(b => b.id.toLowerCase() === want || String(b.name || '').toLowerCase() === want);
|
|
@@ -2947,7 +2939,23 @@ function buildTools(rawServer, opts = {}, sink = null) {
|
|
|
2947
2939
|
const own = (d.brands || []).map(b => `• ${b.name} (id: ${b.id})`).join('\n');
|
|
2948
2940
|
const shr = shared.map(w => `• ${w.name || 'Shared workspace'}${w.ownerName ? ` — ${w.ownerName}` : ''} (id: ${w.profileUuid}, shared with you)`).join('\n');
|
|
2949
2941
|
return { content: [{ type: 'text', text: `No brand matching "${brand}". Available:\n${own}${shr ? `\n${shr}` : ''}` }], isError: true };
|
|
2950
|
-
})
|
|
2942
|
+
});
|
|
2943
|
+
server.registerTool('use_brand', {
|
|
2944
|
+
title: 'Switch brand',
|
|
2945
|
+
description: "Pin which brand this connection acts on (multi-brand accounts). Pass the brand id or exact name from list_brands. Works for a brand on your own account AND for a workspace another account SHARED with you — for a shared one pass its name or the profile id list_brands prints, and access is verified against your real membership before it is pinned. Persists for this API key until changed, on every surface (hosted connector included — no environment variables, no restart).",
|
|
2946
|
+
inputSchema: { brand: z.string().describe('brand id (e.g. default / p_xxx), its exact name from list_brands, or the profile id of a workspace shared with you') },
|
|
2947
|
+
outputSchema: {
|
|
2948
|
+
ok: z.boolean().optional().describe('true when the brand switch persisted'),
|
|
2949
|
+
brand: z.any().optional().describe('the now-active brand ({id, name})'),
|
|
2950
|
+
shared: z.boolean().optional().describe('true when the pinned workspace is owned by another account'),
|
|
2951
|
+
},
|
|
2952
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
2953
|
+
// PER-SESSION, LIKE enable_tools (2026-09-01): this handler re-gates `ctx.handleOf` — the roster of THE SESSION THAT
|
|
2954
|
+
// CALLED IT. A plain closure captured the ctx of the session that BUILT the canon (the first in the process), so every
|
|
2955
|
+
// later session got the right sentence ("re-scoped to 28 connectors") and the wrong roster: measured on prod, a
|
|
2956
|
+
// session pinned to a 0-connector brand switched to one with 28 and still listed 113 tools; `enable_tools` in the
|
|
2957
|
+
// same session said "3 more". It "worked" the morning it shipped because that measurement WAS the first session.
|
|
2958
|
+
}, sessionBound(makeUseBrandHandler, ctx));
|
|
2951
2959
|
|
|
2952
2960
|
// ── BRAND WORKSPACE LIFECYCLE. draft_brand OVERWRITES the active workspace's brand; it does not mint one — so
|
|
2953
2961
|
// without these an agency running Hermoso purely through an agent could never take on a second client.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermoso",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.183",
|
|
4
4
|
"mcpName": "io.github.hermoso-ai/hermoso",
|
|
5
5
|
"description": "AI ad studio and marketing MCP server with 745 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",
|