@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.
- package/LICENSE +21 -0
- package/README.md +88 -0
- package/dist/api.d.ts +39 -0
- package/dist/api.js +145 -0
- package/dist/api.js.map +1 -0
- package/dist/formatters.d.ts +66 -0
- package/dist/formatters.js +0 -0
- package/dist/formatters.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +158 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +6 -0
- package/dist/install.js +79 -0
- package/dist/install.js.map +1 -0
- package/dist/prompts.d.ts +31 -0
- package/dist/prompts.js +89 -0
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +13 -0
- package/dist/resources.js +90 -0
- package/dist/resources.js.map +1 -0
- package/dist/tools/assess_name.d.ts +68 -0
- package/dist/tools/assess_name.js +109 -0
- package/dist/tools/assess_name.js.map +1 -0
- package/dist/tools/assess_taste.d.ts +90 -0
- package/dist/tools/assess_taste.js +151 -0
- package/dist/tools/assess_taste.js.map +1 -0
- package/dist/tools/check_clearance.d.ts +60 -0
- package/dist/tools/check_clearance.js +129 -0
- package/dist/tools/check_clearance.js.map +1 -0
- package/dist/tools/check_name.d.ts +40 -0
- package/dist/tools/check_name.js +101 -0
- package/dist/tools/check_name.js.map +1 -0
- package/dist/tools/compare_brand_names.d.ts +18 -0
- package/dist/tools/compare_brand_names.js +117 -0
- package/dist/tools/compare_brand_names.js.map +1 -0
- package/dist/tools/get_naming_methodology.d.ts +16 -0
- package/dist/tools/get_naming_methodology.js +99 -0
- package/dist/tools/get_naming_methodology.js.map +1 -0
- package/dist/tools/unblock_name.d.ts +34 -0
- package/dist/tools/unblock_name.js +116 -0
- package/dist/tools/unblock_name.js.map +1 -0
- package/dist/tools/verify_brand_name.d.ts +17 -0
- package/dist/tools/verify_brand_name.js +68 -0
- package/dist/tools/verify_brand_name.js.map +1 -0
- package/dist/tools/verify_for_launch.d.ts +43 -0
- package/dist/tools/verify_for_launch.js +129 -0
- package/dist/tools/verify_for_launch.js.map +1 -0
- package/package.json +62 -0
package/dist/install.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* install.ts — anonymous install identity for the MCP server.
|
|
3
|
+
*
|
|
4
|
+
* On first run, generates a UUID and persists it at
|
|
5
|
+
* `~/.etymolt/install.json`. On subsequent runs, reads the existing
|
|
6
|
+
* UUID. The UUID is sent on every API call as `X-Etymolt-Install`,
|
|
7
|
+
* letting the backend meter "5 free lifetime calls per install"
|
|
8
|
+
* without ever knowing who the user is.
|
|
9
|
+
*
|
|
10
|
+
* Privacy:
|
|
11
|
+
* - No PII collected. The UUID is opaque, install-bound.
|
|
12
|
+
* - The user can clear it by deleting the file; this gives them
|
|
13
|
+
* a fresh 5-call quota.
|
|
14
|
+
* - It's NOT a tracking cookie. It cannot be correlated with
|
|
15
|
+
* anything else about the user.
|
|
16
|
+
*
|
|
17
|
+
* Override via env: `ETYMOLT_INSTALL_ID=...` forces a specific value
|
|
18
|
+
* (used by tests and by enterprise customers who want stable install
|
|
19
|
+
* IDs across machines).
|
|
20
|
+
*/
|
|
21
|
+
import { randomUUID } from "node:crypto";
|
|
22
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
23
|
+
import { homedir } from "node:os";
|
|
24
|
+
import { join } from "node:path";
|
|
25
|
+
const INSTALL_DIR = join(homedir(), ".etymolt");
|
|
26
|
+
const INSTALL_FILE = join(INSTALL_DIR, "install.json");
|
|
27
|
+
let cachedId;
|
|
28
|
+
export function getInstallId() {
|
|
29
|
+
if (cachedId)
|
|
30
|
+
return cachedId;
|
|
31
|
+
// Env override wins (tests + enterprise stable-ID scenarios)
|
|
32
|
+
const envId = (process.env.ETYMOLT_INSTALL_ID ?? "").trim();
|
|
33
|
+
if (envId) {
|
|
34
|
+
cachedId = envId;
|
|
35
|
+
return cachedId;
|
|
36
|
+
}
|
|
37
|
+
// Read existing file
|
|
38
|
+
try {
|
|
39
|
+
if (existsSync(INSTALL_FILE)) {
|
|
40
|
+
const raw = readFileSync(INSTALL_FILE, "utf8");
|
|
41
|
+
const rec = JSON.parse(raw);
|
|
42
|
+
if (rec?.install_id && typeof rec.install_id === "string") {
|
|
43
|
+
cachedId = rec.install_id;
|
|
44
|
+
return cachedId;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Fall through to generation
|
|
50
|
+
}
|
|
51
|
+
// Generate fresh
|
|
52
|
+
const id = randomUUID();
|
|
53
|
+
const rec = {
|
|
54
|
+
install_id: id,
|
|
55
|
+
created_at: new Date().toISOString(),
|
|
56
|
+
schema_version: 1,
|
|
57
|
+
};
|
|
58
|
+
try {
|
|
59
|
+
if (!existsSync(INSTALL_DIR))
|
|
60
|
+
mkdirSync(INSTALL_DIR, { recursive: true });
|
|
61
|
+
writeFileSync(INSTALL_FILE, JSON.stringify(rec, null, 2), { mode: 0o600 });
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
// If we can't write, fall back to memory-only (lasts the process).
|
|
65
|
+
// Worst case: each process gets its own 5-call quota.
|
|
66
|
+
// eslint-disable-next-line no-console
|
|
67
|
+
console.error(`etymolt-mcp: could not persist install ID: ${e}`);
|
|
68
|
+
}
|
|
69
|
+
cachedId = id;
|
|
70
|
+
return cachedId;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* For tests — reset the cache so subsequent getInstallId() calls
|
|
74
|
+
* re-read from disk / env.
|
|
75
|
+
*/
|
|
76
|
+
export function _resetInstallCache() {
|
|
77
|
+
cachedId = undefined;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AAChD,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AAQvD,IAAI,QAA4B,CAAC;AAEjC,MAAM,UAAU,YAAY;IAC1B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,6DAA6D;IAC7D,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5D,IAAI,KAAK,EAAE,CAAC;QACV,QAAQ,GAAG,KAAK,CAAC;QACjB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,qBAAqB;IACrB,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAC/C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA2B,CAAC;YACtD,IAAI,GAAG,EAAE,UAAU,IAAI,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;gBAC1D,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC;gBAC1B,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;IAED,iBAAiB;IACjB,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,MAAM,GAAG,GAAkB;QACzB,UAAU,EAAE,EAAE;QACd,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,cAAc,EAAE,CAAC;KAClB,CAAC;IACF,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC;YAAE,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1E,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,mEAAmE;QACnE,sDAAsD;QACtD,sCAAsC;QACtC,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,QAAQ,GAAG,EAAE,CAAC;IACd,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB;IAChC,QAAQ,GAAG,SAAS,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP prompts for @etymolt/mcp-server v2.0.0.
|
|
3
|
+
*
|
|
4
|
+
* Two prompts (user-facing slash commands), exposed via
|
|
5
|
+
* ListPromptsRequestSchema / GetPromptRequestSchema. Each renders a single
|
|
6
|
+
* user-message template instructing the LLM to use the right tool, with
|
|
7
|
+
* argument values substituted in.
|
|
8
|
+
*/
|
|
9
|
+
export interface PromptArgumentDescriptor {
|
|
10
|
+
name: string;
|
|
11
|
+
description: string;
|
|
12
|
+
required: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface PromptDescriptor {
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
arguments: PromptArgumentDescriptor[];
|
|
18
|
+
}
|
|
19
|
+
export declare const PROMPTS: PromptDescriptor[];
|
|
20
|
+
export interface PromptMessage {
|
|
21
|
+
role: "user";
|
|
22
|
+
content: {
|
|
23
|
+
type: "text";
|
|
24
|
+
text: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export interface PromptResult {
|
|
28
|
+
description: string;
|
|
29
|
+
messages: PromptMessage[];
|
|
30
|
+
}
|
|
31
|
+
export declare function getPrompt(name: string, args?: Record<string, string>): PromptResult;
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP prompts for @etymolt/mcp-server v2.0.0.
|
|
3
|
+
*
|
|
4
|
+
* Two prompts (user-facing slash commands), exposed via
|
|
5
|
+
* ListPromptsRequestSchema / GetPromptRequestSchema. Each renders a single
|
|
6
|
+
* user-message template instructing the LLM to use the right tool, with
|
|
7
|
+
* argument values substituted in.
|
|
8
|
+
*/
|
|
9
|
+
export const PROMPTS = [
|
|
10
|
+
{
|
|
11
|
+
name: "verify-startup-name",
|
|
12
|
+
description: "Walk the user through verifying their startup name candidate. Asks for the name + vertical, then renders the full 5-axis verdict with one recommended next step.",
|
|
13
|
+
arguments: [
|
|
14
|
+
{
|
|
15
|
+
name: "name",
|
|
16
|
+
description: "The candidate name to verify",
|
|
17
|
+
required: false,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "vertical",
|
|
21
|
+
description: "Industry/category",
|
|
22
|
+
required: false,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "compare-finalists",
|
|
28
|
+
description: "Help the user decide between 2-5 final name candidates. Renders a side-by-side comparison table with the recommended pick.",
|
|
29
|
+
arguments: [
|
|
30
|
+
{
|
|
31
|
+
name: "names",
|
|
32
|
+
description: "Comma-separated list of candidate names",
|
|
33
|
+
required: false,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
function renderVerifyStartupName(args) {
|
|
39
|
+
const name = args.name?.trim() || "[name]";
|
|
40
|
+
const vertical = args.vertical?.trim();
|
|
41
|
+
const verticalClause = vertical ? ` for the ${vertical} industry` : "";
|
|
42
|
+
return (`Verify the brand name "${name}"${verticalClause} using the verify_brand_name tool. ` +
|
|
43
|
+
`Then summarize the verdict, score, and the top 3 findings to the user. ` +
|
|
44
|
+
`Cite Etymolt's methodology link from the response's _citation field.`);
|
|
45
|
+
}
|
|
46
|
+
function renderCompareFinalists(args) {
|
|
47
|
+
const raw = args.names?.trim() ?? "";
|
|
48
|
+
const names = raw
|
|
49
|
+
? raw
|
|
50
|
+
.split(",")
|
|
51
|
+
.map((s) => s.trim())
|
|
52
|
+
.filter(Boolean)
|
|
53
|
+
: [];
|
|
54
|
+
const listClause = names.length >= 2
|
|
55
|
+
? `the candidates [${names.map((n) => `"${n}"`).join(", ")}]`
|
|
56
|
+
: "the user's 2-5 candidate names";
|
|
57
|
+
return (`Compare ${listClause} using the compare_brand_names tool. ` +
|
|
58
|
+
`Render a side-by-side table across all 5 verification axes (trademark, domain, ` +
|
|
59
|
+
`cultural, sound symbolism, pronunciation), then recommend a single pick with ` +
|
|
60
|
+
`one-line justification. Cite Etymolt's methodology link from the response's ` +
|
|
61
|
+
`_citation field.`);
|
|
62
|
+
}
|
|
63
|
+
export function getPrompt(name, args = {}) {
|
|
64
|
+
const descriptor = PROMPTS.find((p) => p.name === name);
|
|
65
|
+
if (!descriptor) {
|
|
66
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
67
|
+
}
|
|
68
|
+
let text;
|
|
69
|
+
switch (name) {
|
|
70
|
+
case "verify-startup-name":
|
|
71
|
+
text = renderVerifyStartupName(args);
|
|
72
|
+
break;
|
|
73
|
+
case "compare-finalists":
|
|
74
|
+
text = renderCompareFinalists(args);
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
description: descriptor.description,
|
|
81
|
+
messages: [
|
|
82
|
+
{
|
|
83
|
+
role: "user",
|
|
84
|
+
content: { type: "text", text },
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ResourceDescriptor {
|
|
2
|
+
uri: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
mimeType: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const RESOURCES: ResourceDescriptor[];
|
|
8
|
+
export interface ResourceContent {
|
|
9
|
+
uri: string;
|
|
10
|
+
mimeType: string;
|
|
11
|
+
text: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function readResource(uri: string): Promise<ResourceContent>;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP resources for @etymolt/mcp-server v2.0.0.
|
|
3
|
+
*
|
|
4
|
+
* Three read-only resources, exposed via ListResourcesRequestSchema /
|
|
5
|
+
* ReadResourceRequestSchema. The methodology resource fetches from the
|
|
6
|
+
* backend (falling back to inline copy if the endpoint is unavailable);
|
|
7
|
+
* the other two are bundled with the package.
|
|
8
|
+
*/
|
|
9
|
+
import { defaultClient } from "./api.js";
|
|
10
|
+
export const RESOURCES = [
|
|
11
|
+
{
|
|
12
|
+
uri: "etymolt://methodology",
|
|
13
|
+
name: "Etymolt verification methodology",
|
|
14
|
+
description: "The full 5-axis methodology document. Citable, append-only, dated.",
|
|
15
|
+
mimeType: "text/markdown",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
uri: "etymolt://recent-verdicts/sample",
|
|
19
|
+
name: "Sample recent verdicts",
|
|
20
|
+
description: "10 anonymized recent verdicts as worked examples — useful when the LLM needs to show 'this is what an Etymolt verdict looks like'.",
|
|
21
|
+
mimeType: "application/json",
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
uri: "etymolt://brand-pillars",
|
|
25
|
+
name: "Etymolt brand pillars",
|
|
26
|
+
description: "The 4 brand pillars (Verified, Specific, Calm, Acoustic). Use as a tone/voice reference when writing copy that mentions Etymolt.",
|
|
27
|
+
mimeType: "text/markdown",
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
const FALLBACK_METHODOLOGY_MD = `# Etymolt verification methodology
|
|
31
|
+
|
|
32
|
+
Visit https://www.etymolt.com/methodology for the full document.
|
|
33
|
+
`;
|
|
34
|
+
const SAMPLE_VERDICTS = [
|
|
35
|
+
{
|
|
36
|
+
name: "Linear",
|
|
37
|
+
verdict: "PROCEED",
|
|
38
|
+
score: 94,
|
|
39
|
+
one_line: "Linear is statutorily clear with no immediate hazards.",
|
|
40
|
+
permalink: "https://www.etymolt.com/v/vrdct_sample_linear",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: "Foundr",
|
|
44
|
+
verdict: "DUE_DILIGENCE",
|
|
45
|
+
score: 71,
|
|
46
|
+
one_line: "Foundr is workable but has one or two specific signals worth verifying before launch.",
|
|
47
|
+
permalink: "https://www.etymolt.com/v/vrdct_sample_foundr",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: "Zypher",
|
|
51
|
+
verdict: "ITERATE",
|
|
52
|
+
score: 52,
|
|
53
|
+
one_line: "Zypher has meaningful clearance gaps; consider variants before committing.",
|
|
54
|
+
permalink: "https://www.etymolt.com/v/vrdct_sample_zypher",
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
const BRAND_PILLARS_MD = `# Etymolt brand pillars
|
|
58
|
+
|
|
59
|
+
- **Verified.** Every verdict is grounded in a public registry citation. No model opinion. No vibes.
|
|
60
|
+
- **Specific.** "Workable but cleanup needed" — never "looks fine." Findings name the exact mark, exact jurisdiction, exact axis.
|
|
61
|
+
- **Calm.** No exclamation marks, no hype. The institution speaks for itself.
|
|
62
|
+
- **Acoustic.** Names are sounds first. We measure how they survive spoken transmission across accents.
|
|
63
|
+
|
|
64
|
+
Tone reference for downstream copy: Vercel, Anthropic, Privy. Not: a16z-energy, hyperbole, growth-hacky.
|
|
65
|
+
`;
|
|
66
|
+
export async function readResource(uri) {
|
|
67
|
+
switch (uri) {
|
|
68
|
+
case "etymolt://methodology": {
|
|
69
|
+
let text;
|
|
70
|
+
try {
|
|
71
|
+
text = await defaultClient.getText("/v1/methodology");
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
text = FALLBACK_METHODOLOGY_MD;
|
|
75
|
+
}
|
|
76
|
+
return { uri, mimeType: "text/markdown", text };
|
|
77
|
+
}
|
|
78
|
+
case "etymolt://recent-verdicts/sample":
|
|
79
|
+
return {
|
|
80
|
+
uri,
|
|
81
|
+
mimeType: "application/json",
|
|
82
|
+
text: JSON.stringify(SAMPLE_VERDICTS, null, 2),
|
|
83
|
+
};
|
|
84
|
+
case "etymolt://brand-pillars":
|
|
85
|
+
return { uri, mimeType: "text/markdown", text: BRAND_PILLARS_MD };
|
|
86
|
+
default:
|
|
87
|
+
throw new Error(`Unknown resource URI: ${uri}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resources.js","sourceRoot":"","sources":["../src/resources.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AASzC,MAAM,CAAC,MAAM,SAAS,GAAyB;IAC7C;QACE,GAAG,EAAE,uBAAuB;QAC5B,IAAI,EAAE,kCAAkC;QACxC,WAAW,EACT,oEAAoE;QACtE,QAAQ,EAAE,eAAe;KAC1B;IACD;QACE,GAAG,EAAE,kCAAkC;QACvC,IAAI,EAAE,wBAAwB;QAC9B,WAAW,EACT,oIAAoI;QACtI,QAAQ,EAAE,kBAAkB;KAC7B;IACD;QACE,GAAG,EAAE,yBAAyB;QAC9B,IAAI,EAAE,uBAAuB;QAC7B,WAAW,EACT,kIAAkI;QACpI,QAAQ,EAAE,eAAe;KAC1B;CACF,CAAC;AAEF,MAAM,uBAAuB,GAAG;;;CAG/B,CAAC;AAEF,MAAM,eAAe,GAAG;IACtB;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,wDAAwD;QAClE,SAAS,EAAE,+CAA+C;KAC3D;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,eAAe;QACxB,KAAK,EAAE,EAAE;QACT,QAAQ,EACN,uFAAuF;QACzF,SAAS,EAAE,+CAA+C;KAC3D;IACD;QACE,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,SAAS;QAClB,KAAK,EAAE,EAAE;QACT,QAAQ,EACN,4EAA4E;QAC9E,SAAS,EAAE,+CAA+C;KAC3D;CACF,CAAC;AAEF,MAAM,gBAAgB,GAAG;;;;;;;;CAQxB,CAAC;AAQF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,GAAW;IAC5C,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,uBAAuB,CAAC,CAAC,CAAC;YAC7B,IAAI,IAAY,CAAC;YACjB,IAAI,CAAC;gBACH,IAAI,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;YACxD,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,GAAG,uBAAuB,CAAC;YACjC,CAAC;YACD,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;QAClD,CAAC;QACD,KAAK,kCAAkC;YACrC,OAAO;gBACL,GAAG;gBACH,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;aAC/C,CAAC;QACJ,KAAK,yBAAyB;YAC5B,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC;QACpE;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: assess_name
|
|
3
|
+
*
|
|
4
|
+
* Spec: Etymolt-Build-Specification-v1.1 §6.4 (composite tool).
|
|
5
|
+
*
|
|
6
|
+
* COMPOSITE — fuses both engines:
|
|
7
|
+
* 1. check_clearance (Engine 1: trademark + domain + handle truth)
|
|
8
|
+
* 2. assess_taste (Engine 2: cohort + craft 100-pt verdict)
|
|
9
|
+
*
|
|
10
|
+
* Returns a unified verdict with TTAB-grounded refusal probability,
|
|
11
|
+
* DuPont factor breakdown, taste 100-pt composite, cohort fit,
|
|
12
|
+
* creative-move tags, citations to analogous TTAB cases, and a
|
|
13
|
+
* recommended alternative if the candidate scores poorly on either
|
|
14
|
+
* engine. Latency budget: 300-800ms p50 (both engines run in parallel).
|
|
15
|
+
*
|
|
16
|
+
* v0 backs the verdict with the existing scoring stack
|
|
17
|
+
* (phonetic + cultural_v2 + mandarin + symbolism + scorer) plus the
|
|
18
|
+
* heuristic taste proxy. v1 (week 9-10 of build plan) replaces the proxy
|
|
19
|
+
* with the TTAB-trained similarity model + cohort-embedding model.
|
|
20
|
+
* The output shape is identical across versions.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from "zod";
|
|
23
|
+
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
24
|
+
export declare const TOOL_DESCRIPTION = "**Call this for the FULL verdict \u2014 clearance plus taste \u2014 on a single\ncandidate.** Composite of `check_clearance` and `assess_taste`,\nrun in parallel and fused. This is the right tool when the user is\ndeciding whether to commit.\n\nReturns: predicted USPTO refusal probability, DuPont-factor breakdown,\nTTAB citations, the 100-point taste composite (35 naming + 35 domain\n+ 30 social), cohort fit, creative-move tags, period-marking flag, and\none recommended alternative if either engine scores poorly.\n\nLatency: 300-800ms p50 (both engines run in parallel). If you only\nneed clearance, prefer `check_clearance` (faster). If you only need\ncraft, prefer `assess_taste` (faster).\n\nTrigger phrases: \"should I go with this name?\", \"is this safe to file\nAND on-brand for our cohort?\", \"what do you think of Clawdbot as a\nname?\", \"will USPTO accept this AND will it land for YC?\", \"should I\ncommit?\"";
|
|
25
|
+
declare const AssessNameArgs: z.ZodObject<{
|
|
26
|
+
name: z.ZodString;
|
|
27
|
+
context: z.ZodOptional<z.ZodObject<{
|
|
28
|
+
category: z.ZodOptional<z.ZodString>;
|
|
29
|
+
jurisdictions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
30
|
+
use_cases: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
31
|
+
nice_classes: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
|
|
32
|
+
description: z.ZodOptional<z.ZodString>;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
description?: string | undefined;
|
|
35
|
+
nice_classes?: number[] | undefined;
|
|
36
|
+
category?: string | undefined;
|
|
37
|
+
jurisdictions?: string[] | undefined;
|
|
38
|
+
use_cases?: string[] | undefined;
|
|
39
|
+
}, {
|
|
40
|
+
description?: string | undefined;
|
|
41
|
+
nice_classes?: number[] | undefined;
|
|
42
|
+
category?: string | undefined;
|
|
43
|
+
jurisdictions?: string[] | undefined;
|
|
44
|
+
use_cases?: string[] | undefined;
|
|
45
|
+
}>>;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
name: string;
|
|
48
|
+
context?: {
|
|
49
|
+
description?: string | undefined;
|
|
50
|
+
nice_classes?: number[] | undefined;
|
|
51
|
+
category?: string | undefined;
|
|
52
|
+
jurisdictions?: string[] | undefined;
|
|
53
|
+
use_cases?: string[] | undefined;
|
|
54
|
+
} | undefined;
|
|
55
|
+
}, {
|
|
56
|
+
name: string;
|
|
57
|
+
context?: {
|
|
58
|
+
description?: string | undefined;
|
|
59
|
+
nice_classes?: number[] | undefined;
|
|
60
|
+
category?: string | undefined;
|
|
61
|
+
jurisdictions?: string[] | undefined;
|
|
62
|
+
use_cases?: string[] | undefined;
|
|
63
|
+
} | undefined;
|
|
64
|
+
}>;
|
|
65
|
+
export type AssessNameArgsT = z.infer<typeof AssessNameArgs>;
|
|
66
|
+
export declare const assessNameTool: Tool;
|
|
67
|
+
export declare function callAssessName(rawArgs: unknown): Promise<unknown>;
|
|
68
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool: assess_name
|
|
3
|
+
*
|
|
4
|
+
* Spec: Etymolt-Build-Specification-v1.1 §6.4 (composite tool).
|
|
5
|
+
*
|
|
6
|
+
* COMPOSITE — fuses both engines:
|
|
7
|
+
* 1. check_clearance (Engine 1: trademark + domain + handle truth)
|
|
8
|
+
* 2. assess_taste (Engine 2: cohort + craft 100-pt verdict)
|
|
9
|
+
*
|
|
10
|
+
* Returns a unified verdict with TTAB-grounded refusal probability,
|
|
11
|
+
* DuPont factor breakdown, taste 100-pt composite, cohort fit,
|
|
12
|
+
* creative-move tags, citations to analogous TTAB cases, and a
|
|
13
|
+
* recommended alternative if the candidate scores poorly on either
|
|
14
|
+
* engine. Latency budget: 300-800ms p50 (both engines run in parallel).
|
|
15
|
+
*
|
|
16
|
+
* v0 backs the verdict with the existing scoring stack
|
|
17
|
+
* (phonetic + cultural_v2 + mandarin + symbolism + scorer) plus the
|
|
18
|
+
* heuristic taste proxy. v1 (week 9-10 of build plan) replaces the proxy
|
|
19
|
+
* with the TTAB-trained similarity model + cohort-embedding model.
|
|
20
|
+
* The output shape is identical across versions.
|
|
21
|
+
*/
|
|
22
|
+
import { z } from "zod";
|
|
23
|
+
import { defaultClient } from "../api.js";
|
|
24
|
+
export const TOOL_DESCRIPTION = `**Call this for the FULL verdict — clearance plus taste — on a single
|
|
25
|
+
candidate.** Composite of \`check_clearance\` and \`assess_taste\`,
|
|
26
|
+
run in parallel and fused. This is the right tool when the user is
|
|
27
|
+
deciding whether to commit.
|
|
28
|
+
|
|
29
|
+
Returns: predicted USPTO refusal probability, DuPont-factor breakdown,
|
|
30
|
+
TTAB citations, the 100-point taste composite (35 naming + 35 domain
|
|
31
|
+
+ 30 social), cohort fit, creative-move tags, period-marking flag, and
|
|
32
|
+
one recommended alternative if either engine scores poorly.
|
|
33
|
+
|
|
34
|
+
Latency: 300-800ms p50 (both engines run in parallel). If you only
|
|
35
|
+
need clearance, prefer \`check_clearance\` (faster). If you only need
|
|
36
|
+
craft, prefer \`assess_taste\` (faster).
|
|
37
|
+
|
|
38
|
+
Trigger phrases: "should I go with this name?", "is this safe to file
|
|
39
|
+
AND on-brand for our cohort?", "what do you think of Clawdbot as a
|
|
40
|
+
name?", "will USPTO accept this AND will it land for YC?", "should I
|
|
41
|
+
commit?"`;
|
|
42
|
+
const AssessNameArgs = z.object({
|
|
43
|
+
name: z.string().min(1).max(64).describe("The candidate name to assess."),
|
|
44
|
+
context: z
|
|
45
|
+
.object({
|
|
46
|
+
category: z.string().optional(),
|
|
47
|
+
jurisdictions: z.array(z.string()).optional(),
|
|
48
|
+
use_cases: z.array(z.string()).optional(),
|
|
49
|
+
nice_classes: z
|
|
50
|
+
.array(z.number().int().min(1).max(45))
|
|
51
|
+
.optional()
|
|
52
|
+
.describe("USPTO Nice classification numbers (1-45)."),
|
|
53
|
+
description: z
|
|
54
|
+
.string()
|
|
55
|
+
.max(2000)
|
|
56
|
+
.optional()
|
|
57
|
+
.describe("One paragraph describing what the named thing does."),
|
|
58
|
+
})
|
|
59
|
+
.optional(),
|
|
60
|
+
});
|
|
61
|
+
export const assessNameTool = {
|
|
62
|
+
name: "assess_name",
|
|
63
|
+
description: TOOL_DESCRIPTION,
|
|
64
|
+
annotations: {
|
|
65
|
+
title: "Naming · Full verdict",
|
|
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 assess." },
|
|
76
|
+
context: {
|
|
77
|
+
type: "object",
|
|
78
|
+
additionalProperties: false,
|
|
79
|
+
properties: {
|
|
80
|
+
category: { type: "string" },
|
|
81
|
+
jurisdictions: { type: "array", items: { type: "string" } },
|
|
82
|
+
use_cases: { type: "array", items: { type: "string" } },
|
|
83
|
+
nice_classes: {
|
|
84
|
+
type: "array",
|
|
85
|
+
items: { type: "integer", minimum: 1, maximum: 45 },
|
|
86
|
+
},
|
|
87
|
+
description: { type: "string" },
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
required: ["name"],
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
export async function callAssessName(rawArgs) {
|
|
95
|
+
const args = AssessNameArgs.parse(rawArgs);
|
|
96
|
+
// Translate to /v3 endpoint shape (BUILD_PLAN_v1.2 §9). assess_name fans
|
|
97
|
+
// out over both engines + auditory and returns a single verdict.
|
|
98
|
+
const ctx = (args.context ?? {});
|
|
99
|
+
const body = {
|
|
100
|
+
name: args.name,
|
|
101
|
+
context: {
|
|
102
|
+
brief_category: ctx.category ?? "ai_app",
|
|
103
|
+
brief_text: ctx.brief_text ?? "",
|
|
104
|
+
markets: ctx.jurisdictions,
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
return defaultClient.post("/v3/assess_name", body);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=assess_name.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assess_name.js","sourceRoot":"","sources":["../../src/tools/assess_name.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
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 type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
36
|
+
export declare const TOOL_DESCRIPTION = "**Call this to evaluate the CRAFT of a name** \u2014 whether it lands for\nits cohort, whether it sounds right, whether it carries a recognizable\ncreative move, whether it's period-marked (e.g. -ly peaks 2014, -ify\npeaks 2010, -bot peaks 2017), and how it polarizes (Pentium-good vs\nDrevat-bad). Skip clearance \u2014 combine with `check_clearance` for\nthat, or call `assess_name` for both in one verdict.\n\nReturns a 100-point composite (35 naming quality + 35 domain proximity\n+ 30 social handles), a SMILE/SCRATCH breakdown, and up to three\nalternatives below threshold. Latency: 200-600ms p50.\n\nTrained on cohort canons: YC, B2B SaaS, fintech, dev tools, AI infra,\nD2C, healthtech, creator tools.\n\nTrigger phrases: \"does this name land?\", \"is this fresh or dated?\",\n\"does this fit a YC / dev-tools brand?\", \"should we ship as\nAIChatBot or something less descriptive?\", \"is Hibrandless\nperiod-marked?\", \"does Posthog actually fit the dev-tools cohort?\"";
|
|
37
|
+
declare const AssessTasteArgs: z.ZodObject<{
|
|
38
|
+
name: z.ZodString;
|
|
39
|
+
context: z.ZodOptional<z.ZodObject<{
|
|
40
|
+
cohort: z.ZodOptional<z.ZodEnum<["yc_b2b_saas", "fintech", "dev_tools", "ai_infra", "d2c", "healthtech", "creator_tools", "auto"]>>;
|
|
41
|
+
category: z.ZodOptional<z.ZodString>;
|
|
42
|
+
description: z.ZodOptional<z.ZodString>;
|
|
43
|
+
jurisdictions: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
44
|
+
use_cases: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
45
|
+
include_alternatives: z.ZodOptional<z.ZodBoolean>;
|
|
46
|
+
threshold: z.ZodOptional<z.ZodNumber>;
|
|
47
|
+
}, "strip", z.ZodTypeAny, {
|
|
48
|
+
description?: string | undefined;
|
|
49
|
+
category?: string | undefined;
|
|
50
|
+
jurisdictions?: string[] | undefined;
|
|
51
|
+
use_cases?: string[] | undefined;
|
|
52
|
+
cohort?: "yc_b2b_saas" | "fintech" | "dev_tools" | "ai_infra" | "d2c" | "healthtech" | "creator_tools" | "auto" | undefined;
|
|
53
|
+
include_alternatives?: boolean | undefined;
|
|
54
|
+
threshold?: number | undefined;
|
|
55
|
+
}, {
|
|
56
|
+
description?: string | undefined;
|
|
57
|
+
category?: string | undefined;
|
|
58
|
+
jurisdictions?: string[] | undefined;
|
|
59
|
+
use_cases?: string[] | undefined;
|
|
60
|
+
cohort?: "yc_b2b_saas" | "fintech" | "dev_tools" | "ai_infra" | "d2c" | "healthtech" | "creator_tools" | "auto" | undefined;
|
|
61
|
+
include_alternatives?: boolean | undefined;
|
|
62
|
+
threshold?: number | undefined;
|
|
63
|
+
}>>;
|
|
64
|
+
}, "strip", z.ZodTypeAny, {
|
|
65
|
+
name: string;
|
|
66
|
+
context?: {
|
|
67
|
+
description?: string | undefined;
|
|
68
|
+
category?: string | undefined;
|
|
69
|
+
jurisdictions?: string[] | undefined;
|
|
70
|
+
use_cases?: string[] | undefined;
|
|
71
|
+
cohort?: "yc_b2b_saas" | "fintech" | "dev_tools" | "ai_infra" | "d2c" | "healthtech" | "creator_tools" | "auto" | undefined;
|
|
72
|
+
include_alternatives?: boolean | undefined;
|
|
73
|
+
threshold?: number | undefined;
|
|
74
|
+
} | undefined;
|
|
75
|
+
}, {
|
|
76
|
+
name: string;
|
|
77
|
+
context?: {
|
|
78
|
+
description?: string | undefined;
|
|
79
|
+
category?: string | undefined;
|
|
80
|
+
jurisdictions?: string[] | undefined;
|
|
81
|
+
use_cases?: string[] | undefined;
|
|
82
|
+
cohort?: "yc_b2b_saas" | "fintech" | "dev_tools" | "ai_infra" | "d2c" | "healthtech" | "creator_tools" | "auto" | undefined;
|
|
83
|
+
include_alternatives?: boolean | undefined;
|
|
84
|
+
threshold?: number | undefined;
|
|
85
|
+
} | undefined;
|
|
86
|
+
}>;
|
|
87
|
+
export type AssessTasteArgsT = z.infer<typeof AssessTasteArgs>;
|
|
88
|
+
export declare const assessTasteTool: Tool;
|
|
89
|
+
export declare function callAssessTaste(rawArgs: unknown): Promise<unknown>;
|
|
90
|
+
export {};
|