Skip to content

Commit e7480c8

Browse files
committed
feat(cli): update version and enhance server configuration with code execution support
1 parent 484aab7 commit e7480c8

File tree

6 files changed

+104
-12
lines changed

6 files changed

+104
-12
lines changed

deno.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/deno.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@mcpc/cli",
3-
"version": "0.1.18",
3+
"version": "0.1.19",
44
"repository": {
55
"type": "git",
66
"url": "git+https://github.com/mcpc-tech/mcpc.git"
@@ -13,7 +13,7 @@
1313
},
1414
"imports": {
1515
"@mcpc-tech/plugin-code-execution": "npm:@mcpc-tech/plugin-code-execution@^0.0.6",
16-
"@mcpc/core": "jsr:@mcpc/core@^0.3.6",
16+
"@mcpc/core": "jsr:@mcpc/core@^0.3.7",
1717
"@mcpc/utils": "jsr:@mcpc/utils@^0.2.2",
1818
"@modelcontextprotocol/sdk": "npm:@modelcontextprotocol/sdk@^1.8.0",
1919
"@mcpc-tech/ripgrep-napi": "npm:@mcpc-tech/ripgrep-napi@^0.0.4",

packages/cli/src/app.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@ import { mcpc } from "@mcpc/core";
44
import { createLargeResultPlugin } from "@mcpc/core/plugins/large-result";
55
import type { ComposableMCPServer, ComposeDefinition } from "@mcpc/core";
66
import type { MCPCConfig } from "./config/loader.ts";
7+
import { codeExecutionPlugin } from "@mcpc-tech/plugin-code-execution";
78

89
export const createServer = async (
910
config?: MCPCConfig,
1011
): Promise<ComposableMCPServer> => {
1112
// Use provided config or fall back to default example config
1213
const serverConfig = config || {
13-
name: "large-result-plugin-example",
14+
name: "mcpc-server",
1415
version: "0.1.0",
1516
agents: [
1617
{
1718
name: null,
1819
description: "",
19-
plugins: [createLargeResultPlugin({})],
20+
plugins: [createLargeResultPlugin({}), codeExecutionPlugin()],
21+
options: {
22+
mode: "code_execution",
23+
},
2024
},
2125
] as ComposeDefinition[],
2226
};
@@ -39,11 +43,11 @@ export const createServer = async (
3943
);
4044
};
4145

42-
export const createApp = (): OpenAPIHono => {
46+
export const createApp = (config?: MCPCConfig): OpenAPIHono => {
4347
const app = new OpenAPIHono();
4448

45-
// Register routes
46-
registerAgent(app);
49+
// Register routes with config
50+
registerAgent(app, config);
4751

4852
return app;
4953
};

packages/cli/src/controllers/register.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import type { OpenAPIHono } from "@hono/zod-openapi";
22
import { messageHandler } from "./messages.controller.ts";
33
import { sseHandler } from "./sse.controller.ts";
44
import { coreHandler } from "./core.controller.ts";
5+
import { streamableHttpHandler } from "./streamable-http.controller.ts";
6+
import type { MCPCConfig } from "../config/loader.ts";
57

6-
export const registerAgent = (app: OpenAPIHono) => {
8+
export const registerAgent = (app: OpenAPIHono, config?: MCPCConfig) => {
79
messageHandler(app);
810
sseHandler(app);
911
coreHandler(app);
12+
streamableHttpHandler(app, config);
1013
};
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import type { OpenAPIHono } from "@hono/zod-openapi";
2+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3+
import { createServer } from "../app.ts";
4+
import { loadConfig } from "../config/loader.ts";
5+
import type { MCPCConfig } from "../config/loader.ts";
6+
7+
export const streamableHttpHandler = (
8+
app: OpenAPIHono,
9+
providedConfig?: MCPCConfig,
10+
) => {
11+
app.post("/mcp", async (c) => {
12+
try {
13+
// Use provided config or load from environment/file
14+
const config = providedConfig || await loadConfig();
15+
const server = await createServer(config ?? undefined);
16+
17+
const body = await c.req.json();
18+
19+
// Create a new transport for each request (stateless mode)
20+
const transport = new StreamableHTTPServerTransport({
21+
sessionIdGenerator: undefined,
22+
enableJsonResponse: true,
23+
});
24+
25+
// Handle cleanup on request close
26+
c.req.raw.signal?.addEventListener("abort", () => {
27+
transport.close();
28+
});
29+
30+
// Connect server to transport
31+
await server.connect(transport);
32+
33+
// Create adapter for Web API Request/Response
34+
const request = c.req.raw;
35+
const { writable } = new TransformStream();
36+
const writer = writable.getWriter();
37+
38+
// Capture response
39+
let captured: any = null;
40+
const mockResponse = {
41+
statusCode: 200,
42+
setHeader: () => {},
43+
writeHead: () => {},
44+
write: (chunk: any) => {
45+
try {
46+
const text = typeof chunk === "string" ? chunk : chunk.toString();
47+
captured = JSON.parse(text);
48+
} catch {
49+
// ignore parse errors
50+
}
51+
},
52+
end: () => {
53+
writer.close();
54+
},
55+
} as any;
56+
57+
// Handle the request through transport
58+
await transport.handleRequest(request as any, mockResponse, body);
59+
60+
// Close transport after handling
61+
transport.close();
62+
63+
// Return captured response
64+
if (captured) {
65+
return c.json(captured);
66+
}
67+
68+
return c.json({ error: "No response captured" }, 500);
69+
} catch (error) {
70+
console.error("Streamable HTTP error:", error);
71+
return c.json(
72+
{
73+
error: error instanceof Error ? error.message : String(error),
74+
},
75+
500,
76+
);
77+
}
78+
});
79+
};

packages/cli/src/server.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { loadConfig } from "./config/loader.ts";
3232
import process from "node:process";
3333
import { createCodeExecutionPlugin } from "@mcpc-tech/plugin-code-execution";
3434

35-
const port = Number(process.env.PORT || "9000");
35+
const port = Number(process.env.PORT || "3002");
3636
const hostname = "0.0.0.0";
3737

3838
// Load configuration from environment or file
@@ -43,7 +43,13 @@ config?.agents.forEach((agent) => {
4343
if (agent.plugins?.length ?? 0 === 0) {
4444
agent.plugins = [];
4545
}
46-
agent.plugins?.push(createCodeExecutionPlugin());
46+
agent.plugins?.push(
47+
createCodeExecutionPlugin({
48+
sandbox: {
49+
timeout: 300_000,
50+
},
51+
}),
52+
);
4753
});
4854

4955
if (config) {
@@ -54,7 +60,7 @@ if (config) {
5460

5561
const app = new OpenAPIHono();
5662

57-
app.route("core", createApp());
63+
app.route("mcp", createApp(config || undefined));
5864

5965
Deno.serve(
6066
{

0 commit comments

Comments
 (0)