@speakeasy-api/docs-mcp-server 0.1.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/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # @speakeasy-api/docs-mcp-server
2
+
3
+ MCP server runtime exposing hybrid search over documentation via HTTP and stdio transports.
4
+
5
+ **Beta.** Part of the [Speakeasy Docs MCP](https://github.com/speakeasy-api/docs-mcp) monorepo.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install -g @speakeasy-api/docs-mcp-server
11
+ ```
12
+
13
+ ## CLI Usage
14
+
15
+ ```bash
16
+ # HTTP transport
17
+ docs-mcp-server --index-dir ./dist/.lancedb --transport http --port 20310
18
+
19
+ # Stdio transport (for MCP host integration)
20
+ docs-mcp-server --index-dir ./dist/.lancedb --transport stdio
21
+ ```
22
+
23
+ ## Programmatic Usage
24
+
25
+ ```typescript
26
+ import { McpDocsServer } from '@speakeasy-api/docs-mcp-server';
27
+
28
+ const server = new McpDocsServer({
29
+ dbPath: './dist/.lancedb',
30
+ });
31
+
32
+ server.start();
33
+ ```
34
+
35
+ ## MCP Tools
36
+
37
+ | Tool | Description |
38
+ |------|-------------|
39
+ | `search_docs` | Hybrid search with dynamically generated parameters and JSON Schema enum validation. Supports cursor pagination. |
40
+ | `get_doc` | Retrieve a specific chunk with optional neighboring context. |
41
+
42
+ Tool names, descriptions, and parameters are dynamically generated from the `metadata.json` produced during indexing.
43
+
44
+ ## License
45
+
46
+ [AGPL-3.0](https://github.com/speakeasy-api/docs-mcp/blob/main/LICENSE)
package/dist/bin.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=bin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.d.ts","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":""}
package/dist/bin.js ADDED
@@ -0,0 +1,283 @@
1
+ #!/usr/bin/env node
2
+ import { readFile, stat } from "node:fs/promises";
3
+ import { createRequire } from "node:module";
4
+ import path from "node:path";
5
+ import { Command } from "commander";
6
+ import { z } from "zod/v4";
7
+ import { DocsIndex, LanceDbSearchEngine, createEmbeddingProvider, normalizeMetadata } from "@speakeasy-api/docs-mcp-core";
8
+ import { McpDocsServer } from "./server.js";
9
+ import { startStdioServer } from "./stdio.js";
10
+ import { startHttpServer } from "./http.js";
11
+ const require = createRequire(import.meta.url);
12
+ const { version: SERVER_VERSION } = require("../package.json");
13
+ const TaxonomyFieldSchema = z.object({
14
+ description: z.string().optional(),
15
+ values: z.array(z.string())
16
+ }).passthrough();
17
+ const MetadataDocumentSchema = z.object({
18
+ metadata_version: z.string(),
19
+ corpus_description: z.string(),
20
+ taxonomy: z.record(z.string(), TaxonomyFieldSchema),
21
+ stats: z.object({
22
+ total_chunks: z.number().int(),
23
+ total_files: z.number().int(),
24
+ indexed_at: z.string(),
25
+ source_commit: z.string().nullable().optional()
26
+ }).passthrough(),
27
+ embedding: z.object({
28
+ provider: z.string(),
29
+ model: z.string(),
30
+ dimensions: z.number().int()
31
+ }).nullable(),
32
+ index: z.object({
33
+ path: z.string(),
34
+ table: z.string()
35
+ }).optional()
36
+ }).passthrough();
37
+ const program = new Command();
38
+ program
39
+ .name("docs-mcp-server")
40
+ .description("Run @speakeasy-api/docs-mcp-server over MCP stdio transport")
41
+ .requiredOption("--index-dir <path>", "Directory containing chunks.json and metadata.json")
42
+ .option("--name <value>", "MCP server name", "@speakeasy-api/docs-mcp-server")
43
+ .option("--tool-prefix <value>", "Tool name prefix (e.g. 'acme' produces acme_search_docs)")
44
+ .option("--version <value>", "MCP server version", SERVER_VERSION)
45
+ .option("--query-embedding-provider <provider>", "Query embedding provider: auto | none | hash | openai", parseQueryEmbeddingProvider, "auto")
46
+ .option("--query-embedding-model <value>", "Query embedding model override")
47
+ .option("--query-embedding-dimensions <number>", "Query embedding dimensions", parseNumberOption)
48
+ .option("--query-embedding-api-key <value>", "Query embedding API key (or set OPENAI_API_KEY)")
49
+ .option("--query-embedding-base-url <value>", "Query embedding API base URL")
50
+ .option("--query-embedding-batch-size <number>", "Query embedding batch size", parseIntOption)
51
+ .option("--proximity-weight <number>", "Lexical phrase blend weight", parseNumberOption)
52
+ .option("--phrase-slop <number>", "Phrase query slop (0-5)", parseNumberOption)
53
+ .option("--vector-weight <number>", "Vector rank blend weight", parseNumberOption)
54
+ .option("--allow-chunks-fallback", "Allow fallback to chunks.json when .lancedb is missing", false)
55
+ .option("--transport <type>", "Transport type: stdio or http", "stdio")
56
+ .option("--port <number>", "HTTP server port (only used with --transport http)", parseIntOption, 20310)
57
+ .action(async (options) => {
58
+ const indexDir = path.resolve(options.indexDir);
59
+ const metadataPath = path.join(indexDir, "metadata.json");
60
+ const chunksPath = path.join(indexDir, "chunks.json");
61
+ const metadataRaw = await readFile(metadataPath, "utf8");
62
+ let metadataDocument;
63
+ try {
64
+ metadataDocument = MetadataDocumentSchema.parse(JSON.parse(metadataRaw));
65
+ }
66
+ catch (error) {
67
+ const detail = error instanceof z.ZodError ? z.prettifyError(error) : String(error);
68
+ throw new Error(`Invalid metadata.json at '${metadataPath}':\n${detail}`, { cause: error });
69
+ }
70
+ const metadata = normalizeMetadata(metadataDocument);
71
+ const metadataKeys = Object.keys(metadata.taxonomy);
72
+ const indexConfig = parseIndexConfig(metadataDocument);
73
+ const queryEmbeddingProvider = resolveQueryEmbeddingProvider(options, metadata.embedding);
74
+ const loadInput = {
75
+ lancedbPath: path.resolve(indexDir, indexConfig.path),
76
+ tableName: indexConfig.table,
77
+ chunksPath,
78
+ metadataKeys,
79
+ allowChunksFallback: options.allowChunksFallback
80
+ };
81
+ if (queryEmbeddingProvider !== undefined) {
82
+ loadInput.queryEmbeddingProvider = queryEmbeddingProvider;
83
+ }
84
+ if (options.proximityWeight !== undefined) {
85
+ loadInput.proximityWeight = options.proximityWeight;
86
+ }
87
+ if (options.phraseSlop !== undefined) {
88
+ loadInput.phraseSlop = options.phraseSlop;
89
+ }
90
+ if (options.vectorWeight !== undefined) {
91
+ loadInput.vectorWeight = options.vectorWeight;
92
+ }
93
+ const index = await loadSearchEngine(loadInput);
94
+ const rrfWeights = parseRrfWeightsFromEnv();
95
+ const app = new McpDocsServer({
96
+ index,
97
+ metadata,
98
+ ...(options.toolPrefix ? { toolPrefix: options.toolPrefix } : {}),
99
+ ...(rrfWeights ? { rrfWeights } : {})
100
+ });
101
+ const serverName = options.name === "@speakeasy-api/docs-mcp-server" && options.toolPrefix
102
+ ? `${options.toolPrefix}-docs-server`
103
+ : options.name;
104
+ if (options.transport === "http") {
105
+ await startHttpServer(app, {
106
+ name: serverName,
107
+ version: options.version,
108
+ port: options.port
109
+ });
110
+ }
111
+ else {
112
+ await startStdioServer(app, {
113
+ name: serverName,
114
+ version: options.version
115
+ });
116
+ }
117
+ });
118
+ void program.parseAsync(process.argv);
119
+ async function loadSearchEngine(input) {
120
+ if (await exists(input.lancedbPath)) {
121
+ const openInput = {
122
+ dbPath: input.lancedbPath,
123
+ tableName: input.tableName,
124
+ metadataKeys: input.metadataKeys,
125
+ onWarning: (message) => console.warn(`warn: ${message}`)
126
+ };
127
+ if (input.queryEmbeddingProvider !== undefined) {
128
+ openInput.queryEmbeddingProvider = input.queryEmbeddingProvider;
129
+ }
130
+ if (input.proximityWeight !== undefined) {
131
+ openInput.proximityWeight = input.proximityWeight;
132
+ }
133
+ if (input.phraseSlop !== undefined) {
134
+ openInput.phraseSlop = input.phraseSlop;
135
+ }
136
+ if (input.vectorWeight !== undefined) {
137
+ openInput.vectorWeight = input.vectorWeight;
138
+ }
139
+ return LanceDbSearchEngine.open(openInput);
140
+ }
141
+ if (!input.allowChunksFallback) {
142
+ throw new Error(`LanceDB index not found at '${input.lancedbPath}'. Re-run docs-mcp build or pass --allow-chunks-fallback to use chunks.json fallback.`);
143
+ }
144
+ console.warn(`warn: LanceDB index not found at '${input.lancedbPath}'; falling back to chunks.json in-memory search`);
145
+ const chunksRaw = await readFile(input.chunksPath, "utf8");
146
+ const chunks = JSON.parse(chunksRaw);
147
+ return new DocsIndex(chunks);
148
+ }
149
+ function parseIndexConfig(metadata) {
150
+ const index = metadata.index;
151
+ if (!index || typeof index !== "object") {
152
+ return {
153
+ path: ".lancedb",
154
+ table: "chunks"
155
+ };
156
+ }
157
+ const record = index;
158
+ return {
159
+ path: toNonEmptyString(record.path) ?? ".lancedb",
160
+ table: toNonEmptyString(record.table) ?? "chunks"
161
+ };
162
+ }
163
+ function resolveQueryEmbeddingProvider(options, metadataEmbedding) {
164
+ const selectedProvider = selectEmbeddingProvider(options.queryEmbeddingProvider, metadataEmbedding);
165
+ if (!selectedProvider || selectedProvider === "none") {
166
+ return undefined;
167
+ }
168
+ const input = {
169
+ provider: selectedProvider
170
+ };
171
+ const model = options.queryEmbeddingModel ?? metadataEmbedding?.model;
172
+ if (model !== undefined) {
173
+ input.model = model;
174
+ }
175
+ const dimensions = options.queryEmbeddingDimensions ?? metadataEmbedding?.dimensions;
176
+ if (dimensions !== undefined) {
177
+ input.dimensions = dimensions;
178
+ }
179
+ const apiKey = options.queryEmbeddingApiKey ?? process.env.OPENAI_API_KEY;
180
+ if (apiKey !== undefined) {
181
+ input.apiKey = apiKey;
182
+ }
183
+ if (options.queryEmbeddingBaseUrl !== undefined) {
184
+ input.baseUrl = options.queryEmbeddingBaseUrl;
185
+ }
186
+ if (options.queryEmbeddingBatchSize !== undefined) {
187
+ input.batchSize = options.queryEmbeddingBatchSize;
188
+ }
189
+ try {
190
+ return createEmbeddingProvider(input);
191
+ }
192
+ catch (error) {
193
+ const message = error instanceof Error ? error.message : String(error);
194
+ console.warn(`warn: query embedding disabled: ${message}`);
195
+ return undefined;
196
+ }
197
+ }
198
+ function selectEmbeddingProvider(option, metadataEmbedding) {
199
+ if (option !== "auto") {
200
+ return option;
201
+ }
202
+ const provider = metadataEmbedding?.provider?.trim().toLowerCase();
203
+ if (!provider || provider === "none") {
204
+ return undefined;
205
+ }
206
+ if (provider === "hash" || provider === "openai") {
207
+ return provider;
208
+ }
209
+ console.warn(`warn: embedding provider '${metadataEmbedding?.provider}' is not supported at runtime; falling back to FTS-only search`);
210
+ return undefined;
211
+ }
212
+ function parseQueryEmbeddingProvider(value) {
213
+ const normalized = value.trim().toLowerCase();
214
+ if (normalized === "auto" ||
215
+ normalized === "none" ||
216
+ normalized === "hash" ||
217
+ normalized === "openai") {
218
+ return normalized;
219
+ }
220
+ throw new Error(`unsupported query embedding provider '${value}'. Expected one of: auto, none, hash, openai`);
221
+ }
222
+ function parseNumberOption(value) {
223
+ const parsed = Number(value);
224
+ if (!Number.isFinite(parsed)) {
225
+ throw new Error(`invalid numeric value '${value}'`);
226
+ }
227
+ return parsed;
228
+ }
229
+ function parseIntOption(value) {
230
+ const parsed = Number.parseInt(value, 10);
231
+ if (!Number.isFinite(parsed)) {
232
+ throw new Error(`invalid integer value '${value}'`);
233
+ }
234
+ return parsed;
235
+ }
236
+ function parseRrfWeightsFromEnv() {
237
+ const vector = parseOptionalEnvFloat("RRF_WEIGHT_VECTOR");
238
+ const match = parseOptionalEnvFloat("RRF_WEIGHT_MATCH");
239
+ const phrase = parseOptionalEnvFloat("RRF_WEIGHT_PHRASE");
240
+ if (vector === undefined && match === undefined && phrase === undefined) {
241
+ return undefined;
242
+ }
243
+ const weights = {};
244
+ if (vector !== undefined) {
245
+ weights.vector = vector;
246
+ }
247
+ if (match !== undefined) {
248
+ weights.match = match;
249
+ }
250
+ if (phrase !== undefined) {
251
+ weights.phrase = phrase;
252
+ }
253
+ return weights;
254
+ }
255
+ function parseOptionalEnvFloat(name) {
256
+ const raw = process.env[name];
257
+ if (raw === undefined || raw === "") {
258
+ return undefined;
259
+ }
260
+ const parsed = Number(raw);
261
+ if (!Number.isFinite(parsed)) {
262
+ console.warn(`warn: ignoring invalid ${name} value '${raw}'`);
263
+ return undefined;
264
+ }
265
+ return parsed;
266
+ }
267
+ function toNonEmptyString(value) {
268
+ if (typeof value !== "string") {
269
+ return undefined;
270
+ }
271
+ const trimmed = value.trim();
272
+ return trimmed ? trimmed : undefined;
273
+ }
274
+ async function exists(targetPath) {
275
+ try {
276
+ await stat(targetPath);
277
+ return true;
278
+ }
279
+ catch {
280
+ return false;
281
+ }
282
+ }
283
+ //# sourceMappingURL=bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
package/dist/http.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import http from "node:http";
2
+ import type { McpDocsServer } from "./server.js";
3
+ export interface StartHttpServerOptions {
4
+ name?: string;
5
+ version?: string;
6
+ port?: number;
7
+ }
8
+ export interface HttpServerHandle {
9
+ httpServer: http.Server;
10
+ port: number;
11
+ }
12
+ export declare function startHttpServer(app: McpDocsServer, options?: StartHttpServerOptions): Promise<HttpServerHandle>;
13
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAW7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;CACd;AA2CD,wBAAsB,eAAe,CACnC,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,gBAAgB,CAAC,CA2B3B"}
package/dist/http.js ADDED
@@ -0,0 +1,191 @@
1
+ import http from "node:http";
2
+ import { createRequire } from "node:module";
3
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
6
+ const require = createRequire(import.meta.url);
7
+ const { version: PKG_VERSION } = require("../package.json");
8
+ /**
9
+ * Create a fresh MCP Server wired to the given app and return it connected to a
10
+ * new stateless StreamableHTTPServerTransport. In stateless mode every request
11
+ * gets its own server+transport pair (the SDK examples demonstrate this pattern
12
+ * in `simpleStatelessStreamableHttp.ts`).
13
+ */
14
+ function createPerRequestServer(app, options) {
15
+ const server = new Server({
16
+ name: options.name ?? "@speakeasy-api/docs-mcp-server",
17
+ version: options.version ?? PKG_VERSION
18
+ }, {
19
+ capabilities: {
20
+ tools: {}
21
+ }
22
+ });
23
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
24
+ const tools = app.getTools().map((tool) => ({
25
+ name: tool.name,
26
+ description: tool.description,
27
+ inputSchema: tool.inputSchema
28
+ }));
29
+ return { tools };
30
+ });
31
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
32
+ const result = await app.callTool(request.params.name, request.params.arguments ?? {});
33
+ return result;
34
+ });
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- exactOptionalPropertyTypes workaround
36
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
37
+ return { server, transport };
38
+ }
39
+ export async function startHttpServer(app, options = {}) {
40
+ const port = options.port ?? 20310;
41
+ const httpServer = http.createServer(async (req, res) => {
42
+ try {
43
+ await handleRequest(req, res, app, options);
44
+ }
45
+ catch (error) {
46
+ console.error("Unhandled error in request handler:", error);
47
+ if (!res.headersSent) {
48
+ res.writeHead(500, { "Content-Type": "application/json" });
49
+ res.end(JSON.stringify({
50
+ jsonrpc: "2.0",
51
+ error: { code: -32603, message: "Internal server error" },
52
+ id: null
53
+ }));
54
+ }
55
+ else if (!res.writableEnded) {
56
+ res.end();
57
+ }
58
+ }
59
+ });
60
+ const actualPort = await listenOnAvailablePort(httpServer, port);
61
+ console.error(`MCP HTTP server listening on http://localhost:${actualPort}/mcp`);
62
+ return { httpServer, port: actualPort };
63
+ }
64
+ const CORS_HEADERS = {
65
+ "Access-Control-Allow-Origin": "*",
66
+ "Access-Control-Allow-Methods": "POST, OPTIONS",
67
+ "Access-Control-Allow-Headers": "*",
68
+ "Access-Control-Max-Age": "86400"
69
+ };
70
+ function setCorsHeaders(res) {
71
+ for (const [key, value] of Object.entries(CORS_HEADERS)) {
72
+ res.setHeader(key, value);
73
+ }
74
+ }
75
+ async function handleRequest(req, res, app, options) {
76
+ // Only the pathname matters; the base URL is arbitrary.
77
+ const url = new URL(req.url ?? "/", "http://localhost");
78
+ if (url.pathname !== "/mcp") {
79
+ res.writeHead(405, { "Content-Type": "text/plain" });
80
+ res.end("Method Not Allowed");
81
+ return;
82
+ }
83
+ setCorsHeaders(res);
84
+ if (req.method === "OPTIONS") {
85
+ res.writeHead(204);
86
+ res.end();
87
+ return;
88
+ }
89
+ if (req.method === "GET" || req.method === "DELETE") {
90
+ res.writeHead(405, { "Content-Type": "application/json" });
91
+ res.end(JSON.stringify({
92
+ jsonrpc: "2.0",
93
+ error: { code: -32000, message: "Method not allowed." },
94
+ id: null
95
+ }));
96
+ return;
97
+ }
98
+ // Parse JSON body before handing off to the transport
99
+ let parsed;
100
+ try {
101
+ const body = await readBody(req);
102
+ parsed = JSON.parse(body);
103
+ }
104
+ catch {
105
+ res.writeHead(400, { "Content-Type": "application/json" });
106
+ res.end(JSON.stringify({
107
+ jsonrpc: "2.0",
108
+ error: { code: -32700, message: "Parse error" },
109
+ id: null
110
+ }));
111
+ return;
112
+ }
113
+ const { server, transport } = createPerRequestServer(app, options);
114
+ try {
115
+ await server.connect(transport);
116
+ await transport.handleRequest(req, res, parsed);
117
+ res.on("close", () => {
118
+ transport.close();
119
+ server.close();
120
+ });
121
+ }
122
+ catch (error) {
123
+ console.error("Error handling MCP request:", error);
124
+ if (!res.headersSent) {
125
+ res.writeHead(500, { "Content-Type": "application/json" });
126
+ res.end(JSON.stringify({
127
+ jsonrpc: "2.0",
128
+ error: { code: -32603, message: "Internal server error" },
129
+ id: null
130
+ }));
131
+ }
132
+ transport.close();
133
+ server.close();
134
+ }
135
+ }
136
+ const MAX_PORT_ATTEMPTS = 10;
137
+ /**
138
+ * Try to listen on `startPort`. If the port is busy (EADDRINUSE), try
139
+ * startPort+1, startPort+2, etc. up to MAX_PORT_ATTEMPTS.
140
+ * Port 0 is passed through directly (OS picks an ephemeral port).
141
+ */
142
+ function listenOnAvailablePort(server, startPort) {
143
+ if (startPort === 0) {
144
+ return new Promise((resolve, reject) => {
145
+ server.once("error", reject);
146
+ server.listen(0, () => {
147
+ server.removeListener("error", reject);
148
+ const addr = server.address();
149
+ resolve(typeof addr === "object" && addr ? addr.port : 0);
150
+ });
151
+ });
152
+ }
153
+ let attempt = 0;
154
+ return new Promise((resolve, reject) => {
155
+ const tryPort = (port) => {
156
+ server.once("error", (err) => {
157
+ if (err.code === "EADDRINUSE" && attempt < MAX_PORT_ATTEMPTS) {
158
+ attempt++;
159
+ tryPort(port + 1);
160
+ }
161
+ else {
162
+ reject(err);
163
+ }
164
+ });
165
+ server.listen(port, () => {
166
+ server.removeAllListeners("error");
167
+ resolve(port);
168
+ });
169
+ };
170
+ tryPort(startPort);
171
+ });
172
+ }
173
+ const MAX_BODY_BYTES = 50 * 1024 * 1024; // 50 MB
174
+ function readBody(req) {
175
+ return new Promise((resolve, reject) => {
176
+ const chunks = [];
177
+ let totalLength = 0;
178
+ req.on("data", (chunk) => {
179
+ totalLength += chunk.length;
180
+ if (totalLength > MAX_BODY_BYTES) {
181
+ req.destroy();
182
+ reject(new Error("Request body too large"));
183
+ return;
184
+ }
185
+ chunks.push(chunk);
186
+ });
187
+ req.on("end", () => resolve(Buffer.concat(chunks).toString()));
188
+ req.on("error", reject);
189
+ });
190
+ }
191
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from "./types.js";
2
+ export * from "./schema.js";
3
+ export * from "./server.js";
4
+ export * from "./stdio.js";
5
+ export * from "./http.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export * from "./types.js";
2
+ export * from "./schema.js";
3
+ export * from "./server.js";
4
+ export * from "./stdio.js";
5
+ export * from "./http.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { CorpusMetadata } from "@speakeasy-api/docs-mcp-core";
2
+ export declare function buildSearchDocsSchema(metadata: CorpusMetadata): Record<string, unknown>;
3
+ export declare function buildGetDocSchema(): Record<string, unknown>;
4
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkCvF;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAqB3D"}
package/dist/schema.js ADDED
@@ -0,0 +1,53 @@
1
+ export function buildSearchDocsSchema(metadata) {
2
+ const properties = {
3
+ query: {
4
+ type: "string",
5
+ description: "The search query (e.g., 'how to paginate', 'RateLimitError')."
6
+ },
7
+ limit: {
8
+ type: "integer",
9
+ description: "Maximum number of results to return. Default is 10.",
10
+ minimum: 1,
11
+ maximum: 50,
12
+ default: 10
13
+ },
14
+ cursor: {
15
+ type: "string",
16
+ description: "Opaque pagination token returned from a previous search. Omit for the first page."
17
+ }
18
+ };
19
+ for (const [key, field] of Object.entries(metadata.taxonomy)) {
20
+ properties[key] = {
21
+ type: "string",
22
+ description: field.description ?? `Filter results by ${key}.`,
23
+ enum: field.values
24
+ };
25
+ }
26
+ return {
27
+ type: "object",
28
+ additionalProperties: false,
29
+ properties,
30
+ required: ["query"]
31
+ };
32
+ }
33
+ export function buildGetDocSchema() {
34
+ return {
35
+ type: "object",
36
+ additionalProperties: false,
37
+ properties: {
38
+ chunk_id: {
39
+ type: "string",
40
+ description: "The exact ID of the chunk to retrieve, as returned by search_docs (e.g., 'guides/retries.md#backoff-strategy')."
41
+ },
42
+ context: {
43
+ type: "integer",
44
+ description: "Number of adjacent chunks to include before and after the target chunk. Default is 0.",
45
+ minimum: 0,
46
+ maximum: 5,
47
+ default: 0
48
+ }
49
+ },
50
+ required: ["chunk_id"]
51
+ };
52
+ }
53
+ //# sourceMappingURL=schema.js.map