Skip to content

Commit c39e0b6

Browse files
feat: sandbox tools (#15)
* feat: add sandbox MCP tools * feat: add sandbox disk and network tools
1 parent 3a7994f commit c39e0b6

40 files changed

Lines changed: 1298 additions & 3 deletions

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ port: 8080
151151
base_url: https://your-domain.com
152152
authorization_server_url: https://your-auth-server.com
153153
api_base_url: https://api.createos.nodeops.network
154+
sandbox_api_base_url: https://your-fc-control-api.example.com
154155
transport: http # "http" or "stdio"
155156
log_level: debug
156157

@@ -220,6 +221,9 @@ The server exposes **85+ tools** organized into the following categories:
220221
| **GitHub** | `InstallGithubApp`, `ListConnectedGithubAccounts`, `ListGithubRepositories`, `ListGithubRepositoryBranches`, `GetGithubRepositoryContent` | GitHub integration for repo-based deployments |
221222
| **Account** | `GetCurrentUser`, `GetQuotas`, `GetSupportedProjectTypes` | User info, quotas, and platform capabilities |
222223
| **Transfers** | `TransferProject`, `GetProjectTransferUri`, `ListProjectTransferHistory` | Transfer project ownership between accounts |
224+
| **Sandboxes** | `CreateSandbox`, `UpdateSandbox`, `ExecSandbox`, `DeleteSandbox` | Create, update, execute commands in, and destroy sandbox VMs |
225+
| **Sandbox Disks** | `CreateDisk`, `ListDisks`, `GetDisk`, `DeleteDisk`, `AttachSandboxDisk`, `DetachSandboxDisk`, `ListSandboxDisks` | Register S3 disks and attach them to sandboxes |
226+
| **Sandbox Networks** | `CreateNetwork`, `ListNetworks`, `GetNetwork`, `DeleteNetwork`, `AttachSandboxNetwork`, `DetachSandboxNetwork` | Create private sandbox networks and manage membership |
223227

224228
---
225229

config-files/config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ port: 8080
22
base_url:
33
authorization_server_url:
44
api_base_url:
5+
sandbox_api_base_url:
56
transport: http
67
log_level: debug
78

config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type Config struct {
1212
BaseURL string `yaml:"base_url"`
1313
AuthorizationServerUrl string `yaml:"authorization_server_url"`
1414
APIBaseUrl string `yaml:"api_base_url"`
15+
SandboxAPIBaseUrl string `yaml:"sandbox_api_base_url"`
1516
Transport string `yaml:"transport"`
1617
LogLevel string `yaml:"log_level"`
1718

handlers/AttachSandboxDisk.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
mcputils "github.com/NodeOps-app/createos-mcp/helpers"
8+
"github.com/mark3labs/mcp-go/mcp"
9+
)
10+
11+
type AttachSandboxDiskParams struct {
12+
ID string `json:"id"`
13+
Body map[string]interface{} `json:"body"`
14+
}
15+
16+
func AttachSandboxDiskHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
17+
authInfo, args, err := handleRequest(ctx, request)
18+
if err != nil {
19+
return nil, err
20+
}
21+
22+
params, err := mcputils.ParamsParser[AttachSandboxDiskParams](args)
23+
if err != nil {
24+
return nil, fmt.Errorf("failed to parse parameters: %w", err)
25+
}
26+
27+
return makeSandboxPostRequest(fmt.Sprintf("/v1/sandboxes/%s/disks", params.ID), params.Body, authInfo)
28+
}

handlers/AttachSandboxNetwork.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
mcputils "github.com/NodeOps-app/createos-mcp/helpers"
8+
"github.com/mark3labs/mcp-go/mcp"
9+
)
10+
11+
type AttachSandboxNetworkParams struct {
12+
ID string `json:"id"`
13+
Body map[string]interface{} `json:"body"`
14+
}
15+
16+
func AttachSandboxNetworkHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
17+
authInfo, args, err := handleRequest(ctx, request)
18+
if err != nil {
19+
return nil, err
20+
}
21+
22+
params, err := mcputils.ParamsParser[AttachSandboxNetworkParams](args)
23+
if err != nil {
24+
return nil, fmt.Errorf("failed to parse parameters: %w", err)
25+
}
26+
27+
return makeSandboxPostRequest(fmt.Sprintf("/v1/sandboxes/%s/networks", params.ID), params.Body, authInfo)
28+
}

