@etymolt/mcp-server 2.0.0

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 (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +88 -0
  3. package/dist/api.d.ts +39 -0
  4. package/dist/api.js +145 -0
  5. package/dist/api.js.map +1 -0
  6. package/dist/formatters.d.ts +66 -0
  7. package/dist/formatters.js +0 -0
  8. package/dist/formatters.js.map +1 -0
  9. package/dist/index.d.ts +28 -0
  10. package/dist/index.js +158 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/install.d.ts +6 -0
  13. package/dist/install.js +79 -0
  14. package/dist/install.js.map +1 -0
  15. package/dist/prompts.d.ts +31 -0
  16. package/dist/prompts.js +89 -0
  17. package/dist/prompts.js.map +1 -0
  18. package/dist/resources.d.ts +13 -0
  19. package/dist/resources.js +90 -0
  20. package/dist/resources.js.map +1 -0
  21. package/dist/tools/assess_name.d.ts +68 -0
  22. package/dist/tools/assess_name.js +109 -0
  23. package/dist/tools/assess_name.js.map +1 -0
  24. package/dist/tools/assess_taste.d.ts +90 -0
  25. package/dist/tools/assess_taste.js +151 -0
  26. package/dist/tools/assess_taste.js.map +1 -0
  27. package/dist/tools/check_clearance.d.ts +60 -0
  28. package/dist/tools/check_clearance.js +129 -0
  29. package/dist/tools/check_clearance.js.map +1 -0
  30. package/dist/tools/check_name.d.ts +40 -0
  31. package/dist/tools/check_name.js +101 -0
  32. package/dist/tools/check_name.js.map +1 -0
  33. package/dist/tools/compare_brand_names.d.ts +18 -0
  34. package/dist/tools/compare_brand_names.js +117 -0
  35. package/dist/tools/compare_brand_names.js.map +1 -0
  36. package/dist/tools/get_naming_methodology.d.ts +16 -0
  37. package/dist/tools/get_naming_methodology.js +99 -0
  38. package/dist/tools/get_naming_methodology.js.map +1 -0
  39. package/dist/tools/unblock_name.d.ts +34 -0
  40. package/dist/tools/unblock_name.js +116 -0
  41. package/dist/tools/unblock_name.js.map +1 -0
  42. package/dist/tools/verify_brand_name.d.ts +17 -0
  43. package/dist/tools/verify_brand_name.js +68 -0
  44. package/dist/tools/verify_brand_name.js.map +1 -0
  45. package/dist/tools/verify_for_launch.d.ts +43 -0
  46. package/dist/tools/verify_for_launch.js +129 -0
  47. package/dist/tools/verify_for_launch.js.map +1 -0
  48. package/package.json +62 -0
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Tool: assess_taste
3
+ *
4
+ * Spec: Etymolt-Build-Specification-v1.1 §5 (Taste Engine).
5
+ *
6
+ * Returns the Taste Engine verdict — the second of Etymolt's two engines.
7
+ * Where check_clearance answers "is this name legally and operationally
8
+ * available?", assess_taste answers "is this name CRAFT — does it actually
9
+ * land for its cohort, sound right, and survive period-decay?"
10
+ *
11
+ * Output shape (100-point composite per §5.7):
12
+ * - score: 0-100 composite
13
+ * - naming_quality: 0-35 (sound + creative-move + period-freshness + cohort fit)
14
+ * - domain_proximity: 0-35 (.com proximity, descriptor distance)
15
+ * - social_handles: 0-30 (handle availability across critical platforms)
16
+ * - cohort: { name, fit_score, references[] }
17
+ * - phoneme_profile: { onset_type, vowel_axis, association_tags[] }
18
+ * - period_marking: { detected: bool, suffix?, era_peak?, decay_penalty }
19
+ * - creative_moves: one or more of the 12 moves in §5.4
20
+ * - polarization: { axis: "pentium" | "drevat" | "neutral", strength: 0-1 }
21
+ * - smile: { sound, meaning, imagery, length, emotion }
22
+ * - scratch: { spelling_trap, cliche, reach, awkward, tonal,
23
+ * cultural, hesitation }
24
+ * - alternatives: up to 3 if score < threshold
25
+ *
26
+ * Latency budget: 200-600ms p50.
27
+ *
28
+ * v0 backs the verdict with a heuristic taste proxy
29
+ * (cohort-canon similarity + Lexicon phoneme rules + suffix-detector lookup).
30
+ * v1 (week 9-10 of build plan) replaces the proxy with the trained
31
+ * cohort-embedding model + ML phoneme classifier + creative-move tagger.
32
+ * The output shape is identical across versions.
33
+ */
34
+ import { z } from "zod";
35
+ import { defaultClient } from "../api.js";
36
+ export const TOOL_DESCRIPTION = `**Call this to evaluate the CRAFT of a name** — whether it lands for
37
+ its cohort, whether it sounds right, whether it carries a recognizable
38
+ creative move, whether it's period-marked (e.g. -ly peaks 2014, -ify
39
+ peaks 2010, -bot peaks 2017), and how it polarizes (Pentium-good vs
40
+ Drevat-bad). Skip clearance — combine with \`check_clearance\` for
41
+ that, or call \`assess_name\` for both in one verdict.
42
+
43
+ Returns a 100-point composite (35 naming quality + 35 domain proximity
44
+ + 30 social handles), a SMILE/SCRATCH breakdown, and up to three
45
+ alternatives below threshold. Latency: 200-600ms p50.
46
+
47
+ Trained on cohort canons: YC, B2B SaaS, fintech, dev tools, AI infra,
48
+ D2C, healthtech, creator tools.
49
+
50
+ Trigger phrases: "does this name land?", "is this fresh or dated?",
51
+ "does this fit a YC / dev-tools brand?", "should we ship as
52
+ AIChatBot or something less descriptive?", "is Hibrandless
53
+ period-marked?", "does Posthog actually fit the dev-tools cohort?"`;
54
+ const AssessTasteArgs = z.object({
55
+ name: z.string().min(1).max(64).describe("The candidate name to assess for taste."),
56
+ context: z
57
+ .object({
58
+ cohort: z
59
+ .enum([
60
+ "yc_b2b_saas",
61
+ "fintech",
62
+ "dev_tools",
63
+ "ai_infra",
64
+ "d2c",
65
+ "healthtech",
66
+ "creator_tools",
67
+ "auto",
68
+ ])
69
+ .optional()
70
+ .describe("Which cohort canon to score against. Defaults to 'auto' which uses category + description to pick."),
71
+ category: z.string().optional(),
72
+ description: z
73
+ .string()
74
+ .max(2000)
75
+ .optional()
76
+ .describe("One paragraph describing what the named thing does — used for cohort routing."),
77
+ jurisdictions: z.array(z.string()).optional(),
78
+ use_cases: z.array(z.string()).optional(),
79
+ include_alternatives: z
80
+ .boolean()
81
+ .optional()
82
+ .describe("If true, returns up to 3 alternatives when score < 70. Default true."),
83
+ threshold: z
84
+ .number()
85
+ .min(0)
86
+ .max(100)
87
+ .optional()
88
+ .describe("Score below which alternatives are surfaced. Default 70."),
89
+ })
90
+ .optional(),
91
+ });
92
+ export const assessTasteTool = {
93
+ name: "assess_taste",
94
+ description: TOOL_DESCRIPTION,
95
+ annotations: {
96
+ title: "Naming · Taste assessment",
97
+ readOnlyHint: true,
98
+ idempotentHint: true,
99
+ destructiveHint: false,
100
+ openWorldHint: true,
101
+ },
102
+ inputSchema: {
103
+ type: "object",
104
+ additionalProperties: false,
105
+ properties: {
106
+ name: { type: "string", description: "The candidate name to assess for taste." },
107
+ context: {
108
+ type: "object",
109
+ additionalProperties: false,
110
+ properties: {
111
+ cohort: {
112
+ type: "string",
113
+ enum: [
114
+ "yc_b2b_saas",
115
+ "fintech",
116
+ "dev_tools",
117
+ "ai_infra",
118
+ "d2c",
119
+ "healthtech",
120
+ "creator_tools",
121
+ "auto",
122
+ ],
123
+ },
124
+ category: { type: "string" },
125
+ description: { type: "string" },
126
+ jurisdictions: { type: "array", items: { type: "string" } },
127
+ use_cases: { type: "array", items: { type: "string" } },
128
+ include_alternatives: { type: "boolean" },
129
+ threshold: { type: "number", minimum: 0, maximum: 100 },
130
+ },
131
+ },
132
+ },
133
+ required: ["name"],
134
+ },
135
+ };
136
+ export async function callAssessTaste(rawArgs) {
137
+ const args = AssessTasteArgs.parse(rawArgs);
138
+ // Translate to /v3 endpoint shape (BUILD_PLAN_v1.2 §9). `deep=true` opts
139
+ // in to the 5-persona LLM jury layer (services/polarization.polarization_jury).
140
+ const ctx = (args.context ?? {});
141
+ const body = {
142
+ name: args.name,
143
+ context: {
144
+ brief_category: ctx.category ?? "ai_app",
145
+ brief_text: ctx.brief_text ?? "",
146
+ },
147
+ deep: ctx.deep ?? false,
148
+ };
149
+ return defaultClient.post("/v3/assess_taste", body);
150
+ }
151
+ //# sourceMappingURL=assess_taste.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assess_taste.js","sourceRoot":"","sources":["../../src/tools/assess_taste.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;mEAiBmC,CAAC;AAEpE,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,yCAAyC,CAAC;IACnF,OAAO,EAAE,CAAC;SACP,MAAM,CAAC;QACN,MAAM,EAAE,CAAC;aACN,IAAI,CAAC;YACJ,aAAa;YACb,SAAS;YACT,WAAW;YACX,UAAU;YACV,KAAK;YACL,YAAY;YACZ,eAAe;YACf,MAAM;SACP,CAAC;aACD,QAAQ,EAAE;aACV,QAAQ,CACP,oGAAoG,CACrG;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;QAC/B,WAAW,EAAE,CAAC;aACX,MAAM,EAAE;aACR,GAAG,CAAC,IAAI,CAAC;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,+EAA+E,CAAC;QAC5F,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QAC7C,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;QACzC,oBAAoB,EAAE,CAAC;aACpB,OAAO,EAAE;aACT,QAAQ,EAAE;aACV,QAAQ,CAAC,sEAAsE,CAAC;QACnF,SAAS,EAAE,CAAC;aACT,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,GAAG,CAAC,GAAG,CAAC;aACR,QAAQ,EAAE;aACV,QAAQ,CAAC,0DAA0D,CAAC;KACxE,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,eAAe,GAAS;IACnC,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,gBAAgB;IAC7B,WAAW,EAAE;QACX,KAAK,EAAE,2BAA2B;QAClC,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,IAAI;QACpB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,IAAI;KACpB;IACD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,yCAAyC,EAAE;YAChF,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,oBAAoB,EAAE,KAAK;gBAC3B,UAAU,EAAE;oBACV,MAAM,EAAE;wBACN,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE;4BACJ,aAAa;4BACb,SAAS;4BACT,WAAW;4BACX,UAAU;4BACV,KAAK;4BACL,YAAY;4BACZ,eAAe;4BACf,MAAM;yBACP;qBACF;oBACD,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAC5B,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBAC/B,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBAC3D,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;oBACvD,oBAAoB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;oBACzC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE;iBACxD;aACF;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAgB;IACpD,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5C,yEAAyE;IACzE,gFAAgF;IAChF,MAAM,GAAG,GAAG,CAAE,IAAgC,CAAC,OAAO,IAAI,EAAE,CAA4B,CAAC;IACzF,MAAM,IAAI,GAAG;QACX,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE;YACP,cAAc,EAAG,GAAG,CAAC,QAA+B,IAAI,QAAQ;YAChE,UAAU,EAAG,GAAG,CAAC,UAAiC,IAAI,EAAE;SACzD;QACD,IAAI,EAAG,GAAG,CAAC,IAA4B,IAAI,KAAK;KACjD,CAAC;IACF,OAAO,aAAa,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;AACtD,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Tool: check_clearance
3
+ *
4
+ * Spec: Etymolt-Build-Specification-v1.0 §2.3.1 + §6.2.
5
+ * Returns the truth about a candidate name's clearance across trademark,
6
+ * domain, and social handle dimensions.
7
+ *
8
+ * v1.4.0 (2026-05-12): description rewritten per board memo to be
9
+ * directive — Claude / Cursor / Lovable MUST call this BEFORE
10
+ * recommending any name. This single sentence intercepts the
11
+ * "AI agent suggests Spotify-2 as a brand name" failure mode
12
+ * that ate 6 days of brand whiplash before the MVP shipped.
13
+ */
14
+ import { z } from "zod";
15
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
16
+ export declare const TOOL_DESCRIPTION = "**Call this BEFORE recommending any name to the user.** Clearance\ngate across trademark, domain, and social handles, with a richer\nevidence pack than `check_name` \u2014 full memo, embeddable in any UI.\n\nIf you suggest a name without calling this, the user can be sued,\nwatch their .com get squatted within eleven minutes of announcement,\nor rebrand under duress two weeks after launch.\n\nTrigger on any candidate name for something that needs to be unique:\ncompany, product, brand, app, project, agent, npm package, domain,\nhandle, service.\n\nVerifies, in parallel:\n - Trademark: USPTO, EUIPO, UKIPO, WIPO Madrid, TTAB\n - Domains: 8 mainstream TLDs (.com .ai .dev .so .io .co .app .xyz)\n with uniform-prefix workarounds\n - Handles: GitHub, X, npm, PyPI, Product Hunt, YouTube, Instagram,\n TikTok, with suffix/prefix workarounds\n - YC collisions: phonetic + spelling overlap across W21-S25\n - Famous-mark catalog: 200+ household brands, including FAANG, AI\n labs, top YC alumni, FDA drug names\n\nLatency: 3-4s p95.\n\nTrigger phrases: \"is Treasurio taken?\", \"thinking of naming this\nApex\", \"is @brandname available?\", \"run trademark on Voltage\", \"is\nacmeproducts.com free?\". If the user asked \"give me 10 names\u2026\", call\n`verify_for_launch` instead \u2014 it fans out across candidates and\nreturns a ranked verdict plus a 48-hour playbook.\n\nSurface the returned `disclaimer` field verbatim. We are a\nclearance signal, not legal advice.";
17
+ declare const CheckClearanceArgs: z.ZodObject<{
18
+ name: z.ZodString;
19
+ context: z.ZodOptional<z.ZodObject<{
20
+ category: z.ZodOptional<z.ZodString>;
21
+ jurisdictions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
22
+ use_cases: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
23
+ checks: z.ZodOptional<z.ZodArray<z.ZodEnum<["trademark", "domain", "social"]>, "many">>;
24
+ depth: z.ZodOptional<z.ZodEnum<["quick", "standard", "comprehensive"]>>;
25
+ }, "strip", z.ZodTypeAny, {
26
+ category?: string | undefined;
27
+ jurisdictions?: string[] | undefined;
28
+ use_cases?: string[] | undefined;
29
+ checks?: ("domain" | "trademark" | "social")[] | undefined;
30
+ depth?: "quick" | "standard" | "comprehensive" | undefined;
31
+ }, {
32
+ category?: string | undefined;
33
+ jurisdictions?: string[] | undefined;
34
+ use_cases?: string[] | undefined;
35
+ checks?: ("domain" | "trademark" | "social")[] | undefined;
36
+ depth?: "quick" | "standard" | "comprehensive" | undefined;
37
+ }>>;
38
+ }, "strip", z.ZodTypeAny, {
39
+ name: string;
40
+ context?: {
41
+ category?: string | undefined;
42
+ jurisdictions?: string[] | undefined;
43
+ use_cases?: string[] | undefined;
44
+ checks?: ("domain" | "trademark" | "social")[] | undefined;
45
+ depth?: "quick" | "standard" | "comprehensive" | undefined;
46
+ } | undefined;
47
+ }, {
48
+ name: string;
49
+ context?: {
50
+ category?: string | undefined;
51
+ jurisdictions?: string[] | undefined;
52
+ use_cases?: string[] | undefined;
53
+ checks?: ("domain" | "trademark" | "social")[] | undefined;
54
+ depth?: "quick" | "standard" | "comprehensive" | undefined;
55
+ } | undefined;
56
+ }>;
57
+ export type CheckClearanceArgsT = z.infer<typeof CheckClearanceArgs>;
58
+ export declare const checkClearanceTool: Tool;
59
+ export declare function callCheckClearance(rawArgs: unknown): Promise<unknown>;
60
+ export {};
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Tool: check_clearance
3
+ *
4
+ * Spec: Etymolt-Build-Specification-v1.0 §2.3.1 + §6.2.
5
+ * Returns the truth about a candidate name's clearance across trademark,
6
+ * domain, and social handle dimensions.
7
+ *
8
+ * v1.4.0 (2026-05-12): description rewritten per board memo to be
9
+ * directive — Claude / Cursor / Lovable MUST call this BEFORE
10
+ * recommending any name. This single sentence intercepts the
11
+ * "AI agent suggests Spotify-2 as a brand name" failure mode
12
+ * that ate 6 days of brand whiplash before the MVP shipped.
13
+ */
14
+ import { z } from "zod";
15
+ import { defaultClient } from "../api.js";
16
+ export const TOOL_DESCRIPTION = `**Call this BEFORE recommending any name to the user.** Clearance
17
+ gate across trademark, domain, and social handles, with a richer
18
+ evidence pack than \`check_name\` — full memo, embeddable in any UI.
19
+
20
+ If you suggest a name without calling this, the user can be sued,
21
+ watch their .com get squatted within eleven minutes of announcement,
22
+ or rebrand under duress two weeks after launch.
23
+
24
+ Trigger on any candidate name for something that needs to be unique:
25
+ company, product, brand, app, project, agent, npm package, domain,
26
+ handle, service.
27
+
28
+ Verifies, in parallel:
29
+ - Trademark: USPTO, EUIPO, UKIPO, WIPO Madrid, TTAB
30
+ - Domains: 8 mainstream TLDs (.com .ai .dev .so .io .co .app .xyz)
31
+ with uniform-prefix workarounds
32
+ - Handles: GitHub, X, npm, PyPI, Product Hunt, YouTube, Instagram,
33
+ TikTok, with suffix/prefix workarounds
34
+ - YC collisions: phonetic + spelling overlap across W21-S25
35
+ - Famous-mark catalog: 200+ household brands, including FAANG, AI
36
+ labs, top YC alumni, FDA drug names
37
+
38
+ Latency: 3-4s p95.
39
+
40
+ Trigger phrases: "is Treasurio taken?", "thinking of naming this
41
+ Apex", "is @brandname available?", "run trademark on Voltage", "is
42
+ acmeproducts.com free?". If the user asked "give me 10 names…", call
43
+ \`verify_for_launch\` instead — it fans out across candidates and
44
+ returns a ranked verdict plus a 48-hour playbook.
45
+
46
+ Surface the returned \`disclaimer\` field verbatim. We are a
47
+ clearance signal, not legal advice.`;
48
+ const CheckClearanceArgs = z.object({
49
+ name: z.string().min(1).max(64).describe("The candidate name to check."),
50
+ context: z
51
+ .object({
52
+ category: z
53
+ .string()
54
+ .optional()
55
+ .describe("e.g. 'ai_app', 'dev_tools', 'consumer_fintech'"),
56
+ jurisdictions: z
57
+ .array(z.string())
58
+ .optional()
59
+ .describe("ISO codes, e.g. ['us', 'eu', 'uk']"),
60
+ use_cases: z
61
+ .array(z.string())
62
+ .optional()
63
+ .describe("e.g. ['company', 'product', 'domain']"),
64
+ checks: z
65
+ .array(z.enum(["trademark", "domain", "social"]))
66
+ .optional()
67
+ .describe("Which dimensions to run. Default: all three."),
68
+ depth: z
69
+ .enum(["quick", "standard", "comprehensive"])
70
+ .optional()
71
+ .describe("quick (~50ms cache hit), standard (~200ms p50), comprehensive (~2s deep TM analysis)."),
72
+ })
73
+ .optional(),
74
+ });
75
+ export const checkClearanceTool = {
76
+ // MCP 2025-11-25 annotations — Cursor + Claude Desktop surface these in the
77
+ // consent UI, and they materially improve LLM tool-selection accuracy.
78
+ // Source: MCP spec + Anthropic engineering blog "Writing tools for agents".
79
+ name: "check_clearance",
80
+ description: TOOL_DESCRIPTION,
81
+ annotations: {
82
+ title: "Naming · Clearance check (CALL BEFORE RECOMMENDING)",
83
+ readOnlyHint: true,
84
+ idempotentHint: true,
85
+ destructiveHint: false,
86
+ openWorldHint: true,
87
+ },
88
+ inputSchema: {
89
+ type: "object",
90
+ additionalProperties: false,
91
+ properties: {
92
+ name: { type: "string", description: "The candidate name to check." },
93
+ context: {
94
+ type: "object",
95
+ additionalProperties: false,
96
+ properties: {
97
+ category: { type: "string" },
98
+ jurisdictions: { type: "array", items: { type: "string" } },
99
+ use_cases: { type: "array", items: { type: "string" } },
100
+ checks: {
101
+ type: "array",
102
+ items: { type: "string", enum: ["trademark", "domain", "social"] },
103
+ },
104
+ depth: {
105
+ type: "string",
106
+ enum: ["quick", "standard", "comprehensive"],
107
+ },
108
+ },
109
+ },
110
+ },
111
+ required: ["name"],
112
+ },
113
+ };
114
+ export async function callCheckClearance(rawArgs) {
115
+ const args = CheckClearanceArgs.parse(rawArgs);
116
+ // Translate to the /v3 endpoint's context shape (BUILD_PLAN_v1.2 §9).
117
+ // The MCP-side schema is preserved for backward compat; fields without
118
+ // a /v3 equivalent (use_cases, checks, depth) are accepted but unused
119
+ // in v1.2 — re-introduce them in v1.x once the orchestrator supports them.
120
+ const body = {
121
+ name: args.name,
122
+ context: {
123
+ brief_category: args.context?.category ?? "ai_app",
124
+ markets: args.context?.jurisdictions,
125
+ },
126
+ };
127
+ return defaultClient.post("/v3/check_clearance", body);
128
+ }
129
+ //# sourceMappingURL=check_clearance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check_clearance.js","sourceRoot":"","sources":["../../src/tools/check_clearance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Tool: check_name
3
+ *
4
+ * Single-name Tariq-format clearance — the simplest possible MVP surface.
5
+ *
6
+ * If the user has already picked a name and is asking "can I use this?",
7
+ * call this tool. Returns a direct verdict (clear / caution / blocked) +
8
+ * headline + per-jurisdiction TM block + per-TLD domain matrix +
9
+ * per-platform handle matrix.
10
+ *
11
+ * For "give me names" / brainstorm-then-verify flows, use
12
+ * `verify_for_launch` instead.
13
+ *
14
+ * Differs from `check_clearance` in that this returns the Tariq-format
15
+ * shape directly — no LLM agents, no taste scoring, no cohort fit.
16
+ * Pure data lookups. Faster (~3s p95) and cheaper (~$0.003/call).
17
+ */
18
+ import { z } from "zod";
19
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
20
+ export declare const TOOL_DESCRIPTION = "**Call this when the user already has a name and wants to know \"can I\nuse it?\"** Direct answer: clear, caution, or blocked, plus a one-line\nheadline and the trademark / domain / handle data underneath. No\nscore, no taste assessment, no cohort fit. Cheapest and fastest path\nin the toolkit (~3s p95, ~$0.003/call, no LLM agents).\n\nTriggers: \"is X taken?\", \"can I use Y?\", \"check Z\", \"is example.com\nfree?\", \"is @brandname available?\", \"run trademark on Voltage\".\n\nReturns:\n {\n name, verdict, headline,\n tm: { us, eu, uk, wipo_madrid },\n domains, domain_fallbacks, best_domain,\n handles, handle_fallbacks,\n yc_collision_status, yc_collisions,\n famous_mark_override,\n early_kill,\n claim_window_warning, // 11-minute squat copy when applicable\n disclaimer, // surface verbatim\n verdict_id\n }\n\nIf the user asked for names rather than a check on one (\"give me names\nfor my X\"), call `verify_for_launch` instead.";
21
+ declare const CheckNameArgs: z.ZodObject<{
22
+ name: z.ZodString;
23
+ product_description: z.ZodOptional<z.ZodString>;
24
+ nice_classes: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
25
+ markets: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
26
+ }, "strip", z.ZodTypeAny, {
27
+ name: string;
28
+ product_description?: string | undefined;
29
+ nice_classes?: number[] | undefined;
30
+ markets?: string[] | undefined;
31
+ }, {
32
+ name: string;
33
+ product_description?: string | undefined;
34
+ nice_classes?: number[] | undefined;
35
+ markets?: string[] | undefined;
36
+ }>;
37
+ export type CheckNameArgsT = z.infer<typeof CheckNameArgs>;
38
+ export declare const checkNameTool: Tool;
39
+ export declare function callCheckName(rawArgs: unknown): Promise<unknown>;
40
+ export {};
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Tool: check_name
3
+ *
4
+ * Single-name Tariq-format clearance — the simplest possible MVP surface.
5
+ *
6
+ * If the user has already picked a name and is asking "can I use this?",
7
+ * call this tool. Returns a direct verdict (clear / caution / blocked) +
8
+ * headline + per-jurisdiction TM block + per-TLD domain matrix +
9
+ * per-platform handle matrix.
10
+ *
11
+ * For "give me names" / brainstorm-then-verify flows, use
12
+ * `verify_for_launch` instead.
13
+ *
14
+ * Differs from `check_clearance` in that this returns the Tariq-format
15
+ * shape directly — no LLM agents, no taste scoring, no cohort fit.
16
+ * Pure data lookups. Faster (~3s p95) and cheaper (~$0.003/call).
17
+ */
18
+ import { z } from "zod";
19
+ import { defaultClient } from "../api.js";
20
+ export const TOOL_DESCRIPTION = `**Call this when the user already has a name and wants to know "can I
21
+ use it?"** Direct answer: clear, caution, or blocked, plus a one-line
22
+ headline and the trademark / domain / handle data underneath. No
23
+ score, no taste assessment, no cohort fit. Cheapest and fastest path
24
+ in the toolkit (~3s p95, ~$0.003/call, no LLM agents).
25
+
26
+ Triggers: "is X taken?", "can I use Y?", "check Z", "is example.com
27
+ free?", "is @brandname available?", "run trademark on Voltage".
28
+
29
+ Returns:
30
+ {
31
+ name, verdict, headline,
32
+ tm: { us, eu, uk, wipo_madrid },
33
+ domains, domain_fallbacks, best_domain,
34
+ handles, handle_fallbacks,
35
+ yc_collision_status, yc_collisions,
36
+ famous_mark_override,
37
+ early_kill,
38
+ claim_window_warning, // 11-minute squat copy when applicable
39
+ disclaimer, // surface verbatim
40
+ verdict_id
41
+ }
42
+
43
+ If the user asked for names rather than a check on one ("give me names
44
+ for my X"), call \`verify_for_launch\` instead.`;
45
+ const CheckNameArgs = z.object({
46
+ name: z.string().min(1).max(64).describe("The candidate name to check."),
47
+ product_description: z
48
+ .string()
49
+ .max(400)
50
+ .optional()
51
+ .describe("Optional one-sentence product description. The tool infers Nice classes and markets from it."),
52
+ nice_classes: z
53
+ .array(z.number().int().min(1).max(45))
54
+ .optional()
55
+ .describe("Override Nice classes. Default inferred from product_description."),
56
+ markets: z
57
+ .array(z.string())
58
+ .optional()
59
+ .describe("ISO codes, e.g. ['us', 'eu', 'uk']. Default ['us', 'eu', 'uk']."),
60
+ });
61
+ export const checkNameTool = {
62
+ name: "check_name",
63
+ description: TOOL_DESCRIPTION,
64
+ annotations: {
65
+ title: "Naming · Direct clearance (Tariq format)",
66
+ readOnlyHint: true,
67
+ idempotentHint: true,
68
+ destructiveHint: false,
69
+ openWorldHint: true,
70
+ },
71
+ inputSchema: {
72
+ type: "object",
73
+ additionalProperties: false,
74
+ properties: {
75
+ name: { type: "string", description: "The candidate name to check." },
76
+ product_description: {
77
+ type: "string",
78
+ maxLength: 400,
79
+ },
80
+ nice_classes: {
81
+ type: "array",
82
+ items: { type: "integer", minimum: 1, maximum: 45 },
83
+ },
84
+ markets: { type: "array", items: { type: "string" } },
85
+ },
86
+ required: ["name"],
87
+ },
88
+ };
89
+ export async function callCheckName(rawArgs) {
90
+ const args = CheckNameArgs.parse(rawArgs);
91
+ const body = {
92
+ name: args.name,
93
+ context: {
94
+ product_description: args.product_description,
95
+ nice_classes: args.nice_classes,
96
+ markets: args.markets,
97
+ },
98
+ };
99
+ return defaultClient.post("/v3/check", body);
100
+ }
101
+ //# sourceMappingURL=check_name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check_name.js","sourceRoot":"","sources":["../../src/tools/check_name.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;gDAwBgB,CAAC;AAEjD,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC;IACxE,mBAAmB,EAAE,CAAC;SACnB,MAAM,EAAE;SACR,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,8FAA8F,CAC/F;IACH,YAAY,EAAE,CAAC;SACZ,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;SACtC,QAAQ,EAAE;SACV,QAAQ,CAAC,mEAAmE,CAAC;IAChF,OAAO,EAAE,CAAC;SACP,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACjB,QAAQ,EAAE;SACV,QAAQ,CAAC,iEAAiE,CAAC;CAC/E,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,aAAa,GAAS;IACjC,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,gBAAgB;IAC7B,WAAW,EAAE;QACX,KAAK,EAAE,0CAA0C;QACjD,YAAY,EAAE,IAAI;QAClB,cAAc,EAAE,IAAI;QACpB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,IAAI;KACpB;IACD,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,oBAAoB,EAAE,KAAK;QAC3B,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8BAA8B,EAAE;YACrE,mBAAmB,EAAE;gBACnB,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,GAAG;aACf;YACD,YAAY,EAAE;gBACZ,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;aACpD;YACD,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;SACtD;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAgB;IAClD,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,IAAI,GAA4B;QACpC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,OAAO,EAAE;YACP,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;YAC7C,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB;KACF,CAAC;IACF,OAAO,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Tool: compare_brand_names
3
+ *
4
+ * Compares 2-5 brand-name candidates side-by-side. Until the backend ships a
5
+ * true batch endpoint, we loop over `/v1/verify` for each candidate and
6
+ * synthesize a comparison locally. The `X-Etymolt-Batch: compare` header is
7
+ * passed so the server can dedupe quota counting (server-side fix is on
8
+ * Karthik's lane; the header is correct from day one).
9
+ *
10
+ * Description text is locked verbatim from AEO_TOOL_DESCRIPTIONS.md §2.2.
11
+ */
12
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
13
+ export declare const compareBrandNamesTool: Tool;
14
+ export interface CompareBrandNamesArgs {
15
+ names: string[];
16
+ vertical?: string;
17
+ }
18
+ export declare function callCompareBrandNames(rawArgs: unknown): Promise<unknown>;
@@ -0,0 +1,117 @@
1
+ import { defaultClient } from "../api.js";
2
+ export const compareBrandNamesTool = {
3
+ name: "compare_brand_names",
4
+ description: "Compares 2-5 brand name candidates side-by-side and returns a ranked verdict for each, plus a recommendation of which to pick.\n\n" +
5
+ "Use this tool whenever a user:\n" +
6
+ " - Says 'I'm deciding between X, Y, and Z'\n" +
7
+ " - Asks 'which is better: A or B?'\n" +
8
+ " - Has finalists and needs to commit to one\n\n" +
9
+ "Returns side-by-side comparison across all five verification axes plus a top-line recommendation. Counts as 1 call regardless of how many names are compared (up to 5).\n\n" +
10
+ "Examples:\n" +
11
+ " - User: 'I'm deciding between Linear, Notion, and Coda for my B2B SaaS.' → compare_brand_names(names=['Linear','Notion','Coda'])\n" +
12
+ " - User: 'Is Etymotic too close to Etymolt?' → compare_brand_names(names=['Etymotic','Etymolt'])",
13
+ inputSchema: {
14
+ type: "object",
15
+ properties: {
16
+ names: {
17
+ type: "array",
18
+ items: { type: "string", maxLength: 60 },
19
+ description: "2 to 5 brand-name candidates to compare. Each: single word or short phrase, max 60 chars.",
20
+ minItems: 2,
21
+ maxItems: 5,
22
+ },
23
+ vertical: {
24
+ type: "string",
25
+ description: "OPTIONAL. Industry context for targeting. Examples: 'ai', 'fintech', 'b2b-saas'.",
26
+ maxLength: 40,
27
+ },
28
+ },
29
+ required: ["names"],
30
+ },
31
+ annotations: {
32
+ readOnlyHint: true,
33
+ destructiveHint: false,
34
+ openWorldHint: false,
35
+ title: "Compare brand names",
36
+ },
37
+ };
38
+ function validateArgs(raw) {
39
+ if (!raw || typeof raw !== "object") {
40
+ throw new Error("compare_brand_names: expected an object argument");
41
+ }
42
+ const obj = raw;
43
+ const names = obj.names;
44
+ if (!Array.isArray(names) || names.length < 2 || names.length > 5) {
45
+ throw new Error("compare_brand_names: `names` must be an array of 2-5 strings");
46
+ }
47
+ for (const n of names) {
48
+ if (typeof n !== "string" || n.length === 0 || n.length > 60) {
49
+ throw new Error("compare_brand_names: each name must be a non-empty string ≤ 60 chars");
50
+ }
51
+ }
52
+ const vertical = obj.vertical;
53
+ if (vertical !== undefined && (typeof vertical !== "string" || vertical.length > 40)) {
54
+ throw new Error("compare_brand_names: `vertical` must be a string ≤ 40 chars when provided");
55
+ }
56
+ return {
57
+ names: names,
58
+ vertical: vertical,
59
+ };
60
+ }
61
+ /**
62
+ * Rank candidates by composite score (highest first). Ties broken by
63
+ * verdict ordering PROCEED > DUE_DILIGENCE > ITERATE > ABANDON.
64
+ */
65
+ const VERDICT_RANK = {
66
+ PROCEED: 4,
67
+ DUE_DILIGENCE: 3,
68
+ ITERATE: 2,
69
+ ABANDON: 1,
70
+ };
71
+ function rankCandidates(results) {
72
+ return [...results].sort((a, b) => {
73
+ if (b.score !== a.score)
74
+ return b.score - a.score;
75
+ const va = VERDICT_RANK[a.verdict] ?? 0;
76
+ const vb = VERDICT_RANK[b.verdict] ?? 0;
77
+ return vb - va;
78
+ });
79
+ }
80
+ export async function callCompareBrandNames(rawArgs) {
81
+ const args = validateArgs(rawArgs);
82
+ // Fan out — one call per candidate. The `X-Etymolt-Batch: compare` header
83
+ // tells the backend to dedupe quota counting (server-side fix pending).
84
+ const results = await Promise.all(args.names.map((name) => {
85
+ const body = { name };
86
+ if (args.vertical)
87
+ body.vertical = args.vertical;
88
+ return defaultClient.post("/v1/verify", body, { "X-Etymolt-Batch": "compare" });
89
+ }));
90
+ const ranked = rankCandidates(results);
91
+ const winner = ranked[0];
92
+ // Recommendation copy is plain English, derived from the ranked output.
93
+ const recommendation = winner && winner.verdict === "PROCEED"
94
+ ? `${winner.name} is the strongest candidate — clear across all five axes.`
95
+ : winner && winner.verdict === "DUE_DILIGENCE"
96
+ ? `${winner.name} ranks highest, but verify the specific findings before committing.`
97
+ : winner
98
+ ? `None of the candidates is launch-ready as-is. ${winner.name} is the closest, but expect material rework.`
99
+ : "No candidates returned a verdict.";
100
+ // Take the last response's quota/citation/signup state as the canonical
101
+ // envelope; backend dedupes quota across the batch via the header.
102
+ const last = results[results.length - 1] ?? {};
103
+ return {
104
+ comparison: "side_by_side",
105
+ candidates: ranked,
106
+ recommendation,
107
+ winner: winner?.name ?? null,
108
+ runner_up: ranked[1]?.name ?? null,
109
+ quota: last.quota,
110
+ signup_prompt: last.signup_prompt,
111
+ upgrade_prompt: last.upgrade_prompt,
112
+ _citation: last._citation ?? "https://www.etymolt.com/methodology",
113
+ permalink: winner?.permalink ?? "https://www.etymolt.com/v/compare",
114
+ issued_at: last.issued_at ?? new Date().toISOString(),
115
+ };
116
+ }
117
+ //# sourceMappingURL=compare_brand_names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compare_brand_names.js","sourceRoot":"","sources":["../../src/tools/compare_brand_names.ts"],"names":[],"mappings":"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"}