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.
This commit is contained in:
dswbx
2025-09-14 17:03:23 +02:00
parent 92656523ff
commit fea2812688
5 changed files with 30 additions and 7 deletions

View File

@@ -1,10 +1,7 @@
{ {
"mcpServers": { "mcpServers": {
"bknd": { "bknd": {
"url": "http://localhost:3000/mcp", "url": "http://localhost:28623/api/system/mcp"
"headers": {
"API_KEY": "value"
}
} }
} }
} }

View File

@@ -221,6 +221,7 @@ export class AuthController extends Controller {
return user; return user;
}; };
const roles = Object.keys(this.auth.config.roles ?? {});
mcp.tool( mcp.tool(
// @todo: needs permission // @todo: needs permission
"auth_user_create", "auth_user_create",
@@ -231,7 +232,7 @@ export class AuthController extends Controller {
password: s.string({ minLength: 8 }), password: s.string({ minLength: 8 }),
role: s role: s
.string({ .string({
enum: Object.keys(this.auth.config.roles ?? {}), enum: roles.length > 0 ? roles : undefined,
}) })
.optional(), .optional(),
}), }),

View File

@@ -473,3 +473,10 @@ export function deepFreeze<T extends object>(object: T): T {
return Object.freeze(object); 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;
}

View File

@@ -1,6 +1,15 @@
import type { ModuleBuildContext } from "modules"; import type { ModuleBuildContext } from "modules";
import { Controller } from "modules/Controller"; 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 * as SystemPermissions from "modules/permissions";
import type { AppDataConfig } from "../data-schema"; import type { AppDataConfig } from "../data-schema";
import type { EntityManager, EntityData } from "data/entities"; import type { EntityManager, EntityData } from "data/entities";
@@ -420,7 +429,13 @@ export class DataController extends Controller {
if (!this.entityExists(entity)) { if (!this.entityExists(entity)) {
return this.notFound(c); 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)) { if (Array.isArray(body)) {
const result = await this.em.mutator(entity).insertMany(body); const result = await this.em.mutator(entity).insertMany(body);

View File

@@ -9,6 +9,9 @@ import { nodeSqlite } from "./src/adapter/node/connection/NodeSqliteConnection";
import { libsql } from "./src/data/connection/sqlite/libsql/LibsqlConnection"; import { libsql } from "./src/data/connection/sqlite/libsql/LibsqlConnection";
import { $console } from "core/utils/console"; import { $console } from "core/utils/console";
import { createClient } from "@libsql/client"; import { createClient } from "@libsql/client";
import util from "node:util";
util.inspect.defaultOptions.depth = 5;
registries.media.register("local", StorageLocalAdapter); registries.media.register("local", StorageLocalAdapter);