Skip to content

Commit b59fb9d

Browse files
Merge pull request #5 from yepcode/feature/move-tools-code-out-of-server
Move tools definitions out of server
2 parents 93e1323 + 15cdaa0 commit b59fb9d

File tree

6 files changed

+241
-193
lines changed

6 files changed

+241
-193
lines changed

src/server.ts

Lines changed: 26 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,7 @@ import {
1717
YepCodeApiConfig,
1818
} from "@yepcode/run";
1919
import dotenv from "dotenv";
20-
import {
21-
RunCodeSchema,
22-
buildRunCodeSchema,
23-
SetEnvVarSchema,
24-
RemoveEnvVarSchema,
25-
ToolCallRequest,
26-
ToolHandler,
27-
RunProcessSchema,
28-
ExecutionResultSchema,
29-
GetExecutionSchema,
30-
} from "./types.js";
20+
import { ToolCallRequest, ToolHandler } from "./types.js";
3121
import { z } from "zod";
3222
import { getVersion, isEmpty } from "./utils.js";
3323
import Logger from "./logger.js";
@@ -39,6 +29,24 @@ import {
3929
storageToolNames,
4030
UploadObjectSchema,
4131
} from "./tools/storage-tool-definitions.js";
32+
import {
33+
SetEnvVarSchema,
34+
RemoveEnvVarSchema,
35+
envVarsToolDefinitions,
36+
envVarsToolNames,
37+
} from "./tools/env-vars-tool-definitions.js";
38+
import {
39+
GetExecutionSchema,
40+
getExecutionToolNames,
41+
getExecutionToolDefinitions,
42+
} from "./tools/get-execution-tool-definition.js";
43+
import {
44+
runCodeToolDefinitions,
45+
RunCodeSchema,
46+
ExecutionResultSchema,
47+
RunProcessSchema,
48+
runCodeToolNames,
49+
} from "./tools/run-code-tool-definitinos.js";
4250

4351
const RUN_PROCESS_TOOL_NAME_PREFIX = "run_ycp_";
4452
const RUN_PROCESS_TOOL_TAG = "mcp-tool";
@@ -205,79 +213,18 @@ class YepCodeMcpServer extends Server {
205213
};
206214
}
207215

208-
private getCodingRules = async (): Promise<string> => {
209-
try {
210-
let rulesMdFile = await fetch(
211-
"https://yepcode.io/docs/yepcode-coding-rules.md"
212-
).then((res) => res.text());
213-
rulesMdFile = rulesMdFile.substring(
214-
rulesMdFile.indexOf("## General Rules")
215-
);
216-
rulesMdFile = rulesMdFile.replace(
217-
/(\[Section titled .*\]\(#.*\)\n)/g,
218-
""
219-
);
220-
221-
return `Here you can find the general rules for YepCode coding:
222-
223-
${rulesMdFile}`;
224-
} catch (error) {
225-
return "";
226-
}
227-
};
228-
229216
private setupToolHandlers(): void {
230217
this.setRequestHandler(ListToolsRequestSchema, async () => {
231218
this.logger.info(`Handling ListTools request`);
232219
const tools = [
233-
{
234-
name: "set_env_var",
235-
title: "Set environment variable",
236-
description:
237-
"Set a YepCode environment variable to be available for future code executions",
238-
inputSchema: zodToJsonSchema(SetEnvVarSchema),
239-
},
240-
{
241-
name: "remove_env_var",
242-
title: "Remove environment variable",
243-
description: "Remove a YepCode environment variable",
244-
inputSchema: zodToJsonSchema(RemoveEnvVarSchema),
245-
},
246-
{
247-
name: "get_execution",
248-
title: "Get process execution",
249-
description:
250-
"Get the status, result, logs, timeline, etc. of a YepCode execution",
251-
inputSchema: zodToJsonSchema(GetExecutionSchema),
252-
},
220+
...envVarsToolDefinitions,
253221
...storageToolDefinitions,
222+
...getExecutionToolDefinitions,
254223
];
255224

256225
if (!this.disableRunCodeTool) {
257226
const envVars = await this.yepCodeEnv.getEnvVars();
258-
const codingRules = await this.getCodingRules();
259-
tools.push({
260-
name: "run_code",
261-
title:
262-
"Execute LLM-generated code in YepCode’s remote and secure sandboxes",
263-
description: `This tool is ideal when your AI agent needs to handle tasks that don’t have a predefined tool available — but could be solved by writing and running a custom script.
264-
265-
It supports JavaScript and Python, both with external dependencies (NPM or PyPI), so it’s perfect for:
266-
* Complex data transformations
267-
* API calls to services not yet integrated
268-
* Custom logic implementations
269-
* One-off utility scripts
270-
* To use files as input, first upload them to YepCode Storage using the upload storage MCP tools. Then, access them in your code using the \`yepcode.storage\` helper methods to download the files.
271-
* To generate and output files, create them in the local execution storage, then upload them to YepCode Storage using the \`yepcode.storage\` helpers. Once uploaded, you can download them using the download storage MCP tool.
272-
273-
Tip: First try to find a tool that matches your task, but if not available, try generating the code and running it here.`,
274-
inputSchema: zodToJsonSchema(
275-
buildRunCodeSchema(
276-
envVars.map((envVar) => envVar.key),
277-
codingRules
278-
)
279-
),
280-
});
227+
tools.push(...(await runCodeToolDefinitions(envVars)));
281228
}
282229

283230
let page = 0;
@@ -364,7 +311,7 @@ Tip: First try to find a tool that matches your task, but if not available, try
364311
}
365312

366313
switch (request.params.name) {
367-
case "run_code":
314+
case runCodeToolNames.runCode:
368315
if (this.disableRunCodeTool) {
369316
this.logger.error("Run code tool is disabled");
370317
throw new McpError(
@@ -415,7 +362,7 @@ Tip: First try to find a tool that matches your task, but if not available, try
415362
}
416363
);
417364

418-
case "set_env_var":
365+
case envVarsToolNames.set:
419366
return this.handleToolRequest(
420367
SetEnvVarSchema,
421368
request,
@@ -429,7 +376,7 @@ Tip: First try to find a tool that matches your task, but if not available, try
429376
}
430377
);
431378

432-
case "remove_env_var":
379+
case envVarsToolNames.remove:
433380
return this.handleToolRequest(
434381
RemoveEnvVarSchema,
435382
request,
@@ -440,7 +387,7 @@ Tip: First try to find a tool that matches your task, but if not available, try
440387
}
441388
);
442389

443-
case "get_execution":
390+
case getExecutionToolNames.getExecution:
444391
return this.handleToolRequest(
445392
GetExecutionSchema,
446393
request,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { z } from "zod";
2+
import { zodToJsonSchema } from "zod-to-json-schema";
3+
4+
export const envVarsToolNames = {
5+
set: "set_env_var",
6+
remove: "remove_env_var",
7+
};
8+
9+
export const EnvVarKeySchema = z
10+
.string()
11+
.min(1)
12+
.max(255)
13+
.regex(/^[a-zA-Z][a-zA-Z0-9_]*$/);
14+
15+
export const SetEnvVarSchema = z.object({
16+
key: EnvVarKeySchema,
17+
value: z.string(),
18+
isSensitive: z.boolean().optional().default(true),
19+
});
20+
21+
export const RemoveEnvVarSchema = z.object({
22+
key: EnvVarKeySchema,
23+
});
24+
25+
export type SetEnvVarRequestSchema = z.infer<typeof SetEnvVarSchema>;
26+
export type RemoveEnvVarRequestSchema = z.infer<typeof RemoveEnvVarSchema>;
27+
28+
export interface EnvVarResultSchema {
29+
error?: string;
30+
}
31+
32+
export const envVarsToolDefinitions = [
33+
{
34+
name: envVarsToolNames.set,
35+
title: "Set environment variable",
36+
description:
37+
"Set a YepCode environment variable to be available for future code executions",
38+
inputSchema: zodToJsonSchema(SetEnvVarSchema),
39+
},
40+
{
41+
name: envVarsToolNames.remove,
42+
title: "Remove environment variable",
43+
description: "Remove a YepCode environment variable",
44+
inputSchema: zodToJsonSchema(RemoveEnvVarSchema),
45+
},
46+
];
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { z } from "zod";
2+
import { zodToJsonSchema } from "zod-to-json-schema";
3+
4+
export const getExecutionToolNames = {
5+
getExecution: "get_execution",
6+
};
7+
8+
export const GetExecutionSchema = z.object({
9+
executionId: z.string(),
10+
});
11+
12+
export const getExecutionToolDefinitions = [
13+
{
14+
name: getExecutionToolNames.getExecution,
15+
title: "Get process execution",
16+
description:
17+
"Get the status, result, logs, timeline, etc. of a YepCode execution",
18+
inputSchema: zodToJsonSchema(GetExecutionSchema),
19+
},
20+
];
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import { EnvVar } from "@yepcode/run";
2+
import { z } from "zod";
3+
import { zodToJsonSchema } from "zod-to-json-schema";
4+
5+
export const runCodeToolNames = {
6+
runCode: "run_code",
7+
};
8+
9+
export const LogSchema = z.object({
10+
timestamp: z.string(),
11+
level: z.string(),
12+
message: z.string(),
13+
});
14+
15+
export const RunCodeOptionsSchema = z.object({
16+
language: z
17+
.string()
18+
.optional()
19+
.describe(
20+
"The language to be used to run the code. We support javascript or python."
21+
),
22+
comment: z.string().optional(),
23+
settings: z.record(z.unknown()).optional(),
24+
});
25+
26+
export const getCodingRules = async (): Promise<string> => {
27+
try {
28+
let rulesMdFile = await fetch(
29+
"https://yepcode.io/docs/yepcode-coding-rules.md"
30+
).then((res) => res.text());
31+
rulesMdFile = rulesMdFile.substring(
32+
rulesMdFile.indexOf("## General Rules")
33+
);
34+
rulesMdFile = rulesMdFile.replace(
35+
/(\[Section titled .*\]\(#.*\)\n)/g,
36+
""
37+
);
38+
39+
return `Here you can find the general rules for YepCode coding:
40+
41+
${rulesMdFile}`;
42+
} catch (error) {
43+
return "";
44+
}
45+
};
46+
47+
export const buildRunCodeSchema = (envVars: string[], codingRules: string) => {
48+
return z.object({
49+
code: z.string().describe(`${codingRules}
50+
51+
${
52+
envVars &&
53+
envVars.length > 0 &&
54+
`## YepCode Environment Variables
55+
56+
You may use the following environment variables already set in the execution context: ${envVars.join(
57+
", "
58+
)}.`
59+
}`),
60+
options: RunCodeOptionsSchema,
61+
});
62+
};
63+
64+
export const RunCodeSchema = buildRunCodeSchema([], "");
65+
66+
export type RunCodeRequestSchema = z.infer<typeof RunCodeSchema>;
67+
68+
export interface RunCodeResultSchema {
69+
returnValue?: unknown;
70+
logs: Array<typeof LogSchema>;
71+
error?: string;
72+
}
73+
74+
export const RunProcessSchema = z.object({
75+
parameters: z.any().optional(),
76+
options: z
77+
.object({
78+
tag: z
79+
.string()
80+
.optional()
81+
.describe(
82+
"The process version to be executed. You may provide a specific version if user asks explicity for a process version."
83+
),
84+
comment: z
85+
.string()
86+
.optional()
87+
.describe(
88+
"A comment to be added to the execution. You may provide some context about the execution."
89+
),
90+
})
91+
.optional(),
92+
synchronousExecution: z
93+
.boolean()
94+
.optional()
95+
.default(true)
96+
.describe(
97+
"Whether the execution should be synchronous or not. If true, the execution will be synchronous and the execution result will be returned immediately. If false, the execution will be asynchronous and you should use the execution id to get the result later."
98+
),
99+
});
100+
101+
export const ExecutionResultSchema = z.object({
102+
executionId: z.string(),
103+
logs: z.array(LogSchema),
104+
processId: z.string(),
105+
status: z.string(),
106+
timeline: z.array(z.any()),
107+
returnValue: z.any().optional(),
108+
error: z.string().optional(),
109+
});
110+
111+
export type ExecutionResultSchema = z.infer<typeof ExecutionResultSchema>;
112+
113+
export const runCodeToolDefinitions = async (envVars: EnvVar[]) => {
114+
const codingRules = await getCodingRules();
115+
return [
116+
{
117+
name: runCodeToolNames.runCode,
118+
title:
119+
"Execute LLM-generated code in YepCode’s remote and secure sandboxes",
120+
description: `This tool is ideal when your AI agent needs to handle tasks that don’t have a predefined tool available — but could be solved by writing and running a custom script.
121+
122+
It supports JavaScript and Python, both with external dependencies (NPM or PyPI), so it’s perfect for:
123+
* Complex data transformations
124+
* API calls to services not yet integrated
125+
* Custom logic implementations
126+
* One-off utility scripts
127+
* To use files as input, first upload them to YepCode Storage using the upload storage MCP tools. Then, access them in your code using the \`yepcode.storage\` helper methods to download the files.
128+
* To generate and output files, create them in the local execution storage, then upload them to YepCode Storage using the \`yepcode.storage\` helpers. Once uploaded, you can download them using the download storage MCP tool.
129+
130+
Tip: First try to find a tool that matches your task, but if not available, try generating the code and running it here.`,
131+
inputSchema: zodToJsonSchema(
132+
buildRunCodeSchema(
133+
envVars.map((envVar) => envVar.key),
134+
codingRules
135+
)
136+
),
137+
},
138+
];
139+
};

0 commit comments

Comments
 (0)