File size: 3,804 Bytes
67c6e06
0c91a71
67c6e06
 
 
 
 
 
 
 
 
bb25920
0c91a71
 
bb25920
 
0c91a71
 
 
 
 
 
 
 
 
 
bb25920
 
 
 
 
67c6e06
0c91a71
 
 
 
 
67c6e06
0c91a71
 
bb25920
0c91a71
 
 
3254fc3
0c91a71
 
 
 
 
 
 
 
 
 
 
 
bb25920
0c91a71
 
 
 
67c6e06
 
3254fc3
0c91a71
 
 
 
 
 
 
 
 
 
bb25920
0c91a71
3254fc3
0c91a71
 
 
 
3254fc3
0c91a71
 
 
 
 
 
67c6e06
 
 
 
0c91a71
67c6e06
0c91a71
67c6e06
0c91a71
67c6e06
 
 
 
 
 
 
 
 
 
0c91a71
 
 
 
bb25920
0c91a71
 
 
 
bb25920
 
 
 
 
 
 
67c6e06
0c91a71
 
 
bb25920
0c91a71
bb25920
0c91a71
 
 
 
67c6e06
bb25920
 
 
 
 
 
 
67c6e06
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// import Sandbox from "@e2b/code-interpreter";
import { Daytona, Sandbox } from "@daytonaio/sdk";

export const startMcpSandbox = async ({
  cmd,
  envs = {},
}: {
  cmd: string
  envs?: Record<string, string>
}) => {
  console.log("Creating sandbox...");

  try {
    const daytona = new Daytona();
    const sandbox = await daytona.create(
      {
      resources: {
        cpu: 2,
        memory: 4,
        disk: 5,
      },
      public: true,
      autoStopInterval: 0,
      envVars: {
        ...envs,
      },
    },
      {
        timeout: 0,
      }
    );

    const host = await sandbox.getPreviewLink(3000);
    const url = host.url;
    const token = host.token;
    console.log("url", url);
    console.log("token", token);

    const sessionId = Math.random().toString(36).substring(2, 30);
    await sandbox.process.createSession(sessionId);

    // Handle Python package installation if command is a Python command
    const isPythonCommand = cmd.startsWith('python') || cmd.startsWith('python3');
    let installResult = null;

    if (isPythonCommand) {
      const packageName = cmd.split("-m ")[1]?.split(" ")[0] || "";
      if (packageName) {
        console.log(`Installing Python package: ${packageName}`);
        installResult = await sandbox.process.executeSessionCommand(
          sessionId,
          {
            command: `pip install ${packageName}`,
            runAsync: true,
          },
          1000 * 300 // 5 minutes
        );

        console.log("install result", installResult.output);
        if (installResult.exitCode) {
          console.error(`Failed to install package ${packageName}. Exit code: ${installResult.exitCode}`);
        }
      }
    }

    console.log("Starting mcp server...");
    // Run the MCP server using supergateway
    const mcpServer = await sandbox.process.executeSessionCommand(
      sessionId,
      {
        command: `npx -y supergateway --base-url ${url} --header "x-daytona-preview-token: ${token}" --port 3000 --cors --stdio "${cmd}"`,
        runAsync: true,
      },
      0
    );

    console.log("mcp server result", mcpServer.output);

    if (mcpServer.exitCode) {
      console.error("Failed to start mcp server. Exit code:", mcpServer.exitCode);
      throw new Error(`MCP server failed to start with exit code ${mcpServer.exitCode}`);
    }

    console.log("MCP server started at:", url + "/sse");
    return new McpSandbox(sandbox, sessionId);
  } catch (error) {
    console.error("Error starting MCP sandbox:", error);
    throw error;
  }
}

class McpSandbox {
  public sandbox: Sandbox;
  private sessionId?: string;

  constructor(sandbox: Sandbox, sessionId?: string) {
    this.sandbox = sandbox;
    this.sessionId = sessionId;
  }

  async getUrl(): Promise<string> {
    if (!this.sandbox) {
      throw new Error("Sandbox not initialized");
    }
    const host = await this.sandbox.getPreviewLink(3000);
    return `${host.url}/sse`;
  }

  async getSessionInfo(): Promise<any> {
    if (!this.sandbox || !this.sessionId) {
      throw new Error("Sandbox or session not initialized");
    }

    const session = await this.sandbox.process.getSession(this.sessionId);
    return session;
  }

  async start(): Promise<void> {
    if (!this.sandbox) {
      throw new Error("Sandbox not initialized");
    }
    await this.sandbox.start();
  }

  async stop(): Promise<void> {
    if (!this.sandbox) {
      throw new Error("Sandbox not initialized");
    }

    try {
      await this.sandbox.stop();
    } catch (error) {
      console.error("Error stopping sandbox:", error);
      throw error;
    }
  }

  async delete(): Promise<void> {
    if (!this.sandbox) {
      throw new Error("Sandbox not initialized");
    }
    await this.sandbox.delete();
  }
}

export type { McpSandbox };