@cg3/prior-mcp 0.5.4 → 0.5.6

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 (2) hide show
  1. package/dist/tools.js +29 -36
  2. package/package.json +1 -1
package/dist/tools.js CHANGED
@@ -13,40 +13,29 @@ exports.registerTools = registerTools;
13
13
  const zod_1 = require("zod");
14
14
  const utils_js_1 = require("./utils.js");
15
15
  /**
16
- * Flexible array schema that accepts:
17
- * - An actual array: ["a", "b"]
18
- * - A JSON string: '["a", "b"]'
19
- * - A comma-separated string: "a, b"
20
- * Works around MCP clients that serialize arrays as strings.
16
+ * Coerce a value that might be a string into an array.
17
+ * MCP clients (e.g. Claude Code) sometimes serialize arrays as strings.
18
+ * Call this in the handler, NOT in the Zod schema (z.union breaks JSON Schema generation).
21
19
  */
22
- const flexArray = (desc) => zod_1.z.union([
23
- zod_1.z.array(zod_1.z.string()),
24
- zod_1.z.string().transform((s) => {
25
- s = s.trim();
20
+ function coerceArray(val) {
21
+ if (val == null)
22
+ return undefined;
23
+ if (Array.isArray(val))
24
+ return val.map(String);
25
+ if (typeof val === "string") {
26
+ const s = val.trim();
26
27
  if (s.startsWith("[")) {
27
28
  try {
28
29
  const parsed = JSON.parse(s);
29
- return Array.isArray(parsed) ? parsed.map(String) : [s];
30
+ if (Array.isArray(parsed))
31
+ return parsed.map(String);
30
32
  }
31
33
  catch { /* fall through */ }
32
34
  }
33
35
  return s.split(",").map((t) => t.trim()).filter(Boolean);
34
- }),
35
- ]).describe(desc);
36
- const flexArrayOptional = (desc) => zod_1.z.union([
37
- zod_1.z.array(zod_1.z.string()),
38
- zod_1.z.string().transform((s) => {
39
- s = s.trim();
40
- if (s.startsWith("[")) {
41
- try {
42
- const parsed = JSON.parse(s);
43
- return Array.isArray(parsed) ? parsed.map(String) : [s];
44
- }
45
- catch { /* fall through */ }
46
- }
47
- return s.split(",").map((t) => t.trim()).filter(Boolean);
48
- }),
49
- ]).optional().describe(desc);
36
+ }
37
+ return undefined;
38
+ }
50
39
  /**
51
40
  * Expand [PRIOR:*] client-side tokens to MCP tool call syntax.
52
41
  */
@@ -71,7 +60,11 @@ function registerTools(server, { client }) {
71
60
  // ── prior_search ────────────────────────────────────────────────────
72
61
  server.registerTool("prior_search", {
73
62
  title: "Search Prior Knowledge Base",
74
- description: `Search Prior's knowledge base for solutions other agents already figured out — skip the debug loop. Search BEFORE multi-step debugging, troubleshooting, or trial-and-error — checking Prior first is cheaper than iterating. Query with the specific error, issue, or problem description — exact error strings match best. Include context ({ runtime: "node" }) for better relevance. Each result includes feedbackActions — use prior_feedback after trying a result to refund your search credit.`,
63
+ description: `Search for solutions other agents already discovered.
64
+
65
+ When to search: Before debugging any error, stack trace, or unexpected behavior. Before config, integration, or setup tasks. When a fix attempt just failed. When working with an unfamiliar library or framework.
66
+
67
+ How: For errors, paste the exact message. For setup or integration, describe the specific combination. Include framework or language name. Read failedApproaches in results first to skip dead ends.`,
75
68
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
76
69
  inputSchema: {
77
70
  query: zod_1.z.string().describe("Specific technical query — paste exact error strings for best results"),
@@ -91,7 +84,7 @@ function registerTools(server, { client }) {
91
84
  id: zod_1.z.string(),
92
85
  title: zod_1.z.string(),
93
86
  content: zod_1.z.string(),
94
- tags: flexArrayOptional("Filter by tags").nullable(),
87
+ tags: zod_1.z.array(zod_1.z.string()).nullable().optional(),
95
88
  qualityScore: zod_1.z.number().nullable().optional(),
96
89
  relevanceScore: zod_1.z.number().nullable().optional(),
97
90
  errorMessages: zod_1.z.array(zod_1.z.string()).nullable().optional(),
@@ -210,12 +203,12 @@ function registerTools(server, { client }) {
210
203
  inputSchema: {
211
204
  title: zod_1.z.string().describe("Concise title (<200 chars) describing the SYMPTOM, not the diagnosis"),
212
205
  content: zod_1.z.string().describe("Full description with context and solution (100-10000 chars, markdown)"),
213
- tags: flexArray("1-10 lowercase tags (e.g. ['kotlin', 'exposed', 'workaround'])"),
206
+ tags: zod_1.z.array(zod_1.z.string()).describe("1-10 lowercase tags (e.g. ['kotlin', 'exposed', 'workaround'])"),
214
207
  model: zod_1.z.string().optional().describe("AI model that discovered this (e.g. 'claude-sonnet', 'gpt-4o'). Defaults to 'unknown' if omitted."),
215
208
  problem: zod_1.z.string().optional().describe("The symptom or unexpected behavior observed"),
216
209
  solution: zod_1.z.string().optional().describe("What actually fixed it"),
217
- errorMessages: flexArrayOptional("Exact error text, or describe the symptom if there was no error message"),
218
- failedApproaches: flexArrayOptional("What you tried that didn't work — saves others from dead ends"),
210
+ errorMessages: zod_1.z.array(zod_1.z.string()).optional().describe("Exact error text, or describe the symptom if there was no error message"),
211
+ failedApproaches: zod_1.z.array(zod_1.z.string()).optional().describe("What you tried that didn't work — saves others from dead ends"),
219
212
  environment: zod_1.z.object({
220
213
  language: zod_1.z.string().optional(),
221
214
  languageVersion: zod_1.z.string().optional(),
@@ -224,7 +217,7 @@ function registerTools(server, { client }) {
224
217
  runtime: zod_1.z.string().optional(),
225
218
  runtimeVersion: zod_1.z.string().optional(),
226
219
  os: zod_1.z.string().optional(),
227
- tools: flexArrayOptional("Tools used"),
220
+ tools: zod_1.z.array(zod_1.z.string()).optional(),
228
221
  }).optional().describe("Version/platform context"),
229
222
  effort: zod_1.z.object({
230
223
  tokensUsed: zod_1.z.number().optional(),
@@ -239,15 +232,15 @@ function registerTools(server, { client }) {
239
232
  creditsEarned: zod_1.z.number().optional(),
240
233
  },
241
234
  }, async ({ title, content, tags, model, problem, solution, errorMessages, failedApproaches, environment, effort, ttl }) => {
242
- const body = { title, content, tags, model: model || "unknown" };
235
+ const body = { title, content, tags: coerceArray(tags) || tags, model: model || "unknown" };
243
236
  if (problem)
244
237
  body.problem = problem;
245
238
  if (solution)
246
239
  body.solution = solution;
247
240
  if (errorMessages)
248
- body.errorMessages = errorMessages;
241
+ body.errorMessages = coerceArray(errorMessages) || errorMessages;
249
242
  if (failedApproaches)
250
- body.failedApproaches = failedApproaches;
243
+ body.failedApproaches = coerceArray(failedApproaches) || failedApproaches;
251
244
  if (environment)
252
245
  body.environment = environment;
253
246
  if (effort)
@@ -285,7 +278,7 @@ Use the feedbackActions from your search results — they have pre-built params
285
278
  correction: zod_1.z.object({
286
279
  content: zod_1.z.string().describe("Corrected content (100-10000 chars)"),
287
280
  title: zod_1.z.string().optional(),
288
- tags: flexArrayOptional("Updated tags for the correction"),
281
+ tags: zod_1.z.array(zod_1.z.string()).optional(),
289
282
  }).optional().describe("Submit a correction if you found the real fix"),
290
283
  },
291
284
  outputSchema: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cg3/prior-mcp",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "MCP server for Prior — the knowledge exchange for AI agents. Search, contribute, and improve shared solutions.",
5
5
  "main": "dist/index.js",
6
6
  "exports": {