mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
init mcp tools test
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { makeAppFromEnv } from "cli/commands/run";
|
||||
import { createApp } from "core/test/utils";
|
||||
import { ObjectToolSchema } from "modules/mcp";
|
||||
import { s } from "bknd/utils";
|
||||
|
||||
describe("mcp", () => {
|
||||
it("...", async () => {
|
||||
const app = createApp({
|
||||
initialConfig: {
|
||||
auth: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
await app.build();
|
||||
|
||||
const appConfig = app.modules.configs();
|
||||
const { version, ...appSchema } = app.getSchema();
|
||||
|
||||
const schema = s.strictObject(appSchema);
|
||||
|
||||
const nodes = [...schema.walk({ data: appConfig })]
|
||||
.map((n) => {
|
||||
const path = n.instancePath.join(".");
|
||||
if (path.startsWith("auth")) {
|
||||
console.log("schema", n.instancePath, n.schema.constructor.name);
|
||||
if (path === "auth.jwt") {
|
||||
//console.log("jwt", n.schema.IS_MCP);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
})
|
||||
.filter((n) => n.schema instanceof ObjectToolSchema) as s.Node<ObjectToolSchema>[];
|
||||
const tools = nodes.flatMap((n) => n.schema.getTools(n));
|
||||
|
||||
console.log(
|
||||
"tools",
|
||||
tools.map((t) => t.name),
|
||||
);
|
||||
});
|
||||
});
|
||||
41
app/__test__/app/mcp/mcp.auth.test.ts
Normal file
41
app/__test__/app/mcp/mcp.auth.test.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { describe, it, expect, beforeAll } from "bun:test";
|
||||
import { type App, createApp } from "core/test/utils";
|
||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||
|
||||
/**
|
||||
* - [ ] auth_me
|
||||
* - [ ] auth_strategies
|
||||
* - [ ] auth_user_create
|
||||
* - [ ] auth_user_token
|
||||
* - [ ] auth_user_password_change
|
||||
* - [ ] auth_user_password_test
|
||||
* - [ ] config_auth_update
|
||||
* - [ ] config_auth_strategies_get
|
||||
* - [ ] config_auth_strategies_add
|
||||
* - [ ] config_auth_strategies_update
|
||||
* - [ ] config_auth_strategies_remove
|
||||
* - [ ] config_auth_roles_get
|
||||
* - [ ] config_auth_roles_add
|
||||
* - [ ] config_auth_roles_update
|
||||
* - [ ] config_auth_roles_remove
|
||||
*/
|
||||
describe("mcp auth", async () => {
|
||||
let app: App;
|
||||
let server: ReturnType<typeof getSystemMcp>;
|
||||
beforeAll(async () => {
|
||||
app = createApp({
|
||||
initialConfig: {
|
||||
auth: {
|
||||
enabled: true,
|
||||
},
|
||||
server: {
|
||||
mcp: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await app.build();
|
||||
server = getSystemMcp(app);
|
||||
});
|
||||
});
|
||||
32
app/__test__/app/mcp/mcp.base.test.ts
Normal file
32
app/__test__/app/mcp/mcp.base.test.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { createApp } from "core/test/utils";
|
||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||
import { registries } from "index";
|
||||
import { StorageLocalAdapter } from "adapter/node/storage/StorageLocalAdapter";
|
||||
|
||||
describe("mcp", () => {
|
||||
it("should have tools", async () => {
|
||||
registries.media.register("local", StorageLocalAdapter);
|
||||
|
||||
const app = createApp({
|
||||
initialConfig: {
|
||||
auth: {
|
||||
enabled: true,
|
||||
},
|
||||
media: {
|
||||
enabled: true,
|
||||
adapter: {
|
||||
type: "local",
|
||||
config: {
|
||||
path: "./",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await app.build();
|
||||
|
||||
const server = getSystemMcp(app);
|
||||
expect(server.tools.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
48
app/__test__/app/mcp/mcp.data.test.ts
Normal file
48
app/__test__/app/mcp/mcp.data.test.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { describe, it, expect, beforeAll } from "bun:test";
|
||||
import { type App, createApp } from "core/test/utils";
|
||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||
|
||||
/**
|
||||
* - [ ] data_sync
|
||||
* - [ ] data_entity_fn_count
|
||||
* - [ ] data_entity_fn_exists
|
||||
* - [ ] data_entity_read_one
|
||||
* - [ ] data_entity_read_many
|
||||
* - [ ] data_entity_insert
|
||||
* - [ ] data_entity_update_many
|
||||
* - [ ] data_entity_update_one
|
||||
* - [ ] data_entity_delete_one
|
||||
* - [ ] data_entity_delete_many
|
||||
* - [ ] data_entity_info
|
||||
* - [ ] config_data_get
|
||||
* - [ ] config_data_update
|
||||
* - [ ] config_data_entities_get
|
||||
* - [ ] config_data_entities_add
|
||||
* - [ ] config_data_entities_update
|
||||
* - [ ] config_data_entities_remove
|
||||
* - [ ] config_data_relations_get
|
||||
* - [ ] config_data_relations_add
|
||||
* - [ ] config_data_relations_update
|
||||
* - [ ] config_data_relations_remove
|
||||
* - [ ] config_data_indices_get
|
||||
* - [ ] config_data_indices_add
|
||||
* - [ ] config_data_indices_update
|
||||
* - [ ] config_data_indices_remove
|
||||
*/
|
||||
describe("mcp data", async () => {
|
||||
let app: App;
|
||||
let server: ReturnType<typeof getSystemMcp>;
|
||||
beforeAll(async () => {
|
||||
app = createApp({
|
||||
initialConfig: {
|
||||
server: {
|
||||
mcp: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await app.build();
|
||||
server = getSystemMcp(app);
|
||||
});
|
||||
});
|
||||
39
app/__test__/app/mcp/mcp.media.test.ts
Normal file
39
app/__test__/app/mcp/mcp.media.test.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { describe, it, expect, beforeAll } from "bun:test";
|
||||
import { type App, createApp } from "core/test/utils";
|
||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||
import { registries } from "index";
|
||||
import { StorageLocalAdapter } from "adapter/node/storage/StorageLocalAdapter";
|
||||
|
||||
/**
|
||||
* - [ ] config_media_get
|
||||
* - [ ] config_media_update
|
||||
* - [ ] config_media_adapter_get
|
||||
* - [ ] config_media_adapter_update
|
||||
*/
|
||||
describe("mcp media", async () => {
|
||||
let app: App;
|
||||
let server: ReturnType<typeof getSystemMcp>;
|
||||
beforeAll(async () => {
|
||||
registries.media.register("local", StorageLocalAdapter);
|
||||
app = createApp({
|
||||
initialConfig: {
|
||||
media: {
|
||||
enabled: true,
|
||||
adapter: {
|
||||
type: "local",
|
||||
config: {
|
||||
path: "./",
|
||||
},
|
||||
},
|
||||
},
|
||||
server: {
|
||||
mcp: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await app.build();
|
||||
server = getSystemMcp(app);
|
||||
});
|
||||
});
|
||||
38
app/__test__/app/mcp/mcp.system.test.ts
Normal file
38
app/__test__/app/mcp/mcp.system.test.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { describe, test, expect, beforeAll } from "bun:test";
|
||||
import { type App, createApp, createMcpToolCaller } from "core/test/utils";
|
||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||
import { inspect } from "node:util";
|
||||
inspect.defaultOptions.depth = 10;
|
||||
|
||||
/**
|
||||
* - [ ] system_config
|
||||
* - [ ] system_build
|
||||
* - [ ] system_ping
|
||||
* - [ ] system_info
|
||||
* - [ ] config_server_get
|
||||
* - [ ] config_server_update
|
||||
*/
|
||||
describe("mcp system", async () => {
|
||||
let app: App;
|
||||
let server: ReturnType<typeof getSystemMcp>;
|
||||
beforeAll(async () => {
|
||||
app = createApp({
|
||||
initialConfig: {
|
||||
server: {
|
||||
mcp: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await app.build();
|
||||
server = getSystemMcp(app);
|
||||
});
|
||||
|
||||
const tool = createMcpToolCaller();
|
||||
|
||||
test("system_ping", async () => {
|
||||
const result = await tool(server, "system_ping", {});
|
||||
expect(result).toEqual({ pong: true });
|
||||
});
|
||||
});
|
||||
@@ -2,4 +2,5 @@
|
||||
#registry = "http://localhost:4873"
|
||||
|
||||
[test]
|
||||
coverageSkipTestFiles = true
|
||||
coverageSkipTestFiles = true
|
||||
console.depth = 10
|
||||
@@ -65,7 +65,7 @@
|
||||
"hono": "4.8.3",
|
||||
"json-schema-library": "10.0.0-rc7",
|
||||
"json-schema-to-ts": "^3.1.1",
|
||||
"jsonv-ts": "^0.7.1",
|
||||
"jsonv-ts": "^0.7.2",
|
||||
"kysely": "0.27.6",
|
||||
"lodash-es": "^4.17.21",
|
||||
"oauth4webapi": "^2.11.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CliCommand } from "cli/types";
|
||||
import { makeAppFromEnv } from "../run";
|
||||
import { getSystemMcp } from "modules/server/system-mcp";
|
||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||
import { $console } from "bknd/utils";
|
||||
import { stdioTransport } from "jsonv-ts/mcp";
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createApp as createAppInternal, type CreateAppConfig } from "App";
|
||||
import { bunSqlite } from "adapter/bun/connection/BunSqliteConnection";
|
||||
import { Connection } from "data/connection/Connection";
|
||||
import type { getSystemMcp } from "modules/mcp/system-mcp";
|
||||
|
||||
export { App } from "App";
|
||||
|
||||
@@ -10,3 +11,17 @@ export function createApp({ connection, ...config }: CreateAppConfig = {}) {
|
||||
connection: Connection.isConnection(connection) ? connection : bunSqlite(connection as any),
|
||||
});
|
||||
}
|
||||
|
||||
export function createMcpToolCaller() {
|
||||
return async (server: ReturnType<typeof getSystemMcp>, name: string, args: any) => {
|
||||
const res = await server.handle({
|
||||
jsonrpc: "2.0",
|
||||
method: "tools/call",
|
||||
params: {
|
||||
name,
|
||||
arguments: args,
|
||||
},
|
||||
});
|
||||
return JSON.parse((res.result as any)?.content?.[0]?.text ?? "null");
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
openAPISpecs,
|
||||
mcpTool,
|
||||
mcp as mcpMiddleware,
|
||||
isNode,
|
||||
} from "bknd/utils";
|
||||
import type { Context, Hono } from "hono";
|
||||
import { Controller } from "modules/Controller";
|
||||
@@ -28,7 +29,7 @@ import {
|
||||
import * as SystemPermissions from "modules/permissions";
|
||||
import { getVersion } from "core/env";
|
||||
import type { Module } from "modules/Module";
|
||||
import { getSystemMcp } from "./system-mcp";
|
||||
import { getSystemMcp } from "modules/mcp/system-mcp";
|
||||
|
||||
export type ConfigUpdate<Key extends ModuleKey = ModuleKey> = {
|
||||
success: true;
|
||||
@@ -94,6 +95,8 @@ export class SystemController extends Controller {
|
||||
},
|
||||
endpoint: {
|
||||
path: "/mcp",
|
||||
// @ts-ignore
|
||||
_init: isNode() ? { duplex: "half" } : {},
|
||||
},
|
||||
}),
|
||||
);
|
||||
@@ -365,7 +368,10 @@ export class SystemController extends Controller {
|
||||
}),
|
||||
(c) =>
|
||||
c.json({
|
||||
version: c.get("app")?.version(),
|
||||
version: {
|
||||
config: c.get("app")?.version(),
|
||||
bknd: getVersion(),
|
||||
},
|
||||
runtime: getRuntimeKey(),
|
||||
connection: {
|
||||
name: this.app.em.connection.name,
|
||||
|
||||
Reference in New Issue
Block a user