@warlock.js/ai-tools 4.5.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +164 -0
  4. package/cjs/index.cjs +2519 -0
  5. package/cjs/index.cjs.map +1 -0
  6. package/esm/contracts/http.type.d.mts +96 -0
  7. package/esm/contracts/http.type.d.mts.map +1 -0
  8. package/esm/contracts/index.d.mts +4 -0
  9. package/esm/contracts/mcp.type.d.mts +216 -0
  10. package/esm/contracts/mcp.type.d.mts.map +1 -0
  11. package/esm/contracts/utility.type.d.mts +96 -0
  12. package/esm/contracts/utility.type.d.mts.map +1 -0
  13. package/esm/contracts/web.type.d.mts +136 -0
  14. package/esm/contracts/web.type.d.mts.map +1 -0
  15. package/esm/errors.d.mts +225 -0
  16. package/esm/errors.d.mts.map +1 -0
  17. package/esm/errors.mjs +136 -0
  18. package/esm/errors.mjs.map +1 -0
  19. package/esm/http/http-request.d.mts +57 -0
  20. package/esm/http/http-request.d.mts.map +1 -0
  21. package/esm/http/http-request.mjs +221 -0
  22. package/esm/http/http-request.mjs.map +1 -0
  23. package/esm/index.d.mts +19 -0
  24. package/esm/index.mjs +15 -0
  25. package/esm/mcp/client.mjs +199 -0
  26. package/esm/mcp/client.mjs.map +1 -0
  27. package/esm/mcp/index.d.mts +43 -0
  28. package/esm/mcp/index.d.mts.map +1 -0
  29. package/esm/mcp/index.mjs +19 -0
  30. package/esm/mcp/index.mjs.map +1 -0
  31. package/esm/mcp/json-schema-to-standard.d.mts +34 -0
  32. package/esm/mcp/json-schema-to-standard.d.mts.map +1 -0
  33. package/esm/mcp/json-schema-to-standard.mjs +147 -0
  34. package/esm/mcp/json-schema-to-standard.mjs.map +1 -0
  35. package/esm/mcp/serve.d.mts +46 -0
  36. package/esm/mcp/serve.d.mts.map +1 -0
  37. package/esm/mcp/serve.mjs +264 -0
  38. package/esm/mcp/serve.mjs.map +1 -0
  39. package/esm/mcp/transport.d.mts +48 -0
  40. package/esm/mcp/transport.d.mts.map +1 -0
  41. package/esm/mcp/transport.mjs +381 -0
  42. package/esm/mcp/transport.mjs.map +1 -0
  43. package/esm/mcp/transport.type.d.mts +51 -0
  44. package/esm/mcp/transport.type.d.mts.map +1 -0
  45. package/esm/node_modules/@standard-schema/spec/dist/index.d.mts +80 -0
  46. package/esm/node_modules/@standard-schema/spec/dist/index.d.mts.map +1 -0
  47. package/esm/register.d.mts +55 -0
  48. package/esm/register.d.mts.map +1 -0
  49. package/esm/register.mjs +21 -0
  50. package/esm/register.mjs.map +1 -0
  51. package/esm/schema.mjs +127 -0
  52. package/esm/schema.mjs.map +1 -0
  53. package/esm/utility/calculator.d.mts +35 -0
  54. package/esm/utility/calculator.d.mts.map +1 -0
  55. package/esm/utility/calculator.mjs +272 -0
  56. package/esm/utility/calculator.mjs.map +1 -0
  57. package/esm/utility/date-time.d.mts +57 -0
  58. package/esm/utility/date-time.d.mts.map +1 -0
  59. package/esm/utility/date-time.mjs +193 -0
  60. package/esm/utility/date-time.mjs.map +1 -0
  61. package/esm/utility/index.d.mts +2 -0
  62. package/esm/utility/index.mjs +4 -0
  63. package/esm/utility/schema.mjs +114 -0
  64. package/esm/utility/schema.mjs.map +1 -0
  65. package/esm/web/fetch-url.d.mts +39 -0
  66. package/esm/web/fetch-url.d.mts.map +1 -0
  67. package/esm/web/fetch-url.mjs +228 -0
  68. package/esm/web/fetch-url.mjs.map +1 -0
  69. package/esm/web/index.d.mts +2 -0
  70. package/esm/web/index.mjs +4 -0
  71. package/esm/web/schema.mjs +86 -0
  72. package/esm/web/schema.mjs.map +1 -0
  73. package/esm/web/web-search.d.mts +38 -0
  74. package/esm/web/web-search.d.mts.map +1 -0
  75. package/esm/web/web-search.mjs +167 -0
  76. package/esm/web/web-search.mjs.map +1 -0
  77. package/llms-full.txt +326 -0
  78. package/llms.txt +11 -0
  79. package/package.json +45 -0
  80. package/skills/README.md +17 -0
  81. package/skills/connect-mcp-server/SKILL.md +98 -0
  82. package/skills/expose-as-mcp-server/SKILL.md +85 -0
  83. package/skills/use-web-and-http-tools/SKILL.md +125 -0
@@ -0,0 +1,264 @@
1
+ import { McpTransportError } from "../errors.mjs";
2
+ import { extractJsonSchema } from "@warlock.js/ai";
3
+ import { createInterface } from "node:readline";
4
+
5
+ //#region ../@warlock.js/ai-tools/src/mcp/serve.ts
6
+ /** JSON-RPC version literal every outbound message carries. */
7
+ const JSONRPC_VERSION = "2.0";
8
+ /** Default JSON-Schema dialect emitted for each tool's `inputSchema`. */
9
+ const DEFAULT_SCHEMA_TARGET = "draft-2020-12";
10
+ /** Default advertised server version when the caller omits one. */
11
+ const DEFAULT_VERSION = "4.4.0";
12
+ /** The MCP protocol version this server advertises in `initialize`. */
13
+ const PROTOCOL_VERSION = "2025-06-18";
14
+ /** JSON-RPC standard error codes we emit. */
15
+ const JSON_RPC_METHOD_NOT_FOUND = -32601;
16
+ const JSON_RPC_INVALID_PARAMS = -32602;
17
+ /**
18
+ * Resolve the {@link McpServeSource} (either an object exposing `tools()`
19
+ * or a literal `ToolContract[]`) into a flat contract array.
20
+ */
21
+ function resolveTools(source) {
22
+ if (Array.isArray(source)) return source;
23
+ return source.tools();
24
+ }
25
+ /**
26
+ * The pure protocol core of `serve` — maps one JSON-RPC request to its
27
+ * response, with no I/O. Both the stdio and http serve-transports pump
28
+ * their inbound requests through this, and specs can drive it directly.
29
+ *
30
+ * Handles exactly the MCP slice this package serves: `initialize`,
31
+ * `tools/list`, and `tools/call`. Any other method answers with a
32
+ * JSON-RPC `method not found` error.
33
+ *
34
+ * Constructed via {@link createServeHandler}.
35
+ */
36
+ var McpServeHandler = class {
37
+ constructor(source, options) {
38
+ this.tools = resolveTools(source);
39
+ this.byName = new Map(this.tools.map((contract) => [contract.name, contract]));
40
+ this.options = options;
41
+ }
42
+ /**
43
+ * Dispatch one inbound JSON-RPC request to its handler and produce the
44
+ * response. A handler that throws is mapped to a JSON-RPC error response
45
+ * — the serve loop never crashes on a bad request.
46
+ */
47
+ async handle(request) {
48
+ try {
49
+ switch (request.method) {
50
+ case "initialize": return this.ok(request.id, this.initializeResult());
51
+ case "tools/list": return this.ok(request.id, { tools: this.listTools() });
52
+ case "tools/call": return this.ok(request.id, await this.callTool(request.params));
53
+ default: return this.error(request.id, JSON_RPC_METHOD_NOT_FOUND, `Method "${request.method}" is not supported by this MCP server.`);
54
+ }
55
+ } catch (cause) {
56
+ const message = cause instanceof Error ? cause.message : String(cause);
57
+ return this.error(request.id, JSON_RPC_INVALID_PARAMS, message);
58
+ }
59
+ }
60
+ /** Build the `initialize` result advertising name / version / capabilities. */
61
+ initializeResult() {
62
+ return {
63
+ protocolVersion: PROTOCOL_VERSION,
64
+ capabilities: { tools: {} },
65
+ serverInfo: {
66
+ name: this.options.name,
67
+ version: this.options.version ?? DEFAULT_VERSION
68
+ }
69
+ };
70
+ }
71
+ /**
72
+ * Build the `tools/list` payload: one {@link McpToolDescriptor} per
73
+ * contract, its `inputSchema` extracted via `extractJsonSchema` at the
74
+ * configured dialect (default `draft-2020-12` — overriding
75
+ * `extractJsonSchema`'s own `openai-strict` default to a neutral MCP draft).
76
+ */
77
+ listTools() {
78
+ const target = this.options.schemaTarget ?? DEFAULT_SCHEMA_TARGET;
79
+ return this.tools.map((contract) => {
80
+ const inputSchema = extractJsonSchema(contract.input, { target }) ?? {
81
+ type: "object",
82
+ properties: {}
83
+ };
84
+ return {
85
+ name: contract.name,
86
+ description: contract.description,
87
+ inputSchema
88
+ };
89
+ });
90
+ }
91
+ /**
92
+ * Route a `tools/call` to the named contract's `invoke()` and map the
93
+ * never-throwing {@link import("@warlock.js/ai").ToolInvokeResult}: `data`
94
+ * → a text content block, `error` → an `isError: true` result. An unknown
95
+ * tool name throws (mapped to a JSON-RPC error by {@link handle}).
96
+ */
97
+ async callTool(params) {
98
+ const { name, args } = readCallParams(params);
99
+ const contract = this.byName.get(name);
100
+ if (!contract) throw new McpTransportError(`Unknown tool "${name}".`, {
101
+ type: "protocol",
102
+ method: "tools/call"
103
+ });
104
+ const result = await contract.invoke(args);
105
+ if (result.error) return {
106
+ content: [{
107
+ type: "text",
108
+ text: result.error.message
109
+ }],
110
+ isError: true
111
+ };
112
+ return {
113
+ content: [{
114
+ type: "text",
115
+ text: serializeData(result.data)
116
+ }],
117
+ isError: false
118
+ };
119
+ }
120
+ /** Build a JSON-RPC success response. */
121
+ ok(id, result) {
122
+ return {
123
+ jsonrpc: JSONRPC_VERSION,
124
+ id,
125
+ result
126
+ };
127
+ }
128
+ /** Build a JSON-RPC error response. */
129
+ error(id, code, message) {
130
+ return {
131
+ jsonrpc: JSONRPC_VERSION,
132
+ id,
133
+ error: {
134
+ code,
135
+ message
136
+ }
137
+ };
138
+ }
139
+ };
140
+ /**
141
+ * Read and validate the `tools/call` params into `{ name, args }`. Throws
142
+ * a typed {@link McpTransportError} when `name` is missing — mapped to a
143
+ * JSON-RPC `invalid params` error by the handler.
144
+ */
145
+ function readCallParams(params) {
146
+ if (typeof params !== "object" || params === null) throw new McpTransportError("tools/call params must be an object.", {
147
+ type: "protocol",
148
+ method: "tools/call"
149
+ });
150
+ const record = params;
151
+ if (typeof record.name !== "string") throw new McpTransportError("tools/call requires a string `name`.", {
152
+ type: "protocol",
153
+ method: "tools/call"
154
+ });
155
+ return {
156
+ name: record.name,
157
+ args: record.arguments ?? {}
158
+ };
159
+ }
160
+ /**
161
+ * Serialize a tool's `data` for an MCP text content block — a string is
162
+ * passed verbatim, everything else is JSON-stringified so structured
163
+ * output crosses the wire as text the consuming client can re-parse.
164
+ */
165
+ function serializeData(data) {
166
+ if (typeof data === "string") return data;
167
+ if (data === void 0) return "";
168
+ return JSON.stringify(data);
169
+ }
170
+ /**
171
+ * Build the pure protocol handler for a serve source. Exposed (alongside
172
+ * {@link serve}) so callers and tests can drive the MCP protocol without an
173
+ * actual transport — feed it a JSON-RPC request, get the response.
174
+ *
175
+ * @param source - The tools to expose (an object with `tools()` or a literal array).
176
+ * @param options - Serve options (name / version / schema target).
177
+ * @returns An object whose `handle(request)` maps a request to a response.
178
+ */
179
+ function createServeHandler(source, options) {
180
+ return new McpServeHandler(source, options);
181
+ }
182
+ /**
183
+ * The internal {@link McpServer} — owns a {@link McpServeHandler} and a
184
+ * transport pump. For `stdio` it reads newline-delimited JSON-RPC requests
185
+ * from `process.stdin` and writes responses to `process.stdout`; the
186
+ * `http` transport is accepted but listening is deferred to the host
187
+ * (a serve-over-HTTP needs a server the caller owns).
188
+ *
189
+ * Constructed via {@link serve}; the class itself is internal.
190
+ */
191
+ var McpServerImpl = class {
192
+ constructor(source, options) {
193
+ this.running = false;
194
+ this.handler = new McpServeHandler(source, options);
195
+ this.options = options;
196
+ }
197
+ async start() {
198
+ if (this.running) return;
199
+ if ((this.options.transport ?? { type: "stdio" }).type !== "stdio") throw new McpTransportError("serve() over http requires a host-provided server; only stdio is auto-pumped.", { type: "connect" });
200
+ this.running = true;
201
+ this.reader = createInterface({ input: process.stdin });
202
+ this.reader.on("line", (line) => {
203
+ this.onLine(line);
204
+ });
205
+ }
206
+ /**
207
+ * Parse one stdin line as a JSON-RPC request, dispatch it through the
208
+ * handler, and write the response as a single line to stdout. Non-JSON
209
+ * lines and notifications (no `id`) are ignored.
210
+ */
211
+ async onLine(line) {
212
+ const trimmed = line.trim();
213
+ if (!trimmed) return;
214
+ let request;
215
+ try {
216
+ request = JSON.parse(trimmed);
217
+ } catch {
218
+ return;
219
+ }
220
+ if (request.id === void 0 || request.id === null) return;
221
+ const response = await this.handler.handle(request);
222
+ process.stdout.write(`${JSON.stringify(response)}\n`);
223
+ }
224
+ async stop() {
225
+ this.running = false;
226
+ this.reader?.close();
227
+ this.reader = void 0;
228
+ }
229
+ };
230
+ /**
231
+ * Expose a built agent / supervisor / orchestrator (or a raw
232
+ * `ToolContract[]`) AS an MCP server (Direction B: local primitive → MCP
233
+ * server other clients consume).
234
+ *
235
+ * Enumerates `source.tools()` (or the literal array) once at construction.
236
+ * `tools/list` answers with each tool's `inputSchema` extracted via
237
+ * `extractJsonSchema` at the configured `schemaTarget` (default
238
+ * `draft-2020-12`). `tools/call` routes to the named contract's
239
+ * `invoke()` and maps the never-throwing result — `data` becomes a text
240
+ * content block, `error` becomes an `isError: true` result — so a failing
241
+ * tool surfaces as a normal MCP tool error rather than crashing the server.
242
+ *
243
+ * The default transport is `stdio`, pumped over `process.stdin` /
244
+ * `process.stdout`. Serving over HTTP is left to a host-owned server;
245
+ * `start()` rejects an `http` transport (the protocol core is available
246
+ * via {@link createServeHandler} for a caller's own HTTP wiring).
247
+ *
248
+ * @param source - The tools to expose.
249
+ * @param options - Server name, version, transport, and schema dialect.
250
+ * @returns An {@link McpServer} with `start()` / `stop()`.
251
+ *
252
+ * @example
253
+ * serve(
254
+ * { tools: () => ws.allTools() },
255
+ * { name: "warlock-workspace", transport: { type: "stdio" } },
256
+ * ).start();
257
+ */
258
+ function serve(source, options) {
259
+ return new McpServerImpl(source, options);
260
+ }
261
+
262
+ //#endregion
263
+ export { createServeHandler, serve };
264
+ //# sourceMappingURL=serve.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai-tools/src/mcp/serve.ts"],"sourcesContent":["import { createInterface, type Interface } from \"node:readline\";\nimport { extractJsonSchema, type ToolContract } from \"@warlock.js/ai\";\nimport type {\n JsonRpcRequest,\n JsonRpcResponse,\n McpServeOptions,\n McpServeSource,\n McpServer,\n McpToolCallResult,\n McpToolDescriptor,\n} from \"../contracts\";\nimport { McpTransportError } from \"../errors\";\n\n/** JSON-RPC version literal every outbound message carries. */\nconst JSONRPC_VERSION = \"2.0\";\n\n/** Default JSON-Schema dialect emitted for each tool's `inputSchema`. */\nconst DEFAULT_SCHEMA_TARGET = \"draft-2020-12\";\n\n/** Default advertised server version when the caller omits one. */\nconst DEFAULT_VERSION = \"4.4.0\";\n\n/** The MCP protocol version this server advertises in `initialize`. */\nconst PROTOCOL_VERSION = \"2025-06-18\";\n\n/** JSON-RPC standard error codes we emit. */\nconst JSON_RPC_METHOD_NOT_FOUND = -32601;\nconst JSON_RPC_INVALID_PARAMS = -32602;\n\n/**\n * Resolve the {@link McpServeSource} (either an object exposing `tools()`\n * or a literal `ToolContract[]`) into a flat contract array.\n */\nfunction resolveTools(source: McpServeSource): ToolContract[] {\n if (Array.isArray(source)) {\n return source;\n }\n\n return source.tools();\n}\n\n/**\n * The pure protocol core of `serve` — maps one JSON-RPC request to its\n * response, with no I/O. Both the stdio and http serve-transports pump\n * their inbound requests through this, and specs can drive it directly.\n *\n * Handles exactly the MCP slice this package serves: `initialize`,\n * `tools/list`, and `tools/call`. Any other method answers with a\n * JSON-RPC `method not found` error.\n *\n * Constructed via {@link createServeHandler}.\n */\nclass McpServeHandler {\n /** The tools this server exposes (snapshotted at construction). */\n private readonly tools: ToolContract[];\n\n /** Fast lookup by tool name for `tools/call` dispatch. */\n private readonly byName: Map<string, ToolContract>;\n\n /** Construction-time serve options (name / version / schema target). */\n private readonly options: McpServeOptions;\n\n public constructor(source: McpServeSource, options: McpServeOptions) {\n this.tools = resolveTools(source);\n this.byName = new Map(this.tools.map((contract) => [contract.name, contract]));\n this.options = options;\n }\n\n /**\n * Dispatch one inbound JSON-RPC request to its handler and produce the\n * response. A handler that throws is mapped to a JSON-RPC error response\n * — the serve loop never crashes on a bad request.\n */\n public async handle(request: JsonRpcRequest): Promise<JsonRpcResponse> {\n try {\n switch (request.method) {\n case \"initialize\":\n return this.ok(request.id, this.initializeResult());\n case \"tools/list\":\n return this.ok(request.id, { tools: this.listTools() });\n case \"tools/call\":\n return this.ok(request.id, await this.callTool(request.params));\n default:\n return this.error(\n request.id,\n JSON_RPC_METHOD_NOT_FOUND,\n `Method \"${request.method}\" is not supported by this MCP server.`,\n );\n }\n } catch (cause) {\n const message = cause instanceof Error ? cause.message : String(cause);\n\n return this.error(request.id, JSON_RPC_INVALID_PARAMS, message);\n }\n }\n\n /** Build the `initialize` result advertising name / version / capabilities. */\n private initializeResult(): Record<string, unknown> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: { tools: {} },\n serverInfo: {\n name: this.options.name,\n version: this.options.version ?? DEFAULT_VERSION,\n },\n };\n }\n\n /**\n * Build the `tools/list` payload: one {@link McpToolDescriptor} per\n * contract, its `inputSchema` extracted via `extractJsonSchema` at the\n * configured dialect (default `draft-2020-12` — overriding\n * `extractJsonSchema`'s own `openai-strict` default to a neutral MCP draft).\n */\n private listTools(): McpToolDescriptor[] {\n const target = this.options.schemaTarget ?? DEFAULT_SCHEMA_TARGET;\n\n return this.tools.map((contract) => {\n const inputSchema = extractJsonSchema(contract.input, { target }) ?? {\n type: \"object\",\n properties: {},\n };\n\n return {\n name: contract.name,\n description: contract.description,\n inputSchema,\n };\n });\n }\n\n /**\n * Route a `tools/call` to the named contract's `invoke()` and map the\n * never-throwing {@link import(\"@warlock.js/ai\").ToolInvokeResult}: `data`\n * → a text content block, `error` → an `isError: true` result. An unknown\n * tool name throws (mapped to a JSON-RPC error by {@link handle}).\n */\n private async callTool(params: unknown): Promise<McpToolCallResult> {\n const { name, args } = readCallParams(params);\n const contract = this.byName.get(name);\n\n if (!contract) {\n throw new McpTransportError(`Unknown tool \"${name}\".`, {\n type: \"protocol\",\n method: \"tools/call\",\n });\n }\n\n const result = await contract.invoke(args);\n\n if (result.error) {\n return {\n content: [{ type: \"text\", text: result.error.message }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: serializeData(result.data) }],\n isError: false,\n };\n }\n\n /** Build a JSON-RPC success response. */\n private ok(id: JsonRpcRequest[\"id\"], result: unknown): JsonRpcResponse {\n return { jsonrpc: JSONRPC_VERSION, id, result };\n }\n\n /** Build a JSON-RPC error response. */\n private error(id: JsonRpcRequest[\"id\"], code: number, message: string): JsonRpcResponse {\n return { jsonrpc: JSONRPC_VERSION, id, error: { code, message } };\n }\n}\n\n/**\n * Read and validate the `tools/call` params into `{ name, args }`. Throws\n * a typed {@link McpTransportError} when `name` is missing — mapped to a\n * JSON-RPC `invalid params` error by the handler.\n */\nfunction readCallParams(params: unknown): { name: string; args: unknown } {\n if (typeof params !== \"object\" || params === null) {\n throw new McpTransportError(\"tools/call params must be an object.\", {\n type: \"protocol\",\n method: \"tools/call\",\n });\n }\n\n const record = params as { name?: unknown; arguments?: unknown };\n\n if (typeof record.name !== \"string\") {\n throw new McpTransportError(\"tools/call requires a string `name`.\", {\n type: \"protocol\",\n method: \"tools/call\",\n });\n }\n\n return { name: record.name, args: record.arguments ?? {} };\n}\n\n/**\n * Serialize a tool's `data` for an MCP text content block — a string is\n * passed verbatim, everything else is JSON-stringified so structured\n * output crosses the wire as text the consuming client can re-parse.\n */\nfunction serializeData(data: unknown): string {\n if (typeof data === \"string\") {\n return data;\n }\n\n if (data === undefined) {\n return \"\";\n }\n\n return JSON.stringify(data);\n}\n\n/**\n * Build the pure protocol handler for a serve source. Exposed (alongside\n * {@link serve}) so callers and tests can drive the MCP protocol without an\n * actual transport — feed it a JSON-RPC request, get the response.\n *\n * @param source - The tools to expose (an object with `tools()` or a literal array).\n * @param options - Serve options (name / version / schema target).\n * @returns An object whose `handle(request)` maps a request to a response.\n */\nexport function createServeHandler(\n source: McpServeSource,\n options: McpServeOptions,\n): { handle(request: JsonRpcRequest): Promise<JsonRpcResponse> } {\n return new McpServeHandler(source, options);\n}\n\n/**\n * The internal {@link McpServer} — owns a {@link McpServeHandler} and a\n * transport pump. For `stdio` it reads newline-delimited JSON-RPC requests\n * from `process.stdin` and writes responses to `process.stdout`; the\n * `http` transport is accepted but listening is deferred to the host\n * (a serve-over-HTTP needs a server the caller owns).\n *\n * Constructed via {@link serve}; the class itself is internal.\n */\nclass McpServerImpl implements McpServer {\n /** The pure protocol handler. */\n private readonly handler: McpServeHandler;\n\n /** Serve options (transport selection lives here). */\n private readonly options: McpServeOptions;\n\n /** The stdin line reader while serving over stdio. */\n private reader: Interface | undefined;\n\n /** Flipped while the server is actively reading the transport. */\n private running = false;\n\n public constructor(source: McpServeSource, options: McpServeOptions) {\n this.handler = new McpServeHandler(source, options);\n this.options = options;\n }\n\n public async start(): Promise<void> {\n if (this.running) {\n return;\n }\n\n const transport = this.options.transport ?? { type: \"stdio\" };\n\n if (transport.type !== \"stdio\") {\n throw new McpTransportError(\n \"serve() over http requires a host-provided server; only stdio is auto-pumped.\",\n { type: \"connect\" },\n );\n }\n\n this.running = true;\n this.reader = createInterface({ input: process.stdin });\n\n this.reader.on(\"line\", (line) => {\n void this.onLine(line);\n });\n }\n\n /**\n * Parse one stdin line as a JSON-RPC request, dispatch it through the\n * handler, and write the response as a single line to stdout. Non-JSON\n * lines and notifications (no `id`) are ignored.\n */\n private async onLine(line: string): Promise<void> {\n const trimmed = line.trim();\n\n if (!trimmed) {\n return;\n }\n\n let request: JsonRpcRequest;\n\n try {\n request = JSON.parse(trimmed) as JsonRpcRequest;\n } catch {\n return;\n }\n\n if (request.id === undefined || request.id === null) {\n // A notification (e.g. notifications/initialized) — nothing to answer.\n return;\n }\n\n const response = await this.handler.handle(request);\n process.stdout.write(`${JSON.stringify(response)}\\n`);\n }\n\n public async stop(): Promise<void> {\n this.running = false;\n this.reader?.close();\n this.reader = undefined;\n }\n}\n\n/**\n * Expose a built agent / supervisor / orchestrator (or a raw\n * `ToolContract[]`) AS an MCP server (Direction B: local primitive → MCP\n * server other clients consume).\n *\n * Enumerates `source.tools()` (or the literal array) once at construction.\n * `tools/list` answers with each tool's `inputSchema` extracted via\n * `extractJsonSchema` at the configured `schemaTarget` (default\n * `draft-2020-12`). `tools/call` routes to the named contract's\n * `invoke()` and maps the never-throwing result — `data` becomes a text\n * content block, `error` becomes an `isError: true` result — so a failing\n * tool surfaces as a normal MCP tool error rather than crashing the server.\n *\n * The default transport is `stdio`, pumped over `process.stdin` /\n * `process.stdout`. Serving over HTTP is left to a host-owned server;\n * `start()` rejects an `http` transport (the protocol core is available\n * via {@link createServeHandler} for a caller's own HTTP wiring).\n *\n * @param source - The tools to expose.\n * @param options - Server name, version, transport, and schema dialect.\n * @returns An {@link McpServer} with `start()` / `stop()`.\n *\n * @example\n * serve(\n * { tools: () => ws.allTools() },\n * { name: \"warlock-workspace\", transport: { type: \"stdio\" } },\n * ).start();\n */\nexport function serve(source: McpServeSource, options: McpServeOptions): McpServer {\n return new McpServerImpl(source, options);\n}\n"],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import { McpTransport } from "../contracts/mcp.type.mjs";
2
+ import { McpTransportClient } from "./transport.type.mjs";
3
+
4
+ //#region ../@warlock.js/ai-tools/src/mcp/transport.d.ts
5
+ /**
6
+ * Build the concrete {@link McpTransportClient} for an {@link McpTransport}
7
+ * config — a {@link StdioTransport} for `type: "stdio"`, an
8
+ * {@link HttpTransport} for `type: "http"`. The returned client also
9
+ * carries an `allocateId()` for the JSON-RPC client to mint request ids.
10
+ *
11
+ * @param transport - The transport config (discriminated by `type`).
12
+ * @returns A transport client paired with its id allocator.
13
+ */
14
+ declare function createTransport(transport: McpTransport): McpTransportClient & {
15
+ allocateId(): number;
16
+ };
17
+ /**
18
+ * A JSON-RPC client over an MCP transport. Either pass an already-built
19
+ * transport client (tests inject a fake) or an {@link McpTransport} config
20
+ * to spawn/connect a real one.
21
+ */
22
+ interface JsonRpcClientHandle {
23
+ /** Issue a request and resolve with its `result` (throws on error). */
24
+ call<TResult = unknown>(method: string, params?: unknown, options?: {
25
+ signal?: AbortSignal;
26
+ timeoutMs?: number;
27
+ }): Promise<TResult>;
28
+ /** Send a one-way notification. */
29
+ notify(method: string, params?: unknown): Promise<void>;
30
+ /** Close the underlying transport. */
31
+ close(): Promise<void>;
32
+ }
33
+ /**
34
+ * Build a {@link JsonRpcClientHandle} over a transport. Accepts either a
35
+ * pre-built {@link McpTransportClient} (the test seam — inject a scripted
36
+ * fake) or an {@link McpTransport} config, in which case the concrete
37
+ * transport is constructed via {@link createTransport}.
38
+ *
39
+ * When a bare {@link McpTransportClient} (without an `allocateId`) is
40
+ * injected, the client supplies its own monotonic id source.
41
+ *
42
+ * @param source - A transport client or an `McpTransport` config.
43
+ * @returns A JSON-RPC client handle.
44
+ */
45
+ declare function createJsonRpcClient(source: McpTransport | McpTransportClient): JsonRpcClientHandle;
46
+ //#endregion
47
+ export { JsonRpcClientHandle, createJsonRpcClient, createTransport };
48
+ //# sourceMappingURL=transport.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai-tools/src/mcp/transport.ts"],"mappings":";;;;;;;AAicA;;;;;;iBAAgB,eAAA,CACd,SAAA,EAAW,YAAA,GACV,kBAAkB;EAAK,UAAA;AAAA;AAAU;AA8EpC;;;;AA9EoC,UA8EnB,mBAAA;EAMZ;EAJH,IAAA,oBACE,MAAA,UACA,MAAA,YACA,OAAA;IAAY,MAAA,GAAS,WAAA;IAAa,SAAA;EAAA,IACjC,OAAA,CAAQ,OAAA;EAJX;EAMA,MAAA,CAAO,MAAA,UAAgB,MAAA,aAAmB,OAAA;EALxC;EAOF,KAAA,IAAS,OAAA;AAAA;;;;;;;;;;;;;iBAeK,mBAAA,CACd,MAAA,EAAQ,YAAA,GAAe,kBAAA,GACtB,mBAAA"}