@exulu/backend 1.29.0 → 1.30.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
- # [1.29.0](https://github.com/Qventu/exulu-backend/compare/v1.28.2...v1.29.0) (2025-10-28)
1
+ ## [1.30.1](https://github.com/Qventu/exulu-backend/compare/v1.30.0...v1.30.1) (2025-11-04)
2
2
 
3
3
 
4
- ### Features
4
+ ### Bug Fixes
5
5
 
6
- * add agent animations, math tools, and improve file handling ([d335a7e](https://github.com/Qventu/exulu-backend/commit/d335a7e6c8454490d971ec63dc8486fcd60ef59b))
6
+ * dont add eval tools if redis not configured ([4ebbb5c](https://github.com/Qventu/exulu-backend/commit/4ebbb5ce44aaf07072adaf6b6963e6eac376e022))
package/dist/index.cjs CHANGED
@@ -437,7 +437,8 @@ var sanitizeName = (name) => {
437
437
 
438
438
  // src/registry/classes.ts
439
439
  var import_crypto_js2 = __toESM(require("crypto-js"), 1);
440
- var import_express2 = require("express");
440
+ var import_streamableHttp = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
441
+ var import_mcp_stdio = require("ai/mcp-stdio");
441
442
 
442
443
  // src/registry/utils/graphql.ts
443
444
  var import_schema = require("@graphql-tools/schema");
@@ -2428,7 +2429,7 @@ var applyAccessControl = (table, user, query) => {
2428
2429
  console.log("[EXULU] table.name.plural", table.name.plural);
2429
2430
  if (!user.super_admin && (!user.role || !(table.name.plural === "agents" && (user.role.agents === "read" || user.role.agents === "write")) && !(table.name.plural === "workflow_templates" && (user.role.workflows === "read" || user.role.workflows === "write")) && !(table.name.plural === "variables" && (user.role.variables === "read" || user.role.variables === "write")) && !(table.name.plural === "users" && (user.role.users === "read" || user.role.users === "write")) && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (user.role.evals === "read" || user.role.evals === "write")))) {
2430
2431
  console.error("==== Access control error: no role found or no access to entity type. ====");
2431
- return query.where("id", "=", "0");
2432
+ throw new Error("Access control error: no role found or no access to entity type.");
2432
2433
  }
2433
2434
  const hasRBAC = table.RBAC === true;
2434
2435
  console.log("[EXULU] hasRBAC", hasRBAC);
@@ -2532,11 +2533,14 @@ var addAgentFields = async (requestedFields, agents, result, tools, user) => {
2532
2533
  } else {
2533
2534
  hydrated = tools.find((t) => t.id === tool2.id);
2534
2535
  }
2535
- return {
2536
+ const hydratedTool = {
2536
2537
  ...tool2,
2537
2538
  name: hydrated?.name || "",
2538
- description: hydrated?.description || ""
2539
+ description: hydrated?.description || "",
2540
+ category: tool2?.category || "default"
2539
2541
  };
2542
+ console.log("[EXULU] hydratedTool", hydratedTool);
2543
+ return hydratedTool;
2540
2544
  }));
2541
2545
  result.tools = result.tools.filter((tool2) => tool2 !== null);
2542
2546
  } else {
@@ -3480,7 +3484,8 @@ type PageInfo {
3480
3484
  deleteJob(queue: QueueEnum!, id: String!): JobActionReturnPayload
3481
3485
  `;
3482
3486
  typeDefs += `
3483
- tools: ToolPaginationResult
3487
+ tools(search: String, category: String, limit: Int, page: Int): ToolPaginationResult
3488
+ toolCategories: [String!]!
3484
3489
  `;
3485
3490
  typeDefs += `
3486
3491
  jobs(queue: QueueEnum!, statusses: [JobStateEnum!]): JobPaginationResult
@@ -3800,6 +3805,7 @@ type PageInfo {
3800
3805
  };
3801
3806
  resolvers.Query["tools"] = async (_, args, context, info) => {
3802
3807
  const requestedFields = getRequestedFields(info);
3808
+ const { search, category, limit = 100, page = 0 } = args;
3803
3809
  const instances = await loadAgents();
3804
3810
  let agentTools = await Promise.all(
3805
3811
  instances.map(async (instance) => {
@@ -3811,16 +3817,39 @@ type PageInfo {
3811
3817
  })
3812
3818
  );
3813
3819
  const filtered = agentTools.filter((tool2) => tool2 !== null);
3820
+ let allTools = [...filtered, ...tools];
3821
+ if (search && search.trim()) {
3822
+ const searchTerm = search.toLowerCase().trim();
3823
+ allTools = allTools.filter(
3824
+ (tool2) => tool2.name?.toLowerCase().includes(searchTerm) || tool2.description?.toLowerCase().includes(searchTerm)
3825
+ );
3826
+ }
3827
+ if (category && category.trim()) {
3828
+ allTools = allTools.filter((tool2) => tool2.category === category);
3829
+ }
3830
+ const total = allTools.length;
3831
+ const start = page * limit;
3832
+ const end = start + limit;
3833
+ const paginatedTools = allTools.slice(start, end);
3814
3834
  return {
3815
- items: [...filtered, ...tools].map((tool2) => {
3835
+ items: paginatedTools.map((tool2) => {
3816
3836
  const object = {};
3817
3837
  requestedFields.forEach((field) => {
3818
3838
  object[field] = tool2[field];
3819
3839
  });
3820
3840
  return object;
3821
- })
3841
+ }),
3842
+ total,
3843
+ page,
3844
+ limit
3822
3845
  };
3823
3846
  };
3847
+ resolvers.Query["toolCategories"] = async () => {
3848
+ const array = tools.map((tool2) => tool2.category).filter((category) => category && typeof category === "string");
3849
+ array.push("contexts");
3850
+ array.push("agents");
3851
+ return [...new Set(array)].sort();
3852
+ };
3824
3853
  modelDefs += `
3825
3854
  type ProviderPaginationResult {
3826
3855
  items: [Provider]!
@@ -3859,6 +3888,9 @@ type PageInfo {
3859
3888
  modelDefs += `
3860
3889
  type ToolPaginationResult {
3861
3890
  items: [Tool]!
3891
+ total: Int!
3892
+ page: Int!
3893
+ limit: Int!
3862
3894
  }
3863
3895
  `;
3864
3896
  modelDefs += `
@@ -3968,6 +4000,7 @@ type Tool {
3968
4000
  id: ID!
3969
4001
  name: String!
3970
4002
  description: String
4003
+ category: String
3971
4004
  type: String
3972
4005
  config: JSON
3973
4006
  }
@@ -4599,6 +4632,7 @@ var createUppyRoutes = async (app, config) => {
4599
4632
  };
4600
4633
 
4601
4634
  // src/registry/classes.ts
4635
+ var import_streamableHttp2 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
4602
4636
  var s3Client2;
4603
4637
  function sanitizeToolName(name) {
4604
4638
  if (typeof name !== "string") return "";
@@ -4617,12 +4651,6 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
4617
4651
  name: sanitizeToolName(tool2.name)
4618
4652
  })) : [];
4619
4653
  console.log("[EXULU] Sanitized tools", sanitizedTools.map((x) => x.name + " (" + x.id + ")"));
4620
- const askForConfirmation = {
4621
- description: "Ask the user for confirmation.",
4622
- inputSchema: import_zod.z.object({
4623
- message: import_zod.z.string().describe("The message to ask for confirmation.")
4624
- })
4625
- };
4626
4654
  return {
4627
4655
  ...sanitizedTools?.reduce(
4628
4656
  (prev, cur) => ({
@@ -4721,8 +4749,8 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
4721
4749
  }
4722
4750
  }),
4723
4751
  {}
4724
- ),
4725
- askForConfirmation
4752
+ )
4753
+ // askForConfirmation
4726
4754
  };
4727
4755
  };
4728
4756
  var hydrateVariables = async (tool2) => {
@@ -4856,6 +4884,7 @@ var ExuluAgent2 = class {
4856
4884
  id: agentInstance.id,
4857
4885
  name: `${agentInstance.name}`,
4858
4886
  type: "agent",
4887
+ category: "agents",
4859
4888
  inputSchema: import_zod.z.object({
4860
4889
  prompt: import_zod.z.string().describe("The prompt (usually a question for the agent) to send to the agent."),
4861
4890
  information: import_zod.z.string().describe("A summary of relevant context / information from the current session")
@@ -5284,13 +5313,15 @@ var ExuluTool2 = class {
5284
5313
  id;
5285
5314
  name;
5286
5315
  description;
5316
+ category;
5287
5317
  inputSchema;
5288
5318
  type;
5289
5319
  tool;
5290
5320
  config;
5291
- constructor({ id, name, description, inputSchema, type, execute: execute2, config }) {
5321
+ constructor({ id, name, description, category, inputSchema, type, execute: execute2, config }) {
5292
5322
  this.id = id;
5293
5323
  this.config = config;
5324
+ this.category = category || "default";
5294
5325
  this.name = name;
5295
5326
  this.description = description;
5296
5327
  this.inputSchema = inputSchema;
@@ -5719,6 +5750,7 @@ var ExuluContext = class {
5719
5750
  id: this.id,
5720
5751
  name: `${this.name}`,
5721
5752
  type: "context",
5753
+ category: "contexts",
5722
5754
  inputSchema: import_zod.z.object({
5723
5755
  query: import_zod.z.string()
5724
5756
  }),
@@ -5756,7 +5788,6 @@ var ExuluContext = class {
5756
5788
  };
5757
5789
  };
5758
5790
  var updateStatistic = async (statistic) => {
5759
- console.log("[EXULU] Updating statistic", statistic);
5760
5791
  const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
5761
5792
  const { db: db3 } = await postgresClient();
5762
5793
  const existing = await db3.from("tracking").where({
@@ -5767,7 +5798,6 @@ var updateStatistic = async (statistic) => {
5767
5798
  type: statistic.type,
5768
5799
  createdAt: currentDate
5769
5800
  }).first();
5770
- console.log("[EXULU] Existing", existing);
5771
5801
  if (!existing) {
5772
5802
  await db3.from("tracking").insert({
5773
5803
  name: statistic.name,
@@ -5838,11 +5868,11 @@ var getMimeType = (type) => {
5838
5868
  };
5839
5869
 
5840
5870
  // src/registry/index.ts
5841
- var import_express7 = require("express");
5871
+ var import_express6 = require("express");
5842
5872
 
5843
5873
  // src/registry/routes.ts
5844
- var import_express3 = require("express");
5845
- var import_express4 = __toESM(require("express"), 1);
5874
+ var import_express2 = require("express");
5875
+ var import_express3 = __toESM(require("express"), 1);
5846
5876
  var import_server2 = require("@apollo/server");
5847
5877
  var import_cors = __toESM(require("cors"), 1);
5848
5878
  var import_reflect_metadata = require("reflect-metadata");
@@ -5909,7 +5939,7 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, evals, tr
5909
5939
  optionsSuccessStatus: 200
5910
5940
  // some legacy browsers (IE11, various SmartTVs) choke on 204
5911
5941
  };
5912
- app.use(import_express4.default.json({ limit: REQUEST_SIZE_LIMIT }));
5942
+ app.use(import_express3.default.json({ limit: REQUEST_SIZE_LIMIT }));
5913
5943
  app.use((0, import_cors.default)(corsOptions));
5914
5944
  app.use(import_body_parser.default.urlencoded({ extended: true, limit: REQUEST_SIZE_LIMIT }));
5915
5945
  app.use(import_body_parser.default.json({ limit: REQUEST_SIZE_LIMIT }));
@@ -5949,7 +5979,7 @@ var createExpressRoutes = async (app, agents, tools, contexts, config, evals, tr
5949
5979
  app.use(
5950
5980
  "/graphql",
5951
5981
  (0, import_cors.default)(corsOptions),
5952
- import_express4.default.json({ limit: REQUEST_SIZE_LIMIT }),
5982
+ import_express3.default.json({ limit: REQUEST_SIZE_LIMIT }),
5953
5983
  (0, import_express5.expressMiddleware)(server, {
5954
5984
  context: async ({ req }) => {
5955
5985
  console.info("[EXULU] Incoming graphql request", {
@@ -6325,7 +6355,7 @@ Mood: friendly and intelligent.
6325
6355
  }
6326
6356
  });
6327
6357
  });
6328
- app.use("/gateway/anthropic/:id", import_express4.default.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
6358
+ app.use("/gateway/anthropic/:id", import_express3.default.raw({ type: "*/*", limit: REQUEST_SIZE_LIMIT }), async (req, res) => {
6329
6359
  try {
6330
6360
  if (!req.body.tools) {
6331
6361
  req.body.tools = [];
@@ -6466,7 +6496,7 @@ data: ${JSON.stringify(event)}
6466
6496
  }
6467
6497
  }
6468
6498
  });
6469
- app.use(import_express4.default.static("public"));
6499
+ app.use(import_express3.default.static("public"));
6470
6500
  return app;
6471
6501
  };
6472
6502
  var createCustomAnthropicStreamingMessage = (message) => {
@@ -7168,10 +7198,10 @@ function getAverage(arr) {
7168
7198
  // src/mcp/index.ts
7169
7199
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
7170
7200
  var import_node_crypto4 = require("crypto");
7171
- var import_streamableHttp = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
7201
+ var import_streamableHttp3 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
7172
7202
  var import_types = require("@modelcontextprotocol/sdk/types.js");
7173
7203
  var import_zod2 = require("zod");
7174
- var import_express6 = require("express");
7204
+ var import_express4 = require("express");
7175
7205
  var import_api3 = require("@opentelemetry/api");
7176
7206
  var SESSION_ID_HEADER = "mcp-session-id";
7177
7207
  var ExuluMCP = class {
@@ -7258,7 +7288,7 @@ ${code}`
7258
7288
  if (sessionId && this.transports[sessionId]) {
7259
7289
  transport = this.transports[sessionId];
7260
7290
  } else if (!sessionId && (0, import_types.isInitializeRequest)(req.body)) {
7261
- transport = new import_streamableHttp.StreamableHTTPServerTransport({
7291
+ transport = new import_streamableHttp3.StreamableHTTPServerTransport({
7262
7292
  sessionIdGenerator: () => (0, import_node_crypto4.randomUUID)(),
7263
7293
  onsessioninitialized: (sessionId2) => {
7264
7294
  this.transports[sessionId2] = transport;
@@ -7299,7 +7329,7 @@ ${code}`
7299
7329
  };
7300
7330
 
7301
7331
  // src/registry/index.ts
7302
- var import_express8 = __toESM(require("express"), 1);
7332
+ var import_express7 = __toESM(require("express"), 1);
7303
7333
 
7304
7334
  // src/templates/agents/anthropic/claude.ts
7305
7335
  var import_anthropic = require("@ai-sdk/anthropic");
@@ -8104,6 +8134,7 @@ var additionTool = new ExuluTool2({
8104
8134
  name: "Addition",
8105
8135
  description: "Adds two numbers together",
8106
8136
  type: "function",
8137
+ category: "math",
8107
8138
  config: [],
8108
8139
  inputSchema: import_zod4.z.object({
8109
8140
  firstNumber: import_zod4.z.number().describe("The first addend"),
@@ -8119,6 +8150,7 @@ var subtractionTool = new ExuluTool2({
8119
8150
  name: "Subtraction",
8120
8151
  description: "Subtracts the second number from the first number",
8121
8152
  type: "function",
8153
+ category: "math",
8122
8154
  config: [],
8123
8155
  inputSchema: import_zod4.z.object({
8124
8156
  minuend: import_zod4.z.number().describe("The number to subtract from (minuend)"),
@@ -8134,6 +8166,7 @@ var multiplicationTool = new ExuluTool2({
8134
8166
  name: "Multiplication",
8135
8167
  description: "Multiplies two numbers together",
8136
8168
  type: "function",
8169
+ category: "math",
8137
8170
  config: [],
8138
8171
  inputSchema: import_zod4.z.object({
8139
8172
  firstNumber: import_zod4.z.number().describe("The first number"),
@@ -8149,6 +8182,7 @@ var divisionTool = new ExuluTool2({
8149
8182
  name: "Division",
8150
8183
  description: "Divides the first number by the second number",
8151
8184
  type: "function",
8185
+ category: "math",
8152
8186
  config: [],
8153
8187
  inputSchema: import_zod4.z.object({
8154
8188
  numerator: import_zod4.z.number().describe("The number being divided (numerator)"),
@@ -8164,6 +8198,7 @@ var sumTool = new ExuluTool2({
8164
8198
  name: "Sum",
8165
8199
  description: "Adds any number of numbers together",
8166
8200
  type: "function",
8201
+ category: "math",
8167
8202
  config: [],
8168
8203
  inputSchema: import_zod4.z.object({
8169
8204
  numbers: import_zod4.z.array(import_zod4.z.number()).min(1).describe("Array of numbers to sum")
@@ -8178,6 +8213,7 @@ var moduloTool = new ExuluTool2({
8178
8213
  name: "Modulo",
8179
8214
  description: "Divides two numbers and returns the remainder",
8180
8215
  type: "function",
8216
+ category: "math",
8181
8217
  config: [],
8182
8218
  inputSchema: import_zod4.z.object({
8183
8219
  numerator: import_zod4.z.number().describe("The number being divided (numerator)"),
@@ -8193,6 +8229,7 @@ var meanTool = new ExuluTool2({
8193
8229
  name: "Mean",
8194
8230
  description: "Calculates the arithmetic mean of a list of numbers",
8195
8231
  type: "function",
8232
+ category: "math",
8196
8233
  config: [],
8197
8234
  inputSchema: import_zod4.z.object({
8198
8235
  numbers: import_zod4.z.array(import_zod4.z.number()).min(1).describe("Array of numbers to find the mean of")
@@ -8207,6 +8244,7 @@ var medianTool = new ExuluTool2({
8207
8244
  name: "Median",
8208
8245
  description: "Calculates the median of a list of numbers",
8209
8246
  type: "function",
8247
+ category: "math",
8210
8248
  config: [],
8211
8249
  inputSchema: import_zod4.z.object({
8212
8250
  numbers: import_zod4.z.array(import_zod4.z.number()).min(1).describe("Array of numbers to find the median of")
@@ -8221,6 +8259,7 @@ var modeTool = new ExuluTool2({
8221
8259
  name: "Mode",
8222
8260
  description: "Finds the most common number in a list of numbers",
8223
8261
  type: "function",
8262
+ category: "math",
8224
8263
  config: [],
8225
8264
  inputSchema: import_zod4.z.object({
8226
8265
  numbers: import_zod4.z.array(import_zod4.z.number()).describe("Array of numbers to find the mode of")
@@ -8235,6 +8274,7 @@ var minTool = new ExuluTool2({
8235
8274
  name: "Minimum",
8236
8275
  description: "Finds the minimum value from a list of numbers",
8237
8276
  type: "function",
8277
+ category: "math",
8238
8278
  config: [],
8239
8279
  inputSchema: import_zod4.z.object({
8240
8280
  numbers: import_zod4.z.array(import_zod4.z.number()).describe("Array of numbers to find the minimum of")
@@ -8249,6 +8289,7 @@ var maxTool = new ExuluTool2({
8249
8289
  name: "Maximum",
8250
8290
  description: "Finds the maximum value from a list of numbers",
8251
8291
  type: "function",
8292
+ category: "math",
8252
8293
  config: [],
8253
8294
  inputSchema: import_zod4.z.object({
8254
8295
  numbers: import_zod4.z.array(import_zod4.z.number()).describe("Array of numbers to find the maximum of")
@@ -8263,6 +8304,7 @@ var floorTool = new ExuluTool2({
8263
8304
  name: "Floor",
8264
8305
  description: "Rounds a number down to the nearest integer",
8265
8306
  type: "function",
8307
+ category: "math",
8266
8308
  config: [],
8267
8309
  inputSchema: import_zod4.z.object({
8268
8310
  number: import_zod4.z.number().describe("The number to round down")
@@ -8277,6 +8319,7 @@ var ceilingTool = new ExuluTool2({
8277
8319
  name: "Ceiling",
8278
8320
  description: "Rounds a number up to the nearest integer",
8279
8321
  type: "function",
8322
+ category: "math",
8280
8323
  config: [],
8281
8324
  inputSchema: import_zod4.z.object({
8282
8325
  number: import_zod4.z.number().describe("The number to round up")
@@ -8291,6 +8334,7 @@ var roundTool = new ExuluTool2({
8291
8334
  name: "Round",
8292
8335
  description: "Rounds a number to the nearest integer",
8293
8336
  type: "function",
8337
+ category: "math",
8294
8338
  config: [],
8295
8339
  inputSchema: import_zod4.z.object({
8296
8340
  number: import_zod4.z.number().describe("The number to round")
@@ -8305,6 +8349,7 @@ var sinTool = new ExuluTool2({
8305
8349
  name: "Sine",
8306
8350
  description: "Calculates the sine of a number in radians",
8307
8351
  type: "function",
8352
+ category: "math",
8308
8353
  config: [],
8309
8354
  inputSchema: import_zod4.z.object({
8310
8355
  number: import_zod4.z.number().describe("The number in radians to find the sine of")
@@ -8319,6 +8364,7 @@ var arcsinTool = new ExuluTool2({
8319
8364
  name: "Arcsine",
8320
8365
  description: "Calculates the arcsine of a number in radians",
8321
8366
  type: "function",
8367
+ category: "math",
8322
8368
  config: [],
8323
8369
  inputSchema: import_zod4.z.object({
8324
8370
  number: import_zod4.z.number().describe("The number to find the arcsine of")
@@ -8333,6 +8379,7 @@ var cosTool = new ExuluTool2({
8333
8379
  name: "Cosine",
8334
8380
  description: "Calculates the cosine of a number in radians",
8335
8381
  type: "function",
8382
+ category: "math",
8336
8383
  config: [],
8337
8384
  inputSchema: import_zod4.z.object({
8338
8385
  number: import_zod4.z.number().describe("The number in radians to find the cosine of")
@@ -8347,6 +8394,7 @@ var arccosTool = new ExuluTool2({
8347
8394
  name: "Arccosine",
8348
8395
  description: "Calculates the arccosine of a number in radians",
8349
8396
  type: "function",
8397
+ category: "math",
8350
8398
  config: [],
8351
8399
  inputSchema: import_zod4.z.object({
8352
8400
  number: import_zod4.z.number().describe("The number to find the arccosine of")
@@ -8361,6 +8409,7 @@ var tanTool = new ExuluTool2({
8361
8409
  name: "Tangent",
8362
8410
  description: "Calculates the tangent of a number in radians",
8363
8411
  type: "function",
8412
+ category: "math",
8364
8413
  config: [],
8365
8414
  inputSchema: import_zod4.z.object({
8366
8415
  number: import_zod4.z.number().describe("The number in radians to find the tangent of")
@@ -8375,6 +8424,7 @@ var arctanTool = new ExuluTool2({
8375
8424
  name: "Arctangent",
8376
8425
  description: "Calculates the arctangent of a number in radians",
8377
8426
  type: "function",
8427
+ category: "math",
8378
8428
  config: [],
8379
8429
  inputSchema: import_zod4.z.object({
8380
8430
  number: import_zod4.z.number().describe("The number to find the arctangent of")
@@ -8389,6 +8439,7 @@ var radiansToDegreesTool = new ExuluTool2({
8389
8439
  name: "Radians to Degrees",
8390
8440
  description: "Converts a radian value to its equivalent in degrees",
8391
8441
  type: "function",
8442
+ category: "math",
8392
8443
  config: [],
8393
8444
  inputSchema: import_zod4.z.object({
8394
8445
  number: import_zod4.z.number().describe("The number in radians to convert to degrees")
@@ -8403,6 +8454,7 @@ var degreesToRadiansTool = new ExuluTool2({
8403
8454
  name: "Degrees to Radians",
8404
8455
  description: "Converts a degree value to its equivalent in radians",
8405
8456
  type: "function",
8457
+ category: "math",
8406
8458
  config: [],
8407
8459
  inputSchema: import_zod4.z.object({
8408
8460
  number: import_zod4.z.number().describe("The number in degrees to convert to radians")
@@ -8481,10 +8533,10 @@ var ExuluApp = class {
8481
8533
  // Factory function so we can async
8482
8534
  // initialize the MCP server if needed.
8483
8535
  create = async ({ contexts, agents, config, tools, evals }) => {
8484
- this._evals = [
8536
+ this._evals = redisServer.host?.length && redisServer.port?.length ? [
8485
8537
  llmAsJudgeEval,
8486
8538
  ...evals ?? []
8487
- ];
8539
+ ] : [];
8488
8540
  this._contexts = {
8489
8541
  ...contexts,
8490
8542
  codeStandardsContext,
@@ -8514,6 +8566,7 @@ var ExuluApp = class {
8514
8566
  // Because agents are stored in the database, we add those as tools
8515
8567
  // at request time, not during ExuluApp initialization. We add them
8516
8568
  // in the grahql tools resolver.
8569
+ // ...mcpTools
8517
8570
  ];
8518
8571
  const checks = [
8519
8572
  ...Object.keys(this._contexts || {}).map((x) => ({
@@ -8552,7 +8605,7 @@ var ExuluApp = class {
8552
8605
  express = {
8553
8606
  init: async () => {
8554
8607
  if (!this._expressApp) {
8555
- this._expressApp = (0, import_express8.default)();
8608
+ this._expressApp = (0, import_express7.default)();
8556
8609
  await this.server.express.init();
8557
8610
  console.log("[EXULU] Express app initialized.");
8558
8611
  }
package/dist/index.d.cts CHANGED
@@ -469,6 +469,7 @@ declare class ExuluTool {
469
469
  id: string;
470
470
  name: string;
471
471
  description: string;
472
+ category: string;
472
473
  inputSchema?: z.ZodType;
473
474
  type: "context" | "function" | "agent";
474
475
  tool: Tool;
@@ -476,10 +477,11 @@ declare class ExuluTool {
476
477
  name: string;
477
478
  description: string;
478
479
  }[];
479
- constructor({ id, name, description, inputSchema, type, execute, config }: {
480
+ constructor({ id, name, description, category, inputSchema, type, execute, config }: {
480
481
  id: string;
481
482
  name: string;
482
483
  description: string;
484
+ category?: string;
483
485
  inputSchema?: z.ZodType;
484
486
  type: "context" | "function" | "agent";
485
487
  config: {
@@ -563,6 +565,7 @@ declare class ExuluContext {
563
565
  fields: ExuluContextFieldDefinition[];
564
566
  description: string;
565
567
  embedder?: ExuluEmbedder;
568
+ category?: string;
566
569
  active: boolean;
567
570
  rateLimit?: RateLimiterRule;
568
571
  queryRewriter?: (query: string) => Promise<string>;
package/dist/index.d.ts CHANGED
@@ -469,6 +469,7 @@ declare class ExuluTool {
469
469
  id: string;
470
470
  name: string;
471
471
  description: string;
472
+ category: string;
472
473
  inputSchema?: z.ZodType;
473
474
  type: "context" | "function" | "agent";
474
475
  tool: Tool;
@@ -476,10 +477,11 @@ declare class ExuluTool {
476
477
  name: string;
477
478
  description: string;
478
479
  }[];
479
- constructor({ id, name, description, inputSchema, type, execute, config }: {
480
+ constructor({ id, name, description, category, inputSchema, type, execute, config }: {
480
481
  id: string;
481
482
  name: string;
482
483
  description: string;
484
+ category?: string;
483
485
  inputSchema?: z.ZodType;
484
486
  type: "context" | "function" | "agent";
485
487
  config: {
@@ -563,6 +565,7 @@ declare class ExuluContext {
563
565
  fields: ExuluContextFieldDefinition[];
564
566
  description: string;
565
567
  embedder?: ExuluEmbedder;
568
+ category?: string;
566
569
  active: boolean;
567
570
  rateLimit?: RateLimiterRule;
568
571
  queryRewriter?: (query: string) => Promise<string>;
package/dist/index.js CHANGED
@@ -385,7 +385,8 @@ var sanitizeName = (name) => {
385
385
 
386
386
  // src/registry/classes.ts
387
387
  import CryptoJS2 from "crypto-js";
388
- import "express";
388
+ import "@modelcontextprotocol/sdk/client/streamableHttp.js";
389
+ import "ai/mcp-stdio";
389
390
 
390
391
  // src/registry/utils/graphql.ts
391
392
  import { makeExecutableSchema } from "@graphql-tools/schema";
@@ -2376,7 +2377,7 @@ var applyAccessControl = (table, user, query) => {
2376
2377
  console.log("[EXULU] table.name.plural", table.name.plural);
2377
2378
  if (!user.super_admin && (!user.role || !(table.name.plural === "agents" && (user.role.agents === "read" || user.role.agents === "write")) && !(table.name.plural === "workflow_templates" && (user.role.workflows === "read" || user.role.workflows === "write")) && !(table.name.plural === "variables" && (user.role.variables === "read" || user.role.variables === "write")) && !(table.name.plural === "users" && (user.role.users === "read" || user.role.users === "write")) && !((table.name.plural === "test_cases" || table.name.plural === "eval_sets" || table.name.plural === "eval_runs") && (user.role.evals === "read" || user.role.evals === "write")))) {
2378
2379
  console.error("==== Access control error: no role found or no access to entity type. ====");
2379
- return query.where("id", "=", "0");
2380
+ throw new Error("Access control error: no role found or no access to entity type.");
2380
2381
  }
2381
2382
  const hasRBAC = table.RBAC === true;
2382
2383
  console.log("[EXULU] hasRBAC", hasRBAC);
@@ -2480,11 +2481,14 @@ var addAgentFields = async (requestedFields, agents, result, tools, user) => {
2480
2481
  } else {
2481
2482
  hydrated = tools.find((t) => t.id === tool2.id);
2482
2483
  }
2483
- return {
2484
+ const hydratedTool = {
2484
2485
  ...tool2,
2485
2486
  name: hydrated?.name || "",
2486
- description: hydrated?.description || ""
2487
+ description: hydrated?.description || "",
2488
+ category: tool2?.category || "default"
2487
2489
  };
2490
+ console.log("[EXULU] hydratedTool", hydratedTool);
2491
+ return hydratedTool;
2488
2492
  }));
2489
2493
  result.tools = result.tools.filter((tool2) => tool2 !== null);
2490
2494
  } else {
@@ -3428,7 +3432,8 @@ type PageInfo {
3428
3432
  deleteJob(queue: QueueEnum!, id: String!): JobActionReturnPayload
3429
3433
  `;
3430
3434
  typeDefs += `
3431
- tools: ToolPaginationResult
3435
+ tools(search: String, category: String, limit: Int, page: Int): ToolPaginationResult
3436
+ toolCategories: [String!]!
3432
3437
  `;
3433
3438
  typeDefs += `
3434
3439
  jobs(queue: QueueEnum!, statusses: [JobStateEnum!]): JobPaginationResult
@@ -3748,6 +3753,7 @@ type PageInfo {
3748
3753
  };
3749
3754
  resolvers.Query["tools"] = async (_, args, context, info) => {
3750
3755
  const requestedFields = getRequestedFields(info);
3756
+ const { search, category, limit = 100, page = 0 } = args;
3751
3757
  const instances = await loadAgents();
3752
3758
  let agentTools = await Promise.all(
3753
3759
  instances.map(async (instance) => {
@@ -3759,16 +3765,39 @@ type PageInfo {
3759
3765
  })
3760
3766
  );
3761
3767
  const filtered = agentTools.filter((tool2) => tool2 !== null);
3768
+ let allTools = [...filtered, ...tools];
3769
+ if (search && search.trim()) {
3770
+ const searchTerm = search.toLowerCase().trim();
3771
+ allTools = allTools.filter(
3772
+ (tool2) => tool2.name?.toLowerCase().includes(searchTerm) || tool2.description?.toLowerCase().includes(searchTerm)
3773
+ );
3774
+ }
3775
+ if (category && category.trim()) {
3776
+ allTools = allTools.filter((tool2) => tool2.category === category);
3777
+ }
3778
+ const total = allTools.length;
3779
+ const start = page * limit;
3780
+ const end = start + limit;
3781
+ const paginatedTools = allTools.slice(start, end);
3762
3782
  return {
3763
- items: [...filtered, ...tools].map((tool2) => {
3783
+ items: paginatedTools.map((tool2) => {
3764
3784
  const object = {};
3765
3785
  requestedFields.forEach((field) => {
3766
3786
  object[field] = tool2[field];
3767
3787
  });
3768
3788
  return object;
3769
- })
3789
+ }),
3790
+ total,
3791
+ page,
3792
+ limit
3770
3793
  };
3771
3794
  };
3795
+ resolvers.Query["toolCategories"] = async () => {
3796
+ const array = tools.map((tool2) => tool2.category).filter((category) => category && typeof category === "string");
3797
+ array.push("contexts");
3798
+ array.push("agents");
3799
+ return [...new Set(array)].sort();
3800
+ };
3772
3801
  modelDefs += `
3773
3802
  type ProviderPaginationResult {
3774
3803
  items: [Provider]!
@@ -3807,6 +3836,9 @@ type PageInfo {
3807
3836
  modelDefs += `
3808
3837
  type ToolPaginationResult {
3809
3838
  items: [Tool]!
3839
+ total: Int!
3840
+ page: Int!
3841
+ limit: Int!
3810
3842
  }
3811
3843
  `;
3812
3844
  modelDefs += `
@@ -3916,6 +3948,7 @@ type Tool {
3916
3948
  id: ID!
3917
3949
  name: String!
3918
3950
  description: String
3951
+ category: String
3919
3952
  type: String
3920
3953
  config: JSON
3921
3954
  }
@@ -4566,6 +4599,7 @@ var createUppyRoutes = async (app, config) => {
4566
4599
  };
4567
4600
 
4568
4601
  // src/registry/classes.ts
4602
+ import "@modelcontextprotocol/sdk/server/streamableHttp.js";
4569
4603
  var s3Client2;
4570
4604
  function sanitizeToolName(name) {
4571
4605
  if (typeof name !== "string") return "";
@@ -4584,12 +4618,6 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
4584
4618
  name: sanitizeToolName(tool2.name)
4585
4619
  })) : [];
4586
4620
  console.log("[EXULU] Sanitized tools", sanitizedTools.map((x) => x.name + " (" + x.id + ")"));
4587
- const askForConfirmation = {
4588
- description: "Ask the user for confirmation.",
4589
- inputSchema: z.object({
4590
- message: z.string().describe("The message to ask for confirmation.")
4591
- })
4592
- };
4593
4621
  return {
4594
4622
  ...sanitizedTools?.reduce(
4595
4623
  (prev, cur) => ({
@@ -4688,8 +4716,8 @@ var convertToolsArrayToObject = (currentTools, allExuluTools, configs, providera
4688
4716
  }
4689
4717
  }),
4690
4718
  {}
4691
- ),
4692
- askForConfirmation
4719
+ )
4720
+ // askForConfirmation
4693
4721
  };
4694
4722
  };
4695
4723
  var hydrateVariables = async (tool2) => {
@@ -4823,6 +4851,7 @@ var ExuluAgent2 = class {
4823
4851
  id: agentInstance.id,
4824
4852
  name: `${agentInstance.name}`,
4825
4853
  type: "agent",
4854
+ category: "agents",
4826
4855
  inputSchema: z.object({
4827
4856
  prompt: z.string().describe("The prompt (usually a question for the agent) to send to the agent."),
4828
4857
  information: z.string().describe("A summary of relevant context / information from the current session")
@@ -5251,13 +5280,15 @@ var ExuluTool2 = class {
5251
5280
  id;
5252
5281
  name;
5253
5282
  description;
5283
+ category;
5254
5284
  inputSchema;
5255
5285
  type;
5256
5286
  tool;
5257
5287
  config;
5258
- constructor({ id, name, description, inputSchema, type, execute: execute2, config }) {
5288
+ constructor({ id, name, description, category, inputSchema, type, execute: execute2, config }) {
5259
5289
  this.id = id;
5260
5290
  this.config = config;
5291
+ this.category = category || "default";
5261
5292
  this.name = name;
5262
5293
  this.description = description;
5263
5294
  this.inputSchema = inputSchema;
@@ -5686,6 +5717,7 @@ var ExuluContext = class {
5686
5717
  id: this.id,
5687
5718
  name: `${this.name}`,
5688
5719
  type: "context",
5720
+ category: "contexts",
5689
5721
  inputSchema: z.object({
5690
5722
  query: z.string()
5691
5723
  }),
@@ -5723,7 +5755,6 @@ var ExuluContext = class {
5723
5755
  };
5724
5756
  };
5725
5757
  var updateStatistic = async (statistic) => {
5726
- console.log("[EXULU] Updating statistic", statistic);
5727
5758
  const currentDate = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
5728
5759
  const { db: db3 } = await postgresClient();
5729
5760
  const existing = await db3.from("tracking").where({
@@ -5734,7 +5765,6 @@ var updateStatistic = async (statistic) => {
5734
5765
  type: statistic.type,
5735
5766
  createdAt: currentDate
5736
5767
  }).first();
5737
- console.log("[EXULU] Existing", existing);
5738
5768
  if (!existing) {
5739
5769
  await db3.from("tracking").insert({
5740
5770
  name: statistic.name,
@@ -5846,7 +5876,7 @@ var CLAUDE_MESSAGES = {
5846
5876
  };
5847
5877
 
5848
5878
  // src/registry/routes.ts
5849
- import { createIdGenerator as createIdGenerator2 } from "ai";
5879
+ import { createIdGenerator } from "ai";
5850
5880
  var REQUEST_SIZE_LIMIT = "50mb";
5851
5881
  var global_queues = {
5852
5882
  eval_runs: "eval_runs"
@@ -6201,7 +6231,7 @@ Mood: friendly and intelligent.
6201
6231
  console.error("[EXULU] chat response error.", error);
6202
6232
  return errorHandler(error);
6203
6233
  },
6204
- generateMessageId: createIdGenerator2({
6234
+ generateMessageId: createIdGenerator({
6205
6235
  prefix: "msg_",
6206
6236
  size: 16
6207
6237
  }),
@@ -7135,7 +7165,7 @@ function getAverage(arr) {
7135
7165
  // src/mcp/index.ts
7136
7166
  import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
7137
7167
  import { randomUUID as randomUUID4 } from "crypto";
7138
- import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7168
+ import { StreamableHTTPServerTransport as StreamableHTTPServerTransport2 } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7139
7169
  import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
7140
7170
  import { z as z2 } from "zod";
7141
7171
  import "express";
@@ -7225,7 +7255,7 @@ ${code}`
7225
7255
  if (sessionId && this.transports[sessionId]) {
7226
7256
  transport = this.transports[sessionId];
7227
7257
  } else if (!sessionId && isInitializeRequest(req.body)) {
7228
- transport = new StreamableHTTPServerTransport({
7258
+ transport = new StreamableHTTPServerTransport2({
7229
7259
  sessionIdGenerator: () => randomUUID4(),
7230
7260
  onsessioninitialized: (sessionId2) => {
7231
7261
  this.transports[sessionId2] = transport;
@@ -8071,6 +8101,7 @@ var additionTool = new ExuluTool2({
8071
8101
  name: "Addition",
8072
8102
  description: "Adds two numbers together",
8073
8103
  type: "function",
8104
+ category: "math",
8074
8105
  config: [],
8075
8106
  inputSchema: z4.object({
8076
8107
  firstNumber: z4.number().describe("The first addend"),
@@ -8086,6 +8117,7 @@ var subtractionTool = new ExuluTool2({
8086
8117
  name: "Subtraction",
8087
8118
  description: "Subtracts the second number from the first number",
8088
8119
  type: "function",
8120
+ category: "math",
8089
8121
  config: [],
8090
8122
  inputSchema: z4.object({
8091
8123
  minuend: z4.number().describe("The number to subtract from (minuend)"),
@@ -8101,6 +8133,7 @@ var multiplicationTool = new ExuluTool2({
8101
8133
  name: "Multiplication",
8102
8134
  description: "Multiplies two numbers together",
8103
8135
  type: "function",
8136
+ category: "math",
8104
8137
  config: [],
8105
8138
  inputSchema: z4.object({
8106
8139
  firstNumber: z4.number().describe("The first number"),
@@ -8116,6 +8149,7 @@ var divisionTool = new ExuluTool2({
8116
8149
  name: "Division",
8117
8150
  description: "Divides the first number by the second number",
8118
8151
  type: "function",
8152
+ category: "math",
8119
8153
  config: [],
8120
8154
  inputSchema: z4.object({
8121
8155
  numerator: z4.number().describe("The number being divided (numerator)"),
@@ -8131,6 +8165,7 @@ var sumTool = new ExuluTool2({
8131
8165
  name: "Sum",
8132
8166
  description: "Adds any number of numbers together",
8133
8167
  type: "function",
8168
+ category: "math",
8134
8169
  config: [],
8135
8170
  inputSchema: z4.object({
8136
8171
  numbers: z4.array(z4.number()).min(1).describe("Array of numbers to sum")
@@ -8145,6 +8180,7 @@ var moduloTool = new ExuluTool2({
8145
8180
  name: "Modulo",
8146
8181
  description: "Divides two numbers and returns the remainder",
8147
8182
  type: "function",
8183
+ category: "math",
8148
8184
  config: [],
8149
8185
  inputSchema: z4.object({
8150
8186
  numerator: z4.number().describe("The number being divided (numerator)"),
@@ -8160,6 +8196,7 @@ var meanTool = new ExuluTool2({
8160
8196
  name: "Mean",
8161
8197
  description: "Calculates the arithmetic mean of a list of numbers",
8162
8198
  type: "function",
8199
+ category: "math",
8163
8200
  config: [],
8164
8201
  inputSchema: z4.object({
8165
8202
  numbers: z4.array(z4.number()).min(1).describe("Array of numbers to find the mean of")
@@ -8174,6 +8211,7 @@ var medianTool = new ExuluTool2({
8174
8211
  name: "Median",
8175
8212
  description: "Calculates the median of a list of numbers",
8176
8213
  type: "function",
8214
+ category: "math",
8177
8215
  config: [],
8178
8216
  inputSchema: z4.object({
8179
8217
  numbers: z4.array(z4.number()).min(1).describe("Array of numbers to find the median of")
@@ -8188,6 +8226,7 @@ var modeTool = new ExuluTool2({
8188
8226
  name: "Mode",
8189
8227
  description: "Finds the most common number in a list of numbers",
8190
8228
  type: "function",
8229
+ category: "math",
8191
8230
  config: [],
8192
8231
  inputSchema: z4.object({
8193
8232
  numbers: z4.array(z4.number()).describe("Array of numbers to find the mode of")
@@ -8202,6 +8241,7 @@ var minTool = new ExuluTool2({
8202
8241
  name: "Minimum",
8203
8242
  description: "Finds the minimum value from a list of numbers",
8204
8243
  type: "function",
8244
+ category: "math",
8205
8245
  config: [],
8206
8246
  inputSchema: z4.object({
8207
8247
  numbers: z4.array(z4.number()).describe("Array of numbers to find the minimum of")
@@ -8216,6 +8256,7 @@ var maxTool = new ExuluTool2({
8216
8256
  name: "Maximum",
8217
8257
  description: "Finds the maximum value from a list of numbers",
8218
8258
  type: "function",
8259
+ category: "math",
8219
8260
  config: [],
8220
8261
  inputSchema: z4.object({
8221
8262
  numbers: z4.array(z4.number()).describe("Array of numbers to find the maximum of")
@@ -8230,6 +8271,7 @@ var floorTool = new ExuluTool2({
8230
8271
  name: "Floor",
8231
8272
  description: "Rounds a number down to the nearest integer",
8232
8273
  type: "function",
8274
+ category: "math",
8233
8275
  config: [],
8234
8276
  inputSchema: z4.object({
8235
8277
  number: z4.number().describe("The number to round down")
@@ -8244,6 +8286,7 @@ var ceilingTool = new ExuluTool2({
8244
8286
  name: "Ceiling",
8245
8287
  description: "Rounds a number up to the nearest integer",
8246
8288
  type: "function",
8289
+ category: "math",
8247
8290
  config: [],
8248
8291
  inputSchema: z4.object({
8249
8292
  number: z4.number().describe("The number to round up")
@@ -8258,6 +8301,7 @@ var roundTool = new ExuluTool2({
8258
8301
  name: "Round",
8259
8302
  description: "Rounds a number to the nearest integer",
8260
8303
  type: "function",
8304
+ category: "math",
8261
8305
  config: [],
8262
8306
  inputSchema: z4.object({
8263
8307
  number: z4.number().describe("The number to round")
@@ -8272,6 +8316,7 @@ var sinTool = new ExuluTool2({
8272
8316
  name: "Sine",
8273
8317
  description: "Calculates the sine of a number in radians",
8274
8318
  type: "function",
8319
+ category: "math",
8275
8320
  config: [],
8276
8321
  inputSchema: z4.object({
8277
8322
  number: z4.number().describe("The number in radians to find the sine of")
@@ -8286,6 +8331,7 @@ var arcsinTool = new ExuluTool2({
8286
8331
  name: "Arcsine",
8287
8332
  description: "Calculates the arcsine of a number in radians",
8288
8333
  type: "function",
8334
+ category: "math",
8289
8335
  config: [],
8290
8336
  inputSchema: z4.object({
8291
8337
  number: z4.number().describe("The number to find the arcsine of")
@@ -8300,6 +8346,7 @@ var cosTool = new ExuluTool2({
8300
8346
  name: "Cosine",
8301
8347
  description: "Calculates the cosine of a number in radians",
8302
8348
  type: "function",
8349
+ category: "math",
8303
8350
  config: [],
8304
8351
  inputSchema: z4.object({
8305
8352
  number: z4.number().describe("The number in radians to find the cosine of")
@@ -8314,6 +8361,7 @@ var arccosTool = new ExuluTool2({
8314
8361
  name: "Arccosine",
8315
8362
  description: "Calculates the arccosine of a number in radians",
8316
8363
  type: "function",
8364
+ category: "math",
8317
8365
  config: [],
8318
8366
  inputSchema: z4.object({
8319
8367
  number: z4.number().describe("The number to find the arccosine of")
@@ -8328,6 +8376,7 @@ var tanTool = new ExuluTool2({
8328
8376
  name: "Tangent",
8329
8377
  description: "Calculates the tangent of a number in radians",
8330
8378
  type: "function",
8379
+ category: "math",
8331
8380
  config: [],
8332
8381
  inputSchema: z4.object({
8333
8382
  number: z4.number().describe("The number in radians to find the tangent of")
@@ -8342,6 +8391,7 @@ var arctanTool = new ExuluTool2({
8342
8391
  name: "Arctangent",
8343
8392
  description: "Calculates the arctangent of a number in radians",
8344
8393
  type: "function",
8394
+ category: "math",
8345
8395
  config: [],
8346
8396
  inputSchema: z4.object({
8347
8397
  number: z4.number().describe("The number to find the arctangent of")
@@ -8356,6 +8406,7 @@ var radiansToDegreesTool = new ExuluTool2({
8356
8406
  name: "Radians to Degrees",
8357
8407
  description: "Converts a radian value to its equivalent in degrees",
8358
8408
  type: "function",
8409
+ category: "math",
8359
8410
  config: [],
8360
8411
  inputSchema: z4.object({
8361
8412
  number: z4.number().describe("The number in radians to convert to degrees")
@@ -8370,6 +8421,7 @@ var degreesToRadiansTool = new ExuluTool2({
8370
8421
  name: "Degrees to Radians",
8371
8422
  description: "Converts a degree value to its equivalent in radians",
8372
8423
  type: "function",
8424
+ category: "math",
8373
8425
  config: [],
8374
8426
  inputSchema: z4.object({
8375
8427
  number: z4.number().describe("The number in degrees to convert to radians")
@@ -8448,10 +8500,10 @@ var ExuluApp = class {
8448
8500
  // Factory function so we can async
8449
8501
  // initialize the MCP server if needed.
8450
8502
  create = async ({ contexts, agents, config, tools, evals }) => {
8451
- this._evals = [
8503
+ this._evals = redisServer.host?.length && redisServer.port?.length ? [
8452
8504
  llmAsJudgeEval,
8453
8505
  ...evals ?? []
8454
- ];
8506
+ ] : [];
8455
8507
  this._contexts = {
8456
8508
  ...contexts,
8457
8509
  codeStandardsContext,
@@ -8481,6 +8533,7 @@ var ExuluApp = class {
8481
8533
  // Because agents are stored in the database, we add those as tools
8482
8534
  // at request time, not during ExuluApp initialization. We add them
8483
8535
  // in the grahql tools resolver.
8536
+ // ...mcpTools
8484
8537
  ];
8485
8538
  const checks = [
8486
8539
  ...Object.keys(this._contexts || {}).map((x) => ({
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@exulu/backend",
3
3
  "author": "Qventu Bv.",
4
- "version": "1.29.0",
4
+ "version": "1.30.1",
5
5
  "main": "./dist/index.js",
6
6
  "private": false,
7
7
  "publishConfig": {
@@ -5,4 +5,5 @@ export interface Tool {
5
5
  type: string;
6
6
  inputSchema: any;
7
7
  outputSchema: any;
8
+ category: string;
8
9
  }