handlers/CreateDisk.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
mcputils "github.com/NodeOps-app/createos-mcp/helpers"
8+
"github.com/mark3labs/mcp-go/mcp"
9+
)
10+
11+
type CreateDiskParams struct {
12+
Body map[string]interface{} `json:"body"`
13+
}
14+
15+
func CreateDiskHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
16+
authInfo, args, err := handleRequest(ctx, request)
17+
if err != nil {
18+
return nil, err
19+
}
20+
21+
params, err := mcputils.ParamsParser[CreateDiskParams](args)
22+
if err != nil {
23+
return nil, fmt.Errorf("failed to parse parameters: %w", err)
24+
}
25+
26+
return makeSandboxPostRequest("/v1/disks", params.Body, authInfo)
27+
}

handlers/CreateNetwork.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
mcputils "github.com/NodeOps-app/createos-mcp/helpers"
8+
"github.com/mark3labs/mcp-go/mcp"
9+
)
10+
11+
type CreateNetworkParams struct {
12+
Body map[string]interface{} `json:"body"`
13+
}
14+
15+
func CreateNetworkHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
16+
authInfo, args, err := handleRequest(ctx, request)
17+
if err != nil {
18+
return nil, err
19+
}
20+
21+
params, err := mcputils.ParamsParser[CreateNetworkParams](args)
22+
if err != nil {
23+
return nil, fmt.Errorf("failed to parse parameters: %w", err)
24+
}
25+
26+
return makeSandboxPostRequest("/v1/networks", params.Body, authInfo)
27+
}

handlers/CreateSandbox.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
mcputils "github.com/NodeOps-app/createos-mcp/helpers"
8+
"github.com/mark3labs/mcp-go/mcp"
9+
)
10+
11+
type CreateSandboxParams struct {
12+
Body map[string]interface{} `json:"body"`
13+
}
14+
15+
func CreateSandboxHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
16+
authInfo, args, err := handleRequest(ctx, request)
17+
if err != nil {
18+
return nil, err
19+
}
20+
21+
params, err := mcputils.ParamsParser[CreateSandboxParams](args)
22+
if err != nil {
23+
return nil, fmt.Errorf("failed to parse parameters: %w", err)
24+
}
25+
26+
return makeSandboxPostRequest("/v1/sandboxes", params.Body, authInfo)
27+
}

handlers/DeleteDisk.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
mcputils "github.com/NodeOps-app/createos-mcp/helpers"
8+
"github.com/mark3labs/mcp-go/mcp"
9+
)
10+
11+
type DeleteDiskParams struct {
12+
IDOrName string `json:"id_or_name"`
13+
}
14+
15+
func DeleteDiskHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
16+
authInfo, args, err := handleRequest(ctx, request)
17+
if err != nil {
18+
return nil, err
19+
}
20+
21+
params, err := mcputils.ParamsParser[DeleteDiskParams](args)
22+
if err != nil {
23+
return nil, fmt.Errorf("failed to parse parameters: %w", err)
24+
}
25+
26+
return makeSandboxDeleteRequest(fmt.Sprintf("/v1/disks/%s", params.IDOrName), authInfo)
27+
}

handlers/DeleteNetwork.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package handler
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
mcputils "github.com/NodeOps-app/createos-mcp/helpers"
8+
"github.com/mark3labs/mcp-go/mcp"
9+
)
10+
11+
type DeleteNetworkParams struct {
12+
ID string `json:"id"`
13+
}
14+
15+
func DeleteNetworkHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
16+
authInfo, args, err := handleRequest(ctx, request)
17+
if err != nil {
18+
return nil, err
19+
}
20+
21+
params, err := mcputils.ParamsParser[DeleteNetworkParams](args)
22+
if err != nil {
23+
return nil, fmt.Errorf("failed to parse parameters: %w", err)
24+
}
25+
26+
return makeSandboxDeleteRequest(fmt.Sprintf("/v1/networks/%s", params.ID), authInfo)
27+
}

0 commit comments

Comments
 (0)