From fea2812688381d644780aa1200317ab8c7ea60ab Mon Sep 17 00:00:00 2001 From: dswbx Date: Sun, 14 Sep 2025 17:03:23 +0200 Subject: [PATCH] fix: handle numbered object conversion and update MCP tool URL Add `convertNumberedObjectToArray` utility for handling numbered object to array conversion, addressing MCP tool allOf behavior. Adjust MCP tool URL in configuration and ensure default inspect options in development environment. Minor improvement in role enumeration handling for auth. --- .cursor/mcp.json | 5 +---- app/src/auth/api/AuthController.ts | 3 ++- app/src/core/utils/objects.ts | 7 +++++++ app/src/data/api/DataController.ts | 19 +++++++++++++++++-- app/vite.dev.ts | 3 +++ 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/.cursor/mcp.json b/.cursor/mcp.json index 064ec5c..8cd1d99 100644 --- a/.cursor/mcp.json +++ b/.cursor/mcp.json @@ -1,10 +1,7 @@ { "mcpServers": { "bknd": { - "url": "http://localhost:3000/mcp", - "headers": { - "API_KEY": "value" - } + "url": "http://localhost:28623/api/system/mcp" } } } diff --git a/app/src/auth/api/AuthController.ts b/app/src/auth/api/AuthController.ts index 33c0df6..ba12d4a 100644 --- a/app/src/auth/api/AuthController.ts +++ b/app/src/auth/api/AuthController.ts @@ -221,6 +221,7 @@ export class AuthController extends Controller { return user; }; + const roles = Object.keys(this.auth.config.roles ?? {}); mcp.tool( // @todo: needs permission "auth_user_create", @@ -231,7 +232,7 @@ export class AuthController extends Controller { password: s.string({ minLength: 8 }), role: s .string({ - enum: Object.keys(this.auth.config.roles ?? {}), + enum: roles.length > 0 ? roles : undefined, }) .optional(), }), diff --git a/app/src/core/utils/objects.ts b/app/src/core/utils/objects.ts index 4a5e129..6f6a985 100644 --- a/app/src/core/utils/objects.ts +++ b/app/src/core/utils/objects.ts @@ -473,3 +473,10 @@ export function deepFreeze(object: T): T { return Object.freeze(object); } + +export function convertNumberedObjectToArray(obj: object): any[] | object { + if (Object.keys(obj).every((key) => Number.isInteger(Number(key)))) { + return Object.values(obj); + } + return obj; +} diff --git a/app/src/data/api/DataController.ts b/app/src/data/api/DataController.ts index a0d7f02..055033c 100644 --- a/app/src/data/api/DataController.ts +++ b/app/src/data/api/DataController.ts @@ -1,6 +1,15 @@ import type { ModuleBuildContext } from "modules"; import { Controller } from "modules/Controller"; -import { jsc, s, describeRoute, schemaToSpec, omitKeys, pickKeys, mcpTool } from "bknd/utils"; +import { + jsc, + s, + describeRoute, + schemaToSpec, + omitKeys, + pickKeys, + mcpTool, + convertNumberedObjectToArray, +} from "bknd/utils"; import * as SystemPermissions from "modules/permissions"; import type { AppDataConfig } from "../data-schema"; import type { EntityManager, EntityData } from "data/entities"; @@ -420,7 +429,13 @@ export class DataController extends Controller { if (!this.entityExists(entity)) { return this.notFound(c); } - const body = (await c.req.json()) as EntityData | EntityData[]; + + const _body = (await c.req.json()) as EntityData | EntityData[]; + // @todo: check on jsonv-ts how to handle this better + // temporary fix for numbered object to array + // this happens when the MCP tool uses the allOf function + // to transform all validation targets into a single object + const body = convertNumberedObjectToArray(_body); if (Array.isArray(body)) { const result = await this.em.mutator(entity).insertMany(body); diff --git a/app/vite.dev.ts b/app/vite.dev.ts index bee9219..1bc2309 100644 --- a/app/vite.dev.ts +++ b/app/vite.dev.ts @@ -9,6 +9,9 @@ import { nodeSqlite } from "./src/adapter/node/connection/NodeSqliteConnection"; import { libsql } from "./src/data/connection/sqlite/libsql/LibsqlConnection"; import { $console } from "core/utils/console"; import { createClient } from "@libsql/client"; +import util from "node:util"; + +util.inspect.defaultOptions.depth = 5; registries.media.register("local", StorageLocalAdapter);