uniqueness-mcp 0.2.0 → 0.3.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/index.mjs +40 -9
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ import { z } from "zod";
|
|
|
14
14
|
const BASE = process.env.UNIQUENESS_API_URL || "https://uniquenessengine.com";
|
|
15
15
|
const KEY = process.env.UNIQUENESS_API_KEY || "";
|
|
16
16
|
|
|
17
|
-
const server = new McpServer({ name: "uniqueness", version: "0.
|
|
17
|
+
const server = new McpServer({ name: "uniqueness", version: "0.3.0" });
|
|
18
18
|
|
|
19
19
|
server.tool(
|
|
20
20
|
"get_connection_brief",
|
|
@@ -44,19 +44,50 @@ server.tool(
|
|
|
44
44
|
if (args.name) body.name = args.name;
|
|
45
45
|
if (args.company) body.company = args.company;
|
|
46
46
|
if (args.email) body.email = args.email;
|
|
47
|
-
if (args.deep) body.mode = "deep";
|
|
47
|
+
if (args.deep) { body.tier = "deep"; body.mode = "deep"; }
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
// Async enrich+poll (mirrors cli/uniqueness.mjs `brief`). The sync /api/brief
|
|
50
|
+
// path returns {} to the client past the ~124s delivery cliff on fresh
|
|
51
|
+
// (uncached) profiles; /api/enrich submits a job we can poll to completion.
|
|
52
|
+
// A cache hit / immediate brief comes back inline on the submit.
|
|
53
|
+
const auth = { "content-type": "application/json", authorization: `Bearer ${KEY}` };
|
|
54
|
+
const sub = await fetch(`${BASE}/api/enrich`, {
|
|
50
55
|
method: "POST",
|
|
51
|
-
headers:
|
|
56
|
+
headers: auth,
|
|
52
57
|
body: JSON.stringify(body),
|
|
53
58
|
});
|
|
54
|
-
const
|
|
55
|
-
if (
|
|
56
|
-
if (
|
|
57
|
-
|
|
59
|
+
const subJson = await sub.json().catch(() => ({}));
|
|
60
|
+
if (sub.status === 401) return { isError: true, content: [{ type: "text", text: "401 unauthorized — invalid API key." }] };
|
|
61
|
+
if (sub.status === 402) return { isError: true, content: [{ type: "text", text: "Out of credits. " + (subJson.message || "") }] };
|
|
62
|
+
|
|
63
|
+
// Fast path: cache hit / immediate brief.
|
|
64
|
+
let brief = subJson.brief || null;
|
|
65
|
+
let jobId = subJson.job_id || null;
|
|
66
|
+
if (!brief) {
|
|
67
|
+
if (!jobId) {
|
|
68
|
+
return { isError: true, content: [{ type: "text", text: `enrich failed (${sub.status}): ${subJson.error || subJson.message || ""}` }] };
|
|
69
|
+
}
|
|
70
|
+
// Poll GET /api/jobs/:id every 3s until a terminal state or the deadline.
|
|
71
|
+
// Briefs run ~45-180s, so give it up to ~210s before handing back the job_id.
|
|
72
|
+
const deadline = Date.now() + 210000;
|
|
73
|
+
while (Date.now() < deadline && !brief) {
|
|
74
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
75
|
+
const pr = await fetch(`${BASE}/api/jobs/${jobId}`, { headers: { authorization: `Bearer ${KEY}` } });
|
|
76
|
+
const pj = await pr.json().catch(() => ({}));
|
|
77
|
+
const st = pj.status;
|
|
78
|
+
if (st === "done") brief = pj.result;
|
|
79
|
+
else if (st === "refused") brief = pj.result || { status: "needs_review", note: "Identity could not be confidently resolved." };
|
|
80
|
+
else if (st === "failed") return { isError: true, content: [{ type: "text", text: `job failed: ${pj.error || "unknown"}` }] };
|
|
81
|
+
}
|
|
82
|
+
if (!brief) {
|
|
83
|
+
// Never return {} — hand back the job_id so the caller can re-run to keep polling.
|
|
84
|
+
return {
|
|
85
|
+
content: [{ type: "text", text: `Still processing (job ${jobId}). The brief is taking longer than usual — re-run get_connection_brief with the same inputs to keep polling.` }],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
}
|
|
58
89
|
|
|
59
|
-
return { content: [{ type: "text", text: JSON.stringify(
|
|
90
|
+
return { content: [{ type: "text", text: JSON.stringify(brief, null, 2) }] };
|
|
60
91
|
}
|
|
61
92
|
);
|
|
62
93
|
|