Skip to content

Commit 81b67b9

Browse files
committed
added user add method
1 parent 4b06338 commit 81b67b9

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

main.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,36 @@ import (
1414
"github.com/modelcontextprotocol/go-sdk/mcp"
1515
)
1616

17+
// Input struct for the AddUser tool.
18+
type AddUserInput struct {
19+
Username string `json:"username" jsonschema:"the username of the new account"`
20+
BaseDir string `json:"base_dir,omitempty" jsonschema:"the base directory for the home directory of the new account"`
21+
Comment string `json:"comment,omitempty" jsonschema:"the GECOS field of the new account"`
22+
HomeDir string `json:"home_dir,omitempty" jsonschema:"the home directory of the new account"`
23+
ExpireDate string `json:"expire_date,omitempty" jsonschema:"the expiration date of the new account"`
24+
Inactive int `json:"inactive,omitempty" jsonschema:"the password inactivity period of the new account"`
25+
Gid string `json:"gid,omitempty" jsonschema:"the name or ID of the primary group of the new account"`
26+
Groups []string `json:"groups,omitempty" jsonschema:"the list of supplementary groups of the new account"`
27+
SkelDir string `json:"skel_dir,omitempty" jsonschema:"the alternative skeleton directory"`
28+
CreateHome bool `json:"create_home,omitempty" jsonschema:"create the user's home directory"`
29+
NoCreateHome bool `json:"no_create_home,omitempty" jsonschema:"do not create the user's home directory"`
30+
NoUserGroup bool `json:"no_user_group,omitempty" jsonschema:"do not create a group with the same name as the user"`
31+
NonUnique bool `json:"non_unique,omitempty" jsonschema:"allow to create users with duplicate (non-unique) UID"`
32+
Password string `json:"password,omitempty" jsonschema:"the encrypted password of the new account"`
33+
System bool `json:"system,omitempty" jsonschema:"create a system account"`
34+
Shell string `json:"shell,omitempty" jsonschema:"the login shell of the new account"`
35+
Uid int `json:"uid,omitempty" jsonschema:"the user ID of the new account"`
36+
UserGroup bool `json:"user_group,omitempty" jsonschema:"create a group with the same name as the user"`
37+
SelinuxUser string `json:"selinux_user,omitempty" jsonschema:"the specific SEUSER for the SELinux user mapping"`
38+
SelinuxRange string `json:"selinux_range,omitempty" jsonschema:"the specific MLS range for the SELinux user mapping"`
39+
}
40+
41+
// Output struct for the AddUser tool.
42+
type AddUserOutput struct {
43+
Success bool `json:"success" jsonschema:"whether the user was added successfully"`
44+
Message string `json:"message" jsonschema:"a message indicating the result of the operation"`
45+
}
46+
1747
// User struct represents a single user account.
1848
type User struct {
1949
Username string `json:"username"`
@@ -170,6 +200,78 @@ func getGroups() ([]Group, error) {
170200
return groups, nil
171201
}
172202

203+
func AddUser(ctx context.Context, req *mcp.CallToolRequest, input AddUserInput) (
204+
*mcp.CallToolResult, AddUserOutput, error,
205+
) {
206+
slog.Info("AddUser tool called")
207+
args := []string{}
208+
if input.BaseDir != "" {
209+
args = append(args, "-b", input.BaseDir)
210+
}
211+
if input.Comment != "" {
212+
args = append(args, "-c", input.Comment)
213+
}
214+
if input.HomeDir != "" {
215+
args = append(args, "-d", input.HomeDir)
216+
}
217+
if input.ExpireDate != "" {
218+
args = append(args, "-e", input.ExpireDate)
219+
}
220+
if input.Inactive != 0 {
221+
args = append(args, "-f", strconv.Itoa(input.Inactive))
222+
}
223+
if input.Gid != "" {
224+
args = append(args, "-g", input.Gid)
225+
}
226+
if len(input.Groups) > 0 {
227+
args = append(args, "-G", strings.Join(input.Groups, ","))
228+
}
229+
if input.SkelDir != "" {
230+
args = append(args, "-k", input.SkelDir)
231+
}
232+
if input.CreateHome {
233+
args = append(args, "-m")
234+
}
235+
if input.NoCreateHome {
236+
args = append(args, "-M")
237+
}
238+
if input.NoUserGroup {
239+
args = append(args, "-N")
240+
}
241+
if input.NonUnique {
242+
args = append(args, "-o")
243+
}
244+
if input.Password != "" {
245+
args = append(args, "-p", input.Password)
246+
}
247+
if input.System {
248+
args = append(args, "-r")
249+
}
250+
if input.Shell != "" {
251+
args = append(args, "-s", input.Shell)
252+
}
253+
if input.Uid != 0 {
254+
args = append(args, "-u", strconv.Itoa(input.Uid))
255+
}
256+
if input.UserGroup {
257+
args = append(args, "-U")
258+
}
259+
if input.SelinuxUser != "" {
260+
args = append(args, "-Z", input.SelinuxUser)
261+
}
262+
args = append(args, input.Username)
263+
264+
cmd := exec.Command("useradd", args...)
265+
var out bytes.Buffer
266+
cmd.Stdout = &out
267+
cmd.Stderr = &out
268+
err := cmd.Run()
269+
if err != nil {
270+
return nil, AddUserOutput{Success: false, Message: out.String()}, err
271+
}
272+
return nil, AddUserOutput{Success: true, Message: out.String()}, nil
273+
}
274+
173275
func main() {
174276
listenAddr := flag.String("http", "", "address for http transport, defaults to stdio")
175277
flag.Parse()
@@ -179,6 +281,10 @@ func main() {
179281
Name: "ListUsers",
180282
Description: "A tool to list the users on the system",
181283
}, ListUsers)
284+
mcp.AddTool(server, &mcp.Tool{
285+
Name: "AddUser",
286+
Description: "A tool to add a new user to the system",
287+
}, AddUser)
182288

183289
if *listenAddr == "" {
184290
// Run the server on the stdio transport.

0 commit comments

Comments
 (0)