hermoso 0.1.214 → 0.1.215
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 +14 -1
- package/package.json +1 -1
package/mcp/tools.mjs
CHANGED
|
@@ -2578,10 +2578,15 @@ function buildTools(rawServer, opts = {}, sink = null) {
|
|
|
2578
2578
|
if (g && !TOOL_GROUP_NAMES.includes(g)) return { content: [{ type: 'text', text: `Unknown group "${g}". Groups: ${TOOL_GROUP_NAMES.join(', ')}.` }], isError: true };
|
|
2579
2579
|
const rows = [];
|
|
2580
2580
|
const tokenWeight = tokenWeightFor(ctx);
|
|
2581
|
+
const _offGroup = new Map(); // name → { grp, h } for tools the group filter excluded (see below)
|
|
2581
2582
|
for (const [name, h] of Object.entries(ctx.handleOf)) {
|
|
2582
2583
|
if (!h) continue;
|
|
2583
2584
|
const grp = ctx.groupOf[name] || 'core';
|
|
2584
|
-
|
|
2585
|
+
// A GROUP FILTER NARROWS, IT NEVER HIDES (2026-09-07). `find_tools({query:'tiktok_creator_info', group:'channels'})` reported a
|
|
2586
|
+
// dead end because the tool lives in channel_admin — the exact-name hit was thrown away by the filter, and the agent
|
|
2587
|
+
// was told we have no such tool. Off-group matches are kept aside; if the scoped search finds nothing, they are
|
|
2588
|
+
// returned WITH their real group so the caller learns which group to enable instead of giving up.
|
|
2589
|
+
if (g && grp !== g) { if (!_offGroup.has(name)) _offGroup.set(name, { grp, h }); continue; }
|
|
2585
2590
|
const desc = String(h.description || '');
|
|
2586
2591
|
let score = 0;
|
|
2587
2592
|
if (q) {
|
|
@@ -2615,6 +2620,14 @@ function buildTools(rawServer, opts = {}, sink = null) {
|
|
|
2615
2620
|
// THE MOST VALUABLE ROW ON THE DEFECT BOARD: what a user asked for, in their agent's words, that our catalog could
|
|
2616
2621
|
// not name. Unquoted and lowercased on purpose — the ledger collapses quoted strings to <q>, and one group per
|
|
2617
2622
|
// distinct ask is exactly what we want to read.
|
|
2623
|
+
if (!total && g && _offGroup.size) {
|
|
2624
|
+
// Re-score the excluded tools by NAME only (the cheap, unambiguous half): an exact or token hit outside the
|
|
2625
|
+
// asked-for group is an answer, not a dead end — "it exists, in channel_admin; enable that group".
|
|
2626
|
+
const qw = String(q || '').toLowerCase().split(/[^a-z0-9_]+/).filter(Boolean);
|
|
2627
|
+
const off = [..._offGroup.entries()].filter(([name]) => qw.some((w) => name === w || name.includes(w))).slice(0, cap)
|
|
2628
|
+
.map(([name, { grp, h }]) => `• ${name} [${grp}, not in the ${g} group] — ${String(h.description || '').replace(/\s+/g, ' ').slice(0, 200)}`);
|
|
2629
|
+
if (off.length) return ok(`Nothing in the ${g} group matches, but these tools do — they live in another group (enable it with enable_tools, or call them by name through run_tool):\n${off.join('\n')}`, { query: q, group: g, offGroup: off.length });
|
|
2630
|
+
}
|
|
2618
2631
|
if (!total) reportDeadEnd('no_match', 'find_tools', `find_tools found nothing for: ${(q || '(empty)').replace(/["'`]/g, '').slice(0, 80)}${g ? ' in group ' + g : ''}`, { query: q, group: g });
|
|
2619
2632
|
for (const r of top) r.params = compactParams(ctx.handleOf[r.name]);
|
|
2620
2633
|
const lines = top.map((r) => `• ${r.name} [${r.group}${r.inRoster ? '' : ', not in your list'}${r.hold ? ', ' + r.hold : ''}] — ${r.description}\n params: ${Object.entries(r.params).map(([k, v]) => `${k}: ${v}`).join(' | ') || '(none)'}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hermoso",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.215",
|
|
4
4
|
"mcpName": "io.github.hermoso-ai/hermoso",
|
|
5
5
|
"description": "AI ad studio and marketing MCP server with 801 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",
|