kleanmcp 1.0.1 → 1.0.3
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/dist/index.cjs +554 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.mjs +446 -0
- package/dist/types.cjs +460 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.mjs +394 -0
- package/example/README.md +1 -1
- package/package.json +2 -2
- package/build.ts +0 -30
- package/bun.lock +0 -64
- package/example/bun.lock +0 -75
- package/example/index.ts +0 -125
- package/example/package.json +0 -19
- package/example/tsconfig.json +0 -29
- package/src/index.ts +0 -131
- package/src/types.ts +0 -165
- package/test/mcp.test.ts +0 -65
- package/test/testToolSet.ts +0 -67
- package/test/toolset.test.ts +0 -42
- package/tsconfig.dts.json +0 -12
- package/tsconfig.json +0 -36
package/example/index.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { Elysia } from 'elysia'
|
|
2
|
-
import cors from '@elysiajs/cors'
|
|
3
|
-
import {
|
|
4
|
-
type CallToolResult,
|
|
5
|
-
type JSONRPCErrorResponse,
|
|
6
|
-
type ToolDefinitionGeneric,
|
|
7
|
-
type ToolSet,
|
|
8
|
-
type JSONRPCResponse,
|
|
9
|
-
ToolDefinition,
|
|
10
|
-
} from 'leanmcp/types'
|
|
11
|
-
import { treaty } from '@elysiajs/eden';
|
|
12
|
-
import {
|
|
13
|
-
MCPServerService,
|
|
14
|
-
elysiaJsonRPC
|
|
15
|
-
} from 'leanmcp';
|
|
16
|
-
|
|
17
|
-
export const Tool1 = ToolDefinition(
|
|
18
|
-
"tool_name_1",
|
|
19
|
-
"this tool is a test tool 1",
|
|
20
|
-
[
|
|
21
|
-
{
|
|
22
|
-
name: "arg1",
|
|
23
|
-
description: "describing arg1",
|
|
24
|
-
type: "string",
|
|
25
|
-
required: false,
|
|
26
|
-
},
|
|
27
|
-
] as const,
|
|
28
|
-
)(async (
|
|
29
|
-
_reference: object,
|
|
30
|
-
arg_string: string,
|
|
31
|
-
_extra?: any,
|
|
32
|
-
): Promise<CallToolResult> => {
|
|
33
|
-
return {
|
|
34
|
-
content: [
|
|
35
|
-
{
|
|
36
|
-
type: "text",
|
|
37
|
-
text: arg_string,
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
export const Tool2 = ToolDefinition(
|
|
44
|
-
"tool_name_2",
|
|
45
|
-
"this tool is a test tool 2",
|
|
46
|
-
[
|
|
47
|
-
{
|
|
48
|
-
name: "arg1",
|
|
49
|
-
description: "describing arg1",
|
|
50
|
-
type: "string",
|
|
51
|
-
required: false,
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
name: "arg2",
|
|
55
|
-
description: "describing arg2",
|
|
56
|
-
type: "boolean",
|
|
57
|
-
required: false,
|
|
58
|
-
},
|
|
59
|
-
] as const,
|
|
60
|
-
)(async (
|
|
61
|
-
_reference: any,
|
|
62
|
-
arg1: string,
|
|
63
|
-
arg2: boolean,
|
|
64
|
-
_extra?: any,
|
|
65
|
-
): Promise<CallToolResult> => {
|
|
66
|
-
throw new Error("this always fails");
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
export class TestToolSet implements ToolSet {
|
|
70
|
-
getTools(): ToolDefinitionGeneric[] {
|
|
71
|
-
return [Tool1, Tool2];
|
|
72
|
-
}
|
|
73
|
-
getTool(toolName: string): ToolDefinitionGeneric | undefined {
|
|
74
|
-
return this.getTools().find(x => x.name == toolName);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const serverService = new MCPServerService(
|
|
80
|
-
"testServerTitle",
|
|
81
|
-
"1.0.0",
|
|
82
|
-
"No instructions",
|
|
83
|
-
(toolName: string) => {
|
|
84
|
-
return serverService;
|
|
85
|
-
},
|
|
86
|
-
[new TestToolSet()],
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
export const app = new Elysia().use(cors({
|
|
90
|
-
origin: "*",
|
|
91
|
-
methods: ["GET", "POST", "OPTIONS"],
|
|
92
|
-
allowedHeaders: [
|
|
93
|
-
"Content-Type",
|
|
94
|
-
"Authorization",
|
|
95
|
-
"mcp-protocol-version",
|
|
96
|
-
"mcp-session-id",
|
|
97
|
-
]
|
|
98
|
-
})).use(elysiaJsonRPC({
|
|
99
|
-
debug: true,
|
|
100
|
-
dns_rebind_origin: undefined,
|
|
101
|
-
service: serverService,
|
|
102
|
-
onError: (res: JSONRPCErrorResponse) => {
|
|
103
|
-
// console.log("onError", res.error.data);
|
|
104
|
-
},
|
|
105
|
-
onResponse: (res: any) => {
|
|
106
|
-
// console.log("onResponse");
|
|
107
|
-
},
|
|
108
|
-
onRequest: (res: any) => {
|
|
109
|
-
// console.log("onRequest");
|
|
110
|
-
},
|
|
111
|
-
}));
|
|
112
|
-
|
|
113
|
-
const client = treaty<typeof app>(app);
|
|
114
|
-
const resp = await client["stream"].post({
|
|
115
|
-
id: "1",
|
|
116
|
-
jsonrpc: "2.0",
|
|
117
|
-
method: "tools/list",
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const response = resp.data as JSONRPCResponse;
|
|
121
|
-
if (response.id == "1" && response.jsonrpc == "2.0" && response.result) {
|
|
122
|
-
console.log("works!")
|
|
123
|
-
} else {
|
|
124
|
-
console.error("failed!")
|
|
125
|
-
}
|
package/example/package.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "test_leanmcp",
|
|
3
|
-
"module": "index.ts",
|
|
4
|
-
"type": "module",
|
|
5
|
-
"private": true,
|
|
6
|
-
"devDependencies": {
|
|
7
|
-
"@types/bun": "latest"
|
|
8
|
-
},
|
|
9
|
-
"peerDependencies": {
|
|
10
|
-
"typescript": "^5"
|
|
11
|
-
},
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"@elysiajs/cors": "^1.4.1",
|
|
14
|
-
"@elysiajs/eden": "^1.4.8",
|
|
15
|
-
"elysia": "^1.4.25",
|
|
16
|
-
"leanmcp": "link:leanmcp",
|
|
17
|
-
"zod": "^4.3.6"
|
|
18
|
-
}
|
|
19
|
-
}
|
package/example/tsconfig.json
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
// Environment setup & latest features
|
|
4
|
-
"lib": ["ESNext"],
|
|
5
|
-
"target": "ESNext",
|
|
6
|
-
"module": "Preserve",
|
|
7
|
-
"moduleDetection": "force",
|
|
8
|
-
"jsx": "react-jsx",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
|
|
11
|
-
// Bundler mode
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"allowImportingTsExtensions": true,
|
|
14
|
-
"verbatimModuleSyntax": true,
|
|
15
|
-
"noEmit": true,
|
|
16
|
-
|
|
17
|
-
// Best practices
|
|
18
|
-
"strict": true,
|
|
19
|
-
"skipLibCheck": true,
|
|
20
|
-
"noFallthroughCasesInSwitch": true,
|
|
21
|
-
"noUncheckedIndexedAccess": true,
|
|
22
|
-
"noImplicitOverride": true,
|
|
23
|
-
|
|
24
|
-
// Some stricter flags (disabled by default)
|
|
25
|
-
"noUnusedLocals": false,
|
|
26
|
-
"noUnusedParameters": false,
|
|
27
|
-
"noPropertyAccessFromIndexSignature": false
|
|
28
|
-
}
|
|
29
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
InputSchemaFromParameters,
|
|
4
|
-
ToolArgsToParameterList,
|
|
5
|
-
type CallToolResult,
|
|
6
|
-
type Tool,
|
|
7
|
-
type ToolDefinitionGeneric,
|
|
8
|
-
type ToolSet
|
|
9
|
-
} from "./types";
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
MCPError,
|
|
13
|
-
type InitializeParams,
|
|
14
|
-
type InitializeResult,
|
|
15
|
-
type MCPServerInterface,
|
|
16
|
-
type PingParams,
|
|
17
|
-
type PingResult,
|
|
18
|
-
type PromptsGetParams,
|
|
19
|
-
type PromptsGetResult,
|
|
20
|
-
type PromptsListParams,
|
|
21
|
-
type PromptsListResult,
|
|
22
|
-
type ResourcesListParams,
|
|
23
|
-
type ResourcesListResult,
|
|
24
|
-
type ResourcesReadParams,
|
|
25
|
-
type ResourcesReadResult,
|
|
26
|
-
type ResourcesSubscribeParams,
|
|
27
|
-
type ResourcesSubscribeResult,
|
|
28
|
-
type ResourcesTemplatesListParams,
|
|
29
|
-
type ResourcesTemplatesListResult,
|
|
30
|
-
type ToolsCallParams,
|
|
31
|
-
type ToolsCallResult,
|
|
32
|
-
type ToolsListParams,
|
|
33
|
-
type ToolsListResult,
|
|
34
|
-
} from "elysia-jsonrpc/mcp";
|
|
35
|
-
|
|
36
|
-
import elysiaJsonRPC from "elysia-jsonrpc";
|
|
37
|
-
export { elysiaJsonRPC };
|
|
38
|
-
|
|
39
|
-
export type ReferenceForToolCallFunction = (toolName: string) => any;
|
|
40
|
-
|
|
41
|
-
export class MCPServerService implements MCPServerInterface {
|
|
42
|
-
constructor(
|
|
43
|
-
readonly serverTitle: string,
|
|
44
|
-
readonly serverVersion: string,
|
|
45
|
-
readonly serverInstructions: string,
|
|
46
|
-
readonly getReferenceInstanceForToolCall: ReferenceForToolCallFunction,
|
|
47
|
-
readonly toolsets: ToolSet[],
|
|
48
|
-
) {}
|
|
49
|
-
initialize(params: InitializeParams): Promise<InitializeResult> {
|
|
50
|
-
return Promise.resolve({
|
|
51
|
-
capabilities: {
|
|
52
|
-
tools: {},
|
|
53
|
-
},
|
|
54
|
-
serverInfo: {
|
|
55
|
-
name: this.serverTitle,
|
|
56
|
-
version: this.serverVersion,
|
|
57
|
-
},
|
|
58
|
-
protocolVersion: "2025-11-25",
|
|
59
|
-
instructions: this.serverInstructions,
|
|
60
|
-
} as InitializeResult);
|
|
61
|
-
}
|
|
62
|
-
ping(params: PingParams): Promise<PingResult> {
|
|
63
|
-
return Promise.resolve({} as PingResult);
|
|
64
|
-
}
|
|
65
|
-
"tools/list"(params: ToolsListParams): Promise<ToolsListResult> {
|
|
66
|
-
return Promise.resolve({
|
|
67
|
-
tools: this.toolsets.flatMap((toolset: ToolSet): Tool[] => {
|
|
68
|
-
return toolset.getTools().map((tool: ToolDefinitionGeneric): Tool => {
|
|
69
|
-
return {
|
|
70
|
-
name: tool.name,
|
|
71
|
-
description: tool.description,
|
|
72
|
-
inputSchema: InputSchemaFromParameters(
|
|
73
|
-
tool.params,
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
})
|
|
78
|
-
} as ToolsListResult);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
getTool(toolName: string): ToolDefinitionGeneric | null {
|
|
82
|
-
for (const toolset of this.toolsets) {
|
|
83
|
-
const maybeTool = toolset.getTool(toolName);
|
|
84
|
-
if (maybeTool) return maybeTool;
|
|
85
|
-
}
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async "tools/call"(params: ToolsCallParams): Promise<ToolsCallResult> {
|
|
90
|
-
const toolName: string = params.name;
|
|
91
|
-
const toolArgs: any = params.arguments || {};
|
|
92
|
-
const tool = this.getTool(toolName);
|
|
93
|
-
if (!tool) throw new MCPError("Tool not found!", { toolName: toolName });
|
|
94
|
-
const referenceInstance = this.getReferenceInstanceForToolCall(toolName);
|
|
95
|
-
const result: CallToolResult = await tool.callback(
|
|
96
|
-
referenceInstance,
|
|
97
|
-
...ToolArgsToParameterList(toolArgs, tool.params),
|
|
98
|
-
{},
|
|
99
|
-
);
|
|
100
|
-
return ((result: CallToolResult) => {toolArgs
|
|
101
|
-
return {
|
|
102
|
-
toolUseId: "",
|
|
103
|
-
content: result.content,
|
|
104
|
-
type: "tool_result",
|
|
105
|
-
isError: result.isError || false,
|
|
106
|
-
} as ToolsCallResult;
|
|
107
|
-
})(result);
|
|
108
|
-
}
|
|
109
|
-
"prompts/list"(params: PromptsListParams): Promise<PromptsListResult> {
|
|
110
|
-
throw new Error("Method not implemented.");
|
|
111
|
-
}
|
|
112
|
-
"prompts/get"(params: PromptsGetParams): Promise<PromptsGetResult> {
|
|
113
|
-
throw new Error("Method not implemented.");
|
|
114
|
-
}
|
|
115
|
-
"resources/list"(params: ResourcesListParams): Promise<ResourcesListResult> {
|
|
116
|
-
throw new Error("Method not implemented.");
|
|
117
|
-
}
|
|
118
|
-
"resources/read"(params: ResourcesReadParams): Promise<ResourcesReadResult> {
|
|
119
|
-
throw new Error("Method not implemented.");
|
|
120
|
-
}
|
|
121
|
-
"resources/subscribe"(
|
|
122
|
-
params: ResourcesSubscribeParams,
|
|
123
|
-
): Promise<ResourcesSubscribeResult> {
|
|
124
|
-
throw new Error("Method not implemented.");
|
|
125
|
-
}
|
|
126
|
-
"resources/templates/list"(
|
|
127
|
-
params: ResourcesTemplatesListParams,
|
|
128
|
-
): Promise<ResourcesTemplatesListResult> {
|
|
129
|
-
throw new Error("Method not implemented.");
|
|
130
|
-
}
|
|
131
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
export * from "elysia-jsonrpc/mcp";
|
|
2
|
-
export * from "elysia-jsonrpc/rpc";
|
|
3
|
-
export * from "elysia-jsonrpc";
|
|
4
|
-
|
|
5
|
-
export type ParamType =
|
|
6
|
-
| "string"
|
|
7
|
-
| "number"
|
|
8
|
-
| "boolean"
|
|
9
|
-
| "object"
|
|
10
|
-
| "Record<string, any>";
|
|
11
|
-
|
|
12
|
-
export type ParamDef = {
|
|
13
|
-
type: ParamType;
|
|
14
|
-
required?: boolean;
|
|
15
|
-
default?: ParamDef["type"];
|
|
16
|
-
name: string;
|
|
17
|
-
description: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export type ExtractType<T extends ParamDef["type"]> = T extends "string"
|
|
21
|
-
? string
|
|
22
|
-
: T extends "number"
|
|
23
|
-
? number
|
|
24
|
-
: T extends "boolean"
|
|
25
|
-
? boolean
|
|
26
|
-
: T extends "object"
|
|
27
|
-
? object
|
|
28
|
-
: T extends "Record<string, any>"
|
|
29
|
-
? Record<string, any>
|
|
30
|
-
: never;
|
|
31
|
-
|
|
32
|
-
export type MethodResult<
|
|
33
|
-
TResult,
|
|
34
|
-
TParams extends readonly ParamDef[],
|
|
35
|
-
TExtra = any,
|
|
36
|
-
> = {
|
|
37
|
-
name: string;
|
|
38
|
-
params: TParams;
|
|
39
|
-
callback: (...args: [...ParamsToTuple<TParams>, TExtra]) => Promise<TResult>;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export type NamedParam<N extends string, T extends ParamDef> = T & { name: N };
|
|
43
|
-
|
|
44
|
-
export type ParamsToTuple<T extends readonly ParamDef[]> = {
|
|
45
|
-
[K in keyof T]: T[K] extends ParamDef ? ExtractType<T[K]["type"]> : never;
|
|
46
|
-
};
|
|
47
|
-
export type NamedParamsToTuple<
|
|
48
|
-
T extends readonly NamedParam<string, ParamDef>[],
|
|
49
|
-
> = {
|
|
50
|
-
[K in keyof T]: T[K] extends NamedParam<string, infer P>
|
|
51
|
-
? P extends ParamDef
|
|
52
|
-
? ExtractType<P["type"]>
|
|
53
|
-
: never
|
|
54
|
-
: never;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export interface PropertyDescription {
|
|
58
|
-
type: string;
|
|
59
|
-
description: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface InputSchemaType {
|
|
63
|
-
[x: string]: unknown;
|
|
64
|
-
type: "object";
|
|
65
|
-
properties?: Record<string, PropertyDescription>;
|
|
66
|
-
required?: string[];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export type ToolParameterDefinition = {
|
|
70
|
-
required: boolean;
|
|
71
|
-
type: string;
|
|
72
|
-
description: string;
|
|
73
|
-
default?: object;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export interface CallToolResult {
|
|
77
|
-
content: any[];
|
|
78
|
-
isError?: boolean;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function InputSchemaFromParameters(
|
|
82
|
-
params: ToolParameterDefinition[],
|
|
83
|
-
): InputSchemaType {
|
|
84
|
-
return {
|
|
85
|
-
type: "object",
|
|
86
|
-
properties: Object.fromEntries(
|
|
87
|
-
Object.entries(params).map(([k, v]) => [
|
|
88
|
-
k,
|
|
89
|
-
{
|
|
90
|
-
description: v.description,
|
|
91
|
-
type: v.type,
|
|
92
|
-
default: v.default,
|
|
93
|
-
} as PropertyDescription,
|
|
94
|
-
]),
|
|
95
|
-
) as Record<string, PropertyDescription>,
|
|
96
|
-
required: Object.entries(params)
|
|
97
|
-
.map(([k, v]) => (v.required ? k : undefined))
|
|
98
|
-
.filter((v): v is string => v !== undefined),
|
|
99
|
-
} as InputSchemaType;
|
|
100
|
-
}
|
|
101
|
-
export function ToolArgsToParameterList<
|
|
102
|
-
TParams extends readonly NamedParam<string, ParamDef>[] = [],
|
|
103
|
-
>(toolArgs: Record<string, any>, params: TParams): (any | undefined)[] {
|
|
104
|
-
let res: any[] = [];
|
|
105
|
-
for (const param of params) {
|
|
106
|
-
res.push(toolArgs[param.name] ?? param.default ?? undefined);
|
|
107
|
-
}
|
|
108
|
-
return res;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export type ToolDefinitionCreator<
|
|
112
|
-
ReferencedServerType,
|
|
113
|
-
TParams extends readonly NamedParam<string, ParamDef>[] = [],
|
|
114
|
-
> = <UserRef extends ReferencedServerType, TExtra = any>(
|
|
115
|
-
callback: (
|
|
116
|
-
...args: [UserRef, ...NamedParamsToTuple<TParams>, TExtra?]
|
|
117
|
-
) => Promise<CallToolResult>,
|
|
118
|
-
) => any;
|
|
119
|
-
|
|
120
|
-
export function ToolDefinition<
|
|
121
|
-
ReferencedServerType = any,
|
|
122
|
-
TParams extends readonly NamedParam<string, ParamDef>[] = [],
|
|
123
|
-
>(methodName: string, methodDescription: string, params: TParams): ToolDefinitionCreator<ReferencedServerType, TParams> {
|
|
124
|
-
return <UserRef extends ReferencedServerType, TExtra = any>(
|
|
125
|
-
callback: (
|
|
126
|
-
...args: [UserRef, ...NamedParamsToTuple<TParams>, TExtra?]
|
|
127
|
-
) => Promise<CallToolResult>,
|
|
128
|
-
) => {
|
|
129
|
-
return {
|
|
130
|
-
name: methodName,
|
|
131
|
-
description: methodDescription,
|
|
132
|
-
params,
|
|
133
|
-
callback,
|
|
134
|
-
};
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export type ToolDefinitionGeneric<
|
|
139
|
-
ReferencedServerType = any,
|
|
140
|
-
// TParams extends readonly NamedParam<string, ParamDef>[] = [],
|
|
141
|
-
TParams = any,
|
|
142
|
-
> = {
|
|
143
|
-
name: string;
|
|
144
|
-
description: string;
|
|
145
|
-
params: TParams;
|
|
146
|
-
callback: (
|
|
147
|
-
argfirst: ReferencedServerType,
|
|
148
|
-
...args: any[]
|
|
149
|
-
) => Promise<CallToolResult>;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
export interface ToolResult {
|
|
153
|
-
content: PropertyDescription[]; // TODO: maybe change
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export interface Tool {
|
|
157
|
-
name: string;
|
|
158
|
-
description: string;
|
|
159
|
-
inputSchema: InputSchemaType;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
export interface ToolSet {
|
|
163
|
-
getTools(): ToolDefinitionGeneric[];
|
|
164
|
-
getTool(toolName: string): ToolDefinitionGeneric | undefined;
|
|
165
|
-
}
|
package/test/mcp.test.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { describe, expect, it, test } from "bun:test";
|
|
5
|
-
import { MCPServerService } from "../src";
|
|
6
|
-
import { TestToolSet } from "./testToolSet";
|
|
7
|
-
|
|
8
|
-
describe("MCPServerService", () => {
|
|
9
|
-
const serverService = new MCPServerService(
|
|
10
|
-
"testServerTitle",
|
|
11
|
-
"1.0.0",
|
|
12
|
-
"No instructions",
|
|
13
|
-
(toolName: string) => { return serverService },
|
|
14
|
-
[
|
|
15
|
-
new TestToolSet(),
|
|
16
|
-
]
|
|
17
|
-
);
|
|
18
|
-
|
|
19
|
-
test("that the server has the tools", async () => {
|
|
20
|
-
const toolsListResult = await serverService["tools/list"]({});
|
|
21
|
-
expect(toolsListResult.tools).toBeArrayOfSize(2);
|
|
22
|
-
expect(toolsListResult.tools.at(0)?.name).toBe("tool_name_1");
|
|
23
|
-
expect(toolsListResult.tools.at(1)?.name).toBe("tool_name_2");
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("that the server has callable tools that works without args", async () => {
|
|
27
|
-
const toolsListResult = await serverService["tools/call"]({
|
|
28
|
-
name: "tool_name_1"
|
|
29
|
-
});
|
|
30
|
-
expect(toolsListResult.isError).toBeFalse();
|
|
31
|
-
expect(toolsListResult.content).toBeArrayOfSize(1)
|
|
32
|
-
expect(toolsListResult.content[0]).toBeObject();
|
|
33
|
-
expect(toolsListResult.content[0]?.type).toBe("text");
|
|
34
|
-
expect(toolsListResult.content[0]?.text).toBe(undefined);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("that the server has callable tools that works with args", async () => {
|
|
38
|
-
const toolsListResult = await serverService["tools/call"]({
|
|
39
|
-
name: "tool_name_1",
|
|
40
|
-
arguments: {
|
|
41
|
-
"arg1": "any"
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
expect(toolsListResult.isError).toBeFalse();
|
|
45
|
-
expect(toolsListResult.content).toBeArrayOfSize(1)
|
|
46
|
-
expect(toolsListResult.content[0]).toBeObject();
|
|
47
|
-
expect(toolsListResult.content[0]?.type).toBe("text");
|
|
48
|
-
expect(toolsListResult.content[0]?.text).toBe("any");
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test("that the server has callable tools that works with arg name validation", async () => {
|
|
52
|
-
const toolsListResult = await serverService["tools/call"]({
|
|
53
|
-
name: "tool_name_1",
|
|
54
|
-
arguments: {
|
|
55
|
-
"arg0": "any"
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
expect(toolsListResult.isError).toBeFalse();
|
|
59
|
-
expect(toolsListResult.content).toBeArrayOfSize(1)
|
|
60
|
-
expect(toolsListResult.content[0]).toBeObject();
|
|
61
|
-
expect(toolsListResult.content[0]?.type).toBe("text");
|
|
62
|
-
expect(toolsListResult.content[0]?.text).toBe(undefined); // since we dont have the correct argument name
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
});
|
package/test/testToolSet.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ToolDefinition,
|
|
3
|
-
type CallToolResult,
|
|
4
|
-
type ToolDefinitionGeneric,
|
|
5
|
-
type ToolSet,
|
|
6
|
-
} from "../src/types";
|
|
7
|
-
|
|
8
|
-
export const Tool1 = ToolDefinition(
|
|
9
|
-
"tool_name_1",
|
|
10
|
-
"this tool is a test tool 1",
|
|
11
|
-
[
|
|
12
|
-
{
|
|
13
|
-
name: "arg1",
|
|
14
|
-
description: "describing arg1",
|
|
15
|
-
type: "string",
|
|
16
|
-
required: false,
|
|
17
|
-
},
|
|
18
|
-
] as const,
|
|
19
|
-
)(async (
|
|
20
|
-
_reference: object,
|
|
21
|
-
arg_string: string,
|
|
22
|
-
_extra?: any,
|
|
23
|
-
): Promise<CallToolResult> => {
|
|
24
|
-
return {
|
|
25
|
-
content: [
|
|
26
|
-
{
|
|
27
|
-
type: "text",
|
|
28
|
-
text: arg_string,
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
};
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
export const Tool2 = ToolDefinition(
|
|
35
|
-
"tool_name_2",
|
|
36
|
-
"this tool is a test tool 2",
|
|
37
|
-
[
|
|
38
|
-
{
|
|
39
|
-
name: "arg1",
|
|
40
|
-
description: "describing arg1",
|
|
41
|
-
type: "string",
|
|
42
|
-
required: false,
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
name: "arg2",
|
|
46
|
-
description: "describing arg2",
|
|
47
|
-
type: "boolean",
|
|
48
|
-
required: false,
|
|
49
|
-
},
|
|
50
|
-
] as const,
|
|
51
|
-
)(async (
|
|
52
|
-
_reference: any,
|
|
53
|
-
arg1: string,
|
|
54
|
-
arg2: boolean,
|
|
55
|
-
_extra?: any,
|
|
56
|
-
): Promise<CallToolResult> => {
|
|
57
|
-
throw new Error("this always fails");
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
export class TestToolSet implements ToolSet {
|
|
61
|
-
getTools(): ToolDefinitionGeneric[] {
|
|
62
|
-
return [Tool1, Tool2];
|
|
63
|
-
}
|
|
64
|
-
getTool(toolName: string): ToolDefinitionGeneric | undefined {
|
|
65
|
-
return this.getTools().find(x => x.name == toolName);
|
|
66
|
-
}
|
|
67
|
-
}
|
package/test/toolset.test.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, test } from "bun:test";
|
|
2
|
-
import { TestToolSet } from "./testToolSet";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
describe("TestToolSet", () => {
|
|
6
|
-
const toolSet = new TestToolSet();
|
|
7
|
-
test("that the toolset can handle any name", async () => {
|
|
8
|
-
expect(toolSet.getTool("tool_name_1")).not.toBeUndefined();
|
|
9
|
-
});
|
|
10
|
-
const tools = toolSet.getTools();
|
|
11
|
-
for (const toolId in tools) {
|
|
12
|
-
const tool = tools[toolId];
|
|
13
|
-
if (!tool) continue;
|
|
14
|
-
test(`that the toolset ${toolId} is constructed correctly`, async () => {
|
|
15
|
-
expect(tool.name).toBeOneOf(["tool_name_1", "tool_name_2"]);
|
|
16
|
-
expect(tool.description).not.toBe("");
|
|
17
|
-
expect(tool.params).toBeArray();
|
|
18
|
-
expect(tool.params).not.toBeArrayOfSize(0);
|
|
19
|
-
expect(tool.params.length).toBeOneOf([1, 2]);
|
|
20
|
-
});
|
|
21
|
-
// test(`that the toolset ${i} is callable with any amount of args`, async () => {
|
|
22
|
-
const callback = tool.callback;
|
|
23
|
-
const args = [this, "test", false, "test"];
|
|
24
|
-
|
|
25
|
-
for (let n = 0; n < args.length + 1; n++) {
|
|
26
|
-
test(`should handle ${n} args correctly `, async () => {
|
|
27
|
-
const result = await expect(async () => {
|
|
28
|
-
const xargs = args.slice(0, n);
|
|
29
|
-
const ret = await (callback as any)(...xargs);
|
|
30
|
-
expect(ret).toBeObject();
|
|
31
|
-
expect(ret.content).toBeArrayOfSize(1);
|
|
32
|
-
if(n > 1) expect(ret.content[0].text).toBe(args[1]);
|
|
33
|
-
});
|
|
34
|
-
if (toolId == "0") {
|
|
35
|
-
result.not.toThrow();
|
|
36
|
-
} else if (toolId == "1") {
|
|
37
|
-
result.toThrow("this always fails");
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
});
|
package/tsconfig.dts.json
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"declaration": true,
|
|
4
|
-
"emitDeclarationOnly": true,
|
|
5
|
-
"outDir": "./dist",
|
|
6
|
-
"skipLibCheck": true,
|
|
7
|
-
"esModuleInterop": true,
|
|
8
|
-
"noCheck": true,
|
|
9
|
-
},
|
|
10
|
-
"exclude": ["node_modules", "test", "src/**/*.d.ts"],
|
|
11
|
-
"include": ["src/**/*.ts"]
|
|
12
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
// Environment setup & latest features
|
|
4
|
-
"lib": ["ESNext"],
|
|
5
|
-
"target": "ESNext",
|
|
6
|
-
"module": "Preserve",
|
|
7
|
-
"moduleDetection": "force",
|
|
8
|
-
"jsx": "react-jsx",
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
|
|
11
|
-
// Bundler mode
|
|
12
|
-
"moduleResolution": "bundler",
|
|
13
|
-
"allowImportingTsExtensions": true,
|
|
14
|
-
"verbatimModuleSyntax": true,
|
|
15
|
-
"noEmit": false,
|
|
16
|
-
"declaration": true,
|
|
17
|
-
"declarationDir": "./out",
|
|
18
|
-
"emitDeclarationOnly": true,
|
|
19
|
-
"rootDir": "./src",
|
|
20
|
-
|
|
21
|
-
// Best practices
|
|
22
|
-
"strict": true,
|
|
23
|
-
"skipLibCheck": true,
|
|
24
|
-
"noFallthroughCasesInSwitch": true,
|
|
25
|
-
"noUncheckedIndexedAccess": true,
|
|
26
|
-
"noImplicitOverride": true,
|
|
27
|
-
|
|
28
|
-
// Some stricter flags (disabled by default)
|
|
29
|
-
"noUnusedLocals": false,
|
|
30
|
-
"noUnusedParameters": false,
|
|
31
|
-
"noPropertyAccessFromIndexSignature": false
|
|
32
|
-
},
|
|
33
|
-
"include": [
|
|
34
|
-
"src/**/*.ts"
|
|
35
|
-
]
|
|
36
|
-
}
|