@monadeo.com/grimoire-mcp 0.2.0 → 0.2.1

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/dist/index.js CHANGED
@@ -11,29 +11,6 @@ import { ApiError } from "@monadeo.com/grimoire-core";
11
11
  // src/tools.ts
12
12
  import { z } from "zod";
13
13
  import { GrimoireClient, resolveDefaultSources, loadGlobalConfig } from "@monadeo.com/grimoire-core";
14
- var ARG_ALIASES = {
15
- question: "query",
16
- userQuery: "query",
17
- q: "query",
18
- chunkId: "chunk_id",
19
- chunkID: "chunk_id",
20
- documentId: "chunk_id",
21
- sourceId: "source",
22
- library: "source"
23
- };
24
- function rewriteArgs(args, schemaKeys) {
25
- const declared = new Set(schemaKeys);
26
- const out = {};
27
- for (const [k, v] of Object.entries(args)) {
28
- if (declared.has(k) || !(k in ARG_ALIASES)) out[k] = v;
29
- }
30
- for (const [k, v] of Object.entries(args)) {
31
- if (declared.has(k)) continue;
32
- const target = ARG_ALIASES[k];
33
- if (target !== void 0) out[target] ??= v;
34
- }
35
- return out;
36
- }
37
14
  var client = new GrimoireClient();
38
15
  function sourcesFromArg(arg) {
39
16
  if (Array.isArray(arg)) {
@@ -74,7 +51,7 @@ ${r.text}`
74
51
  {
75
52
  name: "fetch_document",
76
53
  description: "Expand context around a search hit by chunk id (neighbors in the same section).",
77
- schema: { chunk_id: z.string(), window: z.number().optional() },
54
+ schema: { chunk_id: z.string(), window: z.number().int().min(0).max(5).optional() },
78
55
  async handler(args) {
79
56
  const res = await client.getContext(String(args.chunk_id), args.window ?? 2);
80
57
  return JSON.stringify(res.chunks ?? [], null, 2);
@@ -125,7 +102,7 @@ function buildServer() {
125
102
  { description: tool.description, inputSchema: tool.schema },
126
103
  async (rawArgs) => {
127
104
  try {
128
- const text = await tool.handler(rewriteArgs(rawArgs, Object.keys(tool.schema)));
105
+ const text = await tool.handler(rawArgs);
129
106
  return { content: [{ type: "text", text }] };
130
107
  } catch (err) {
131
108
  const message = err instanceof ApiError ? err.status === 401 ? "Not authenticated \u2014 the user should run `grimoire login`." : err.status === 429 ? "Quota or rate limit reached \u2014 inform the user; do not retry." : err.status === 404 ? `Not found: ${JSON.stringify(err.body)}` : `Grimoire error: ${err.code}` : `Error: ${err.message}`;
@@ -148,8 +125,12 @@ function runHttp(port) {
148
125
  enableDnsRebindingProtection: true,
149
126
  allowedHosts: ["127.0.0.1", `127.0.0.1:${port}`, "localhost", `localhost:${port}`]
150
127
  });
151
- res.on("close", () => void transport.close());
152
- await buildServer().connect(transport);
128
+ const server = buildServer();
129
+ res.on("close", () => {
130
+ void transport.close();
131
+ void server.close();
132
+ });
133
+ await server.connect(transport);
153
134
  await transport.handleRequest(req, res, req.body);
154
135
  });
155
136
  app.get("/mcp", (_req, res) => res.status(405).end());
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/tools.ts"],
4
- "sourcesContent": ["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport express from \"express\";\nimport { ApiError } from \"@monadeo.com/grimoire-core\";\nimport { TOOLS, rewriteArgs } from \"./tools.js\";\n\nfunction buildServer(): McpServer {\n const server = new McpServer(\n { name: \"grimoire\", version: \"0.1.0\" },\n {\n instructions:\n \"Use grimoire for any question about a library, framework, or tool \u2014 even when you think you know the answer, to get version-correct docs. Not for refactoring, business logic, or code review.\",\n },\n );\n\n for (const tool of TOOLS) {\n server.registerTool(\n tool.name,\n { description: tool.description, inputSchema: tool.schema },\n async (rawArgs: Record<string, unknown>) => {\n try {\n const text = await tool.handler(rewriteArgs(rawArgs, Object.keys(tool.schema)));\n return { content: [{ type: \"text\" as const, text }] };\n } catch (err) {\n const message =\n err instanceof ApiError\n ? err.status === 401\n ? \"Not authenticated \u2014 the user should run `grimoire login`.\"\n : err.status === 429\n ? \"Quota or rate limit reached \u2014 inform the user; do not retry.\"\n : err.status === 404\n ? `Not found: ${JSON.stringify(err.body)}`\n : `Grimoire error: ${err.code}`\n : `Error: ${(err as Error).message}`;\n return { content: [{ type: \"text\" as const, text: message }], isError: true };\n }\n },\n );\n }\n return server;\n}\n\nasync function runStdio(): Promise<void> {\n await buildServer().connect(new StdioServerTransport());\n}\n\nfunction runHttp(port: number): void {\n const app = express();\n app.use(express.json());\n // Fresh server + transport per request; session lifecycle owned by the client.\n app.post(\"/mcp\", async (req, res) => {\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableDnsRebindingProtection: true,\n allowedHosts: [\"127.0.0.1\", `127.0.0.1:${port}`, \"localhost\", `localhost:${port}`],\n });\n res.on(\"close\", () => void transport.close());\n await buildServer().connect(transport);\n await transport.handleRequest(req, res, req.body);\n });\n app.get(\"/mcp\", (_req, res) => res.status(405).end()); // no server-initiated SSE\n app.listen(port, \"127.0.0.1\");\n}\n\nif (process.argv.includes(\"--http\")) {\n runHttp(Number(process.env.PORT ?? 8080));\n} else {\n void runStdio();\n}\n", "import { z } from \"zod\";\nimport { GrimoireClient, resolveDefaultSources, loadGlobalConfig } from \"@monadeo.com/grimoire-core\";\n\n// Hallucinated-argument rewriting before schema validation \u2014 cheap, model-agnostic\n// robustness (learned from the incumbent). Maps common LLM variants to our names.\nconst ARG_ALIASES: Record<string, string> = {\n question: \"query\",\n userQuery: \"query\",\n q: \"query\",\n chunkId: \"chunk_id\",\n chunkID: \"chunk_id\",\n documentId: \"chunk_id\",\n sourceId: \"source\",\n library: \"source\",\n};\n\n// A key that the current tool declares is never an alias (list_sources takes `q`\n// literally), and an alias only fills its target when the target is absent.\nexport function rewriteArgs(\n args: Record<string, unknown>,\n schemaKeys: readonly string[],\n): Record<string, unknown> {\n const declared = new Set(schemaKeys);\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(args)) {\n if (declared.has(k) || !(k in ARG_ALIASES)) out[k] = v;\n }\n for (const [k, v] of Object.entries(args)) {\n if (declared.has(k)) continue;\n const target = ARG_ALIASES[k];\n if (target !== undefined) out[target] ??= v;\n }\n return out;\n}\n\nconst client = new GrimoireClient();\n\nfunction sourcesFromArg(arg: unknown): { source: string; version?: string }[] {\n if (Array.isArray(arg)) {\n return arg.map((s) =>\n typeof s === \"string\"\n ? { source: s.split(\"@\")[0], version: s.split(\"@\")[1] }\n : (s as { source: string; version?: string }),\n );\n }\n return resolveDefaultSources();\n}\n\nexport interface ToolDef {\n name: string;\n description: string;\n schema: z.ZodRawShape;\n handler: (args: Record<string, unknown>) => Promise<string>;\n}\n\nexport const TOOLS: ToolDef[] = [\n {\n name: \"search\",\n description:\n \"Query technical documentation. One concept per query \u2014 iterate with refined queries rather than raising top_k. Specify sources and versions; omit version for latest. If the response says confidence is weak, the documentation likely does not cover the topic \u2014 tell the user rather than guessing. Good: 'revalidateTag on-demand cache invalidation'. Bad (too broad): 'routing and auth and caching'.\",\n schema: {\n query: z.string().describe(\"One documentation concept to look up\"),\n sources: z\n .array(z.string())\n .optional()\n .describe(\"Source ids, optionally source@version; omit to use project defaults\"),\n language: z.string().optional(),\n max_response_tokens: z.number().optional().describe(\"Cap response size to control context bloat\"),\n },\n async handler(args) {\n const res = await client.search({\n query: String(args.query),\n sources: sourcesFromArg(args.sources),\n language: args.language as string | undefined,\n max_response_tokens:\n (args.max_response_tokens as number | undefined) ?? loadGlobalConfig().maxResponseTokens,\n });\n if (res.results.length === 0) return \"No results. The documentation likely does not cover this.\";\n const header =\n res.confidence === \"weak\"\n ? \"CONFIDENCE: WEAK \u2014 the docs may not cover this; say so rather than guessing.\\n\\n\"\n : \"\";\n return (\n header +\n res.results\n .map(\n (r) =>\n `## ${(r.heading_path ?? []).join(\" \u203A \")} (${r.source}@${r.version})\\nSource: ${r.origin_url}\\nchunk_id: ${r.chunk_id}\\n\\n${r.text}`,\n )\n .join(\"\\n\\n---\\n\\n\")\n );\n },\n },\n {\n name: \"fetch_document\",\n description: \"Expand context around a search hit by chunk id (neighbors in the same section).\",\n schema: { chunk_id: z.string(), window: z.number().optional() },\n async handler(args) {\n const res = await client.getContext(String(args.chunk_id), (args.window as number) ?? 2);\n return JSON.stringify(res.chunks ?? [], null, 2);\n },\n },\n {\n name: \"list_sources\",\n description: \"Discover indexed documentation sources; supports alias text search.\",\n schema: { q: z.string().optional() },\n async handler(args) {\n return JSON.stringify((await client.listSources(args.q as string | undefined)).sources ?? [], null, 2);\n },\n },\n {\n name: \"list_versions\",\n description: \"List indexed versions of a source.\",\n schema: { source: z.string() },\n async handler(args) {\n return JSON.stringify((await client.listVersions(String(args.source))).versions ?? [], null, 2);\n },\n },\n {\n name: \"report_result\",\n description:\n \"Report a retrieved chunk as helpful, incorrect, or outdated \u2014 use when documentation contradicted observed behavior.\",\n schema: {\n chunk_id: z.string(),\n verdict: z.enum([\"helpful\", \"incorrect\", \"outdated\"]),\n note: z.string().optional(),\n },\n async handler(args) {\n await client.reportResult(String(args.chunk_id), String(args.verdict), args.note as string | undefined);\n return \"Reported. Thank you \u2014 this feeds the quality benchmark.\";\n },\n },\n];\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport express from \"express\";\nimport { ApiError } from \"@monadeo.com/grimoire-core\";\nimport { TOOLS } from \"./tools.js\";\n\nfunction buildServer(): McpServer {\n const server = new McpServer(\n { name: \"grimoire\", version: \"0.1.0\" },\n {\n instructions:\n \"Use grimoire for any question about a library, framework, or tool \u2014 even when you think you know the answer, to get version-correct docs. Not for refactoring, business logic, or code review.\",\n },\n );\n\n for (const tool of TOOLS) {\n server.registerTool(\n tool.name,\n { description: tool.description, inputSchema: tool.schema },\n async (rawArgs: Record<string, unknown>) => {\n try {\n const text = await tool.handler(rawArgs);\n return { content: [{ type: \"text\" as const, text }] };\n } catch (err) {\n const message =\n err instanceof ApiError\n ? err.status === 401\n ? \"Not authenticated \u2014 the user should run `grimoire login`.\"\n : err.status === 429\n ? \"Quota or rate limit reached \u2014 inform the user; do not retry.\"\n : err.status === 404\n ? `Not found: ${JSON.stringify(err.body)}`\n : `Grimoire error: ${err.code}`\n : `Error: ${(err as Error).message}`;\n return { content: [{ type: \"text\" as const, text: message }], isError: true };\n }\n },\n );\n }\n return server;\n}\n\nasync function runStdio(): Promise<void> {\n await buildServer().connect(new StdioServerTransport());\n}\n\nfunction runHttp(port: number): void {\n const app = express();\n app.use(express.json());\n // Fresh server + transport per request; session lifecycle owned by the client.\n app.post(\"/mcp\", async (req, res) => {\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: undefined,\n enableDnsRebindingProtection: true,\n allowedHosts: [\"127.0.0.1\", `127.0.0.1:${port}`, \"localhost\", `localhost:${port}`],\n });\n const server = buildServer();\n res.on(\"close\", () => {\n void transport.close();\n void server.close();\n });\n await server.connect(transport);\n await transport.handleRequest(req, res, req.body);\n });\n app.get(\"/mcp\", (_req, res) => res.status(405).end()); // no server-initiated SSE\n app.listen(port, \"127.0.0.1\");\n}\n\nif (process.argv.includes(\"--http\")) {\n runHttp(Number(process.env.PORT ?? 8080));\n} else {\n void runStdio();\n}\n", "import { z } from \"zod\";\nimport { GrimoireClient, resolveDefaultSources, loadGlobalConfig } from \"@monadeo.com/grimoire-core\";\n\nconst client = new GrimoireClient();\n\nfunction sourcesFromArg(arg: unknown): { source: string; version?: string }[] {\n if (Array.isArray(arg)) {\n return arg.map((s) =>\n typeof s === \"string\"\n ? { source: s.split(\"@\")[0], version: s.split(\"@\")[1] }\n : (s as { source: string; version?: string }),\n );\n }\n return resolveDefaultSources();\n}\n\nexport interface ToolDef {\n name: string;\n description: string;\n schema: z.ZodRawShape;\n handler: (args: Record<string, unknown>) => Promise<string>;\n}\n\nexport const TOOLS: ToolDef[] = [\n {\n name: \"search\",\n description:\n \"Query technical documentation. One concept per query \u2014 iterate with refined queries rather than raising top_k. Specify sources and versions; omit version for latest. If the response says confidence is weak, the documentation likely does not cover the topic \u2014 tell the user rather than guessing. Good: 'revalidateTag on-demand cache invalidation'. Bad (too broad): 'routing and auth and caching'.\",\n schema: {\n query: z.string().describe(\"One documentation concept to look up\"),\n sources: z\n .array(z.string())\n .optional()\n .describe(\"Source ids, optionally source@version; omit to use project defaults\"),\n language: z.string().optional(),\n max_response_tokens: z.number().optional().describe(\"Cap response size to control context bloat\"),\n },\n async handler(args) {\n const res = await client.search({\n query: String(args.query),\n sources: sourcesFromArg(args.sources),\n language: args.language as string | undefined,\n max_response_tokens:\n (args.max_response_tokens as number | undefined) ?? loadGlobalConfig().maxResponseTokens,\n });\n if (res.results.length === 0) return \"No results. The documentation likely does not cover this.\";\n const header =\n res.confidence === \"weak\"\n ? \"CONFIDENCE: WEAK \u2014 the docs may not cover this; say so rather than guessing.\\n\\n\"\n : \"\";\n return (\n header +\n res.results\n .map(\n (r) =>\n `## ${(r.heading_path ?? []).join(\" \u203A \")} (${r.source}@${r.version})\\nSource: ${r.origin_url}\\nchunk_id: ${r.chunk_id}\\n\\n${r.text}`,\n )\n .join(\"\\n\\n---\\n\\n\")\n );\n },\n },\n {\n name: \"fetch_document\",\n description: \"Expand context around a search hit by chunk id (neighbors in the same section).\",\n schema: { chunk_id: z.string(), window: z.number().int().min(0).max(5).optional() },\n async handler(args) {\n const res = await client.getContext(String(args.chunk_id), (args.window as number) ?? 2);\n return JSON.stringify(res.chunks ?? [], null, 2);\n },\n },\n {\n name: \"list_sources\",\n description: \"Discover indexed documentation sources; supports alias text search.\",\n schema: { q: z.string().optional() },\n async handler(args) {\n return JSON.stringify((await client.listSources(args.q as string | undefined)).sources ?? [], null, 2);\n },\n },\n {\n name: \"list_versions\",\n description: \"List indexed versions of a source.\",\n schema: { source: z.string() },\n async handler(args) {\n return JSON.stringify((await client.listVersions(String(args.source))).versions ?? [], null, 2);\n },\n },\n {\n name: \"report_result\",\n description:\n \"Report a retrieved chunk as helpful, incorrect, or outdated \u2014 use when documentation contradicted observed behavior.\",\n schema: {\n chunk_id: z.string(),\n verdict: z.enum([\"helpful\", \"incorrect\", \"outdated\"]),\n note: z.string().optional(),\n },\n async handler(args) {\n await client.reportResult(String(args.chunk_id), String(args.verdict), args.note as string | undefined);\n return \"Reported. Thank you \u2014 this feeds the quality benchmark.\";\n },\n },\n];\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monadeo.com/grimoire-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "bin": {
@@ -14,7 +14,7 @@
14
14
  "@napi-rs/keyring": "^1.3.0",
15
15
  "express": "^5.2.1",
16
16
  "zod": "^4.1.12",
17
- "@monadeo.com/grimoire-core": "0.2.0"
17
+ "@monadeo.com/grimoire-core": "0.2.1"
18
18
  },
19
19
  "devDependencies": {
20
20
  "@types/express": "^5.0.6",