@matthesketh/utopia-ai 0.4.0 → 0.7.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.
@@ -20,12 +20,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/adapters/ollama.ts
21
21
  var ollama_exports = {};
22
22
  __export(ollama_exports, {
23
+ TRAILING_SLASH_RE: () => TRAILING_SLASH_RE,
23
24
  ollamaAdapter: () => ollamaAdapter
24
25
  });
25
26
  module.exports = __toCommonJS(ollama_exports);
27
+ var TRAILING_SLASH_RE = /\/$/;
26
28
  var ollamaToolCallCounter = 0;
27
29
  function ollamaAdapter(config = {}) {
28
- const baseURL = (config.baseURL ?? "http://localhost:11434").replace(/\/$/, "");
30
+ const baseURL = (config.baseURL ?? "http://localhost:11434").replace(TRAILING_SLASH_RE, "");
29
31
  return {
30
32
  async chat(request) {
31
33
  const model = request.model ?? config.defaultModel ?? "llama3.2";
@@ -194,5 +196,6 @@ function toOllamaTool(tool) {
194
196
  }
195
197
  // Annotate the CommonJS export names for ESM import in node:
196
198
  0 && (module.exports = {
199
+ TRAILING_SLASH_RE,
197
200
  ollamaAdapter
198
201
  });
@@ -1,5 +1,7 @@
1
1
  import { O as OllamaConfig, A as AIAdapter } from '../types-FSnS43LM.cjs';
2
2
 
3
+ /** Matches a trailing slash for URL normalization. */
4
+ declare const TRAILING_SLASH_RE: RegExp;
3
5
  /**
4
6
  * Create an Ollama adapter for local models.
5
7
  *
@@ -14,4 +16,4 @@ import { O as OllamaConfig, A as AIAdapter } from '../types-FSnS43LM.cjs';
14
16
  */
15
17
  declare function ollamaAdapter(config?: OllamaConfig): AIAdapter;
16
18
 
17
- export { ollamaAdapter };
19
+ export { TRAILING_SLASH_RE, ollamaAdapter };
@@ -1,5 +1,7 @@
1
1
  import { O as OllamaConfig, A as AIAdapter } from '../types-FSnS43LM.js';
2
2
 
3
+ /** Matches a trailing slash for URL normalization. */
4
+ declare const TRAILING_SLASH_RE: RegExp;
3
5
  /**
4
6
  * Create an Ollama adapter for local models.
5
7
  *
@@ -14,4 +16,4 @@ import { O as OllamaConfig, A as AIAdapter } from '../types-FSnS43LM.js';
14
16
  */
15
17
  declare function ollamaAdapter(config?: OllamaConfig): AIAdapter;
16
18
 
17
- export { ollamaAdapter };
19
+ export { TRAILING_SLASH_RE, ollamaAdapter };
@@ -1,7 +1,8 @@
1
1
  // src/adapters/ollama.ts
2
+ var TRAILING_SLASH_RE = /\/$/;
2
3
  var ollamaToolCallCounter = 0;
3
4
  function ollamaAdapter(config = {}) {
4
- const baseURL = (config.baseURL ?? "http://localhost:11434").replace(/\/$/, "");
5
+ const baseURL = (config.baseURL ?? "http://localhost:11434").replace(TRAILING_SLASH_RE, "");
5
6
  return {
6
7
  async chat(request) {
7
8
  const model = request.model ?? config.defaultModel ?? "llama3.2";
@@ -169,5 +170,6 @@ function toOllamaTool(tool) {
169
170
  };
170
171
  }
171
172
  export {
173
+ TRAILING_SLASH_RE,
172
174
  ollamaAdapter
173
175
  };
@@ -139,9 +139,11 @@ function createMCPServer(config) {
139
139
  }
140
140
  return { handleRequest, info: () => serverInfo };
141
141
  }
142
+ var REGEX_SPECIAL_CHARS_RE = /[.*+?^${}()|[\]\\]/g;
143
+ var TEMPLATE_PLACEHOLDER_RE = /\\\{[^\\}]+\\\}/g;
142
144
  function matchesTemplate(pattern, uri) {
143
- const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
144
- const regex = escaped.replace(/\\\{[^\\}]+\\\}/g, "([^/]+)");
145
+ const escaped = pattern.replace(REGEX_SPECIAL_CHARS_RE, "\\$&");
146
+ const regex = escaped.replace(TEMPLATE_PLACEHOLDER_RE, "([^/]+)");
145
147
  return new RegExp(`^${regex}$`).test(uri);
146
148
  }
147
149
  function makeError(code, message) {
@@ -236,9 +238,10 @@ function createMCPClient(config) {
236
238
  }
237
239
 
238
240
  // src/mcp/handler.ts
239
- function createMCPHandler(server) {
241
+ function createMCPHandler(server, options) {
242
+ const corsOrigin = options?.corsOrigin ?? "*";
240
243
  return async (req, res) => {
241
- res.setHeader("Access-Control-Allow-Origin", "*");
244
+ res.setHeader("Access-Control-Allow-Origin", corsOrigin);
242
245
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
243
246
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
244
247
  if (req.method === "OPTIONS") {
@@ -267,6 +270,7 @@ async function handlePost(server, req, res) {
267
270
  res.writeHead(200, { "Content-Type": "application/json" });
268
271
  res.end(JSON.stringify(response));
269
272
  } catch (err) {
273
+ const data = err instanceof SyntaxError ? err.message : "Invalid request";
270
274
  res.writeHead(400, { "Content-Type": "application/json" });
271
275
  res.end(
272
276
  JSON.stringify({
@@ -275,7 +279,7 @@ async function handlePost(server, req, res) {
275
279
  error: {
276
280
  code: -32700,
277
281
  message: "Parse error",
278
- data: err instanceof Error ? err.message : String(err)
282
+ data
279
283
  }
280
284
  })
281
285
  );
@@ -172,6 +172,9 @@ interface MCPClient {
172
172
  }
173
173
  declare function createMCPClient(config: MCPClientConfig): MCPClient;
174
174
 
175
+ interface MCPHandlerOptions {
176
+ corsOrigin?: string;
177
+ }
175
178
  /**
176
179
  * Create a Node.js HTTP handler for an MCP server.
177
180
  *
@@ -186,12 +189,12 @@ declare function createMCPClient(config: MCPClientConfig): MCPClient;
186
189
  * import { createMCPHandler } from '@matthesketh/utopia-ai/mcp';
187
190
  *
188
191
  * const mcp = createMCPServer({ name: 'my-app', tools: [...] });
189
- * const handler = createMCPHandler(mcp);
192
+ * const handler = createMCPHandler(mcp, { corsOrigin: 'https://example.com' });
190
193
  *
191
194
  * http.createServer(handler).listen(3001);
192
195
  * // or use as middleware: app.use('/mcp', handler);
193
196
  * ```
194
197
  */
195
- declare function createMCPHandler(server: MCPServer): (req: IncomingMessage, res: ServerResponse) => void;
198
+ declare function createMCPHandler(server: MCPServer, options?: MCPHandlerOptions): (req: IncomingMessage, res: ServerResponse) => void;
196
199
 
197
200
  export { type JsonRpcError, type JsonRpcNotification, type JsonRpcRequest, type JsonRpcResponse, type MCPClient, type MCPClientConfig, type MCPContent, type MCPPromptArgument, type MCPPromptDefinition, type MCPPromptHandler, type MCPPromptResult, type MCPResourceContent, type MCPResourceDefinition, type MCPResourceHandler, type MCPServer, type MCPServerConfig, type MCPServerInfo, type MCPToolDefinition, type MCPToolHandler, type MCPToolResult, createMCPClient, createMCPHandler, createMCPServer };
@@ -172,6 +172,9 @@ interface MCPClient {
172
172
  }
173
173
  declare function createMCPClient(config: MCPClientConfig): MCPClient;
174
174
 
175
+ interface MCPHandlerOptions {
176
+ corsOrigin?: string;
177
+ }
175
178
  /**
176
179
  * Create a Node.js HTTP handler for an MCP server.
177
180
  *
@@ -186,12 +189,12 @@ declare function createMCPClient(config: MCPClientConfig): MCPClient;
186
189
  * import { createMCPHandler } from '@matthesketh/utopia-ai/mcp';
187
190
  *
188
191
  * const mcp = createMCPServer({ name: 'my-app', tools: [...] });
189
- * const handler = createMCPHandler(mcp);
192
+ * const handler = createMCPHandler(mcp, { corsOrigin: 'https://example.com' });
190
193
  *
191
194
  * http.createServer(handler).listen(3001);
192
195
  * // or use as middleware: app.use('/mcp', handler);
193
196
  * ```
194
197
  */
195
- declare function createMCPHandler(server: MCPServer): (req: IncomingMessage, res: ServerResponse) => void;
198
+ declare function createMCPHandler(server: MCPServer, options?: MCPHandlerOptions): (req: IncomingMessage, res: ServerResponse) => void;
196
199
 
197
200
  export { type JsonRpcError, type JsonRpcNotification, type JsonRpcRequest, type JsonRpcResponse, type MCPClient, type MCPClientConfig, type MCPContent, type MCPPromptArgument, type MCPPromptDefinition, type MCPPromptHandler, type MCPPromptResult, type MCPResourceContent, type MCPResourceDefinition, type MCPResourceHandler, type MCPServer, type MCPServerConfig, type MCPServerInfo, type MCPToolDefinition, type MCPToolHandler, type MCPToolResult, createMCPClient, createMCPHandler, createMCPServer };
package/dist/mcp/index.js CHANGED
@@ -111,9 +111,11 @@ function createMCPServer(config) {
111
111
  }
112
112
  return { handleRequest, info: () => serverInfo };
113
113
  }
114
+ var REGEX_SPECIAL_CHARS_RE = /[.*+?^${}()|[\]\\]/g;
115
+ var TEMPLATE_PLACEHOLDER_RE = /\\\{[^\\}]+\\\}/g;
114
116
  function matchesTemplate(pattern, uri) {
115
- const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
116
- const regex = escaped.replace(/\\\{[^\\}]+\\\}/g, "([^/]+)");
117
+ const escaped = pattern.replace(REGEX_SPECIAL_CHARS_RE, "\\$&");
118
+ const regex = escaped.replace(TEMPLATE_PLACEHOLDER_RE, "([^/]+)");
117
119
  return new RegExp(`^${regex}$`).test(uri);
118
120
  }
119
121
  function makeError(code, message) {
@@ -208,9 +210,10 @@ function createMCPClient(config) {
208
210
  }
209
211
 
210
212
  // src/mcp/handler.ts
211
- function createMCPHandler(server) {
213
+ function createMCPHandler(server, options) {
214
+ const corsOrigin = options?.corsOrigin ?? "*";
212
215
  return async (req, res) => {
213
- res.setHeader("Access-Control-Allow-Origin", "*");
216
+ res.setHeader("Access-Control-Allow-Origin", corsOrigin);
214
217
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
215
218
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
216
219
  if (req.method === "OPTIONS") {
@@ -239,6 +242,7 @@ async function handlePost(server, req, res) {
239
242
  res.writeHead(200, { "Content-Type": "application/json" });
240
243
  res.end(JSON.stringify(response));
241
244
  } catch (err) {
245
+ const data = err instanceof SyntaxError ? err.message : "Invalid request";
242
246
  res.writeHead(400, { "Content-Type": "application/json" });
243
247
  res.end(
244
248
  JSON.stringify({
@@ -247,7 +251,7 @@ async function handlePost(server, req, res) {
247
251
  error: {
248
252
  code: -32700,
249
253
  message: "Parse error",
250
- data: err instanceof Error ? err.message : String(err)
254
+ data
251
255
  }
252
256
  })
253
257
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matthesketh/utopia-ai",
3
- "version": "0.4.0",
3
+ "version": "0.7.0",
4
4
  "description": "AI adapters and MCP support for UtopiaJS",
5
5
  "type": "module",
6
6
  "license": "MIT